> On 14. Jan 2018, at 21:12, Kelvin Ma via swift-evolution
> <[email protected]> wrote:
>
> This could work, but you’re also giving up all the nice Numeric and
> FloatingPoint conformances when you use this,, all of a sudden adding two
> angles together isn’t let γ = α + β, it’s γ = Angle.radians(α.radians +
> β.radians). just no. at the risk of blowing up the scope of this idea,
> dedicated Angle types also begs for generic trigonometric functions like
> Angle.sin(_:) and Angle.cos(_:). i proposed that a while back and even tried
> implementing it but fast trig evaluation doesn’t genericize well since it
> relies a lot on rsqrt-style magic constants
You could add those conformances back, if you wanted. Most low-level trig code
will quickly escape the wrapper once it starts using the values. Mostly I use
it as a currency type and for converting untyped angles. I think it’s a great
example of Swift’s zero-cost abstractions - we added semantic meaning (this
value isn’t just a number with a specific bit representation, it’s a number
which represents a specific kind of quantity), and encapsulated some useful
functionality, and we don't lose any performance.
I have a couple of these, such as Distance<T> and Time (wraps a TimeInterval).
This allows me to write algorithms like:
public func point(_ distance: Distance<Double>, along bearing:
Angle<Double>) -> Geo.Point
And use it like this:
let nextPlace = thisPlace.point(.kilometers(42), along: .degrees(45))
Or this:
let nextPlace = thisPlace.point(.miles(500), along: .radians(.pi/2))
And so my algorithm actually becomes quite difficult to use incorrectly. Also,
that’s why I use static constructors; similar to how lots of OptionSet types
are implemented, doing it this way lets you use an enum-like syntax to create
values, which fits Angle’s intended use as a parameter/return type.
I’m not saying this should be part of the standard library (this isn’t my
pitch), I’m just saying these kind of wrappers are useful when creating good
APIs. I think somebody was dismissing the idea of an Angle<T> type in general
before.
- Karl
>
> also, why are radians(_:) and degrees(_:) static functions? i really only use
> static constructors for initializers that have side effects
>
> On Sun, Jan 14, 2018 at 6:36 AM, Karl Wagner <[email protected]
> <mailto:[email protected]>> wrote:
>
>
>> On 14. Jan 2018, at 09:51, Taylor Swift via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> I do a lot of geometry and spherical-related work and i have never found an
>> Angle type to be worth having. Always use radians. It’s what sin() and cos()
>> take, it’s what graphics APIs like Cairo expect, it’s what graphics formats
>> like SVG use. plus,, do you *really* want to be case-branching on every
>> angle value? that really adds up when you’re converting 100,000s of lat-long
>> pairs to cartesian.
>
> You can do it without case-branching. I too have an Angle type; this is what
> I use:
>
> public struct Angle<T: FloatingPoint> {
> public var radians: T
> public var degrees: T {
> return (radians / .pi) * 180
> }
>
> public static func radians(_ rads: T) -> Angle {
> return Angle(radians: rads)
> }
> public static func degrees(_ degs: T) -> Angle {
> return Angle(radians: (degs / 180) * .pi)
> }
> }
>
> If you ask for “radians” (like most low-level trig code will), you just get
> the stored property. The conversion “overhead” is only done at construction
> time, so it makes a convenient parameter/return value.
>
> - Karl
>
>>
>> On Jan 14, 2018, at 12:04 AM, BJ Homer via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>>> An Angle type already exists in Foundation; see Measurement<UnitAngle>. You
>>> could add some convenience methods in an extension pretty easily.
>>>
>>> import Foundation
>>>
>>> typealias Angle = Measurement<UnitAngle>
>>>
>>> extension Measurement where UnitType == UnitAngle {
>>> var sine: Double {
>>> let radians = self.converted(to: .radians).value
>>> return sin(radians)
>>> }
>>>
>>> static var threeQuarterTurn: Angle {
>>> return Angle(value: 0.75, unit: .revolutions)
>>> }
>>> }
>>>
>>> let x = Angle.threeQuarterTurn
>>> x.sine // -1
>>>
>>> -BJ
>>>
>>>
>>>> On Jan 13, 2018, at 9:31 PM, Erica Sadun via swift-evolution
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>
>>>> I would like to see a full Geometry implementation but I don't think it
>>>> should be part of the standard library.
>>>>
>>>> I've kicked around some ideas here:
>>>>
>>>> * https://gist.github.com/erica/8cb4b21cf0c429828fad1d8ad459b71b
>>>> <https://gist.github.com/erica/8cb4b21cf0c429828fad1d8ad459b71b>
>>>> * https://gist.github.com/erica/ee06008202c9fed699bfa6254c42c721
>>>> <https://gist.github.com/erica/ee06008202c9fed699bfa6254c42c721>
>>>>
>>>> and
>>>>
>>>> * https://github.com/erica/SwiftGeometry
>>>> <https://github.com/erica/SwiftGeometry>
>>>>
>>>>> On Jan 13, 2018, at 7:49 PM, Jonathan Hull via swift-evolution
>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>
>>>>> Hi Evolution,
>>>>>
>>>>> I would really like to see Swift gain an Angle type in the standard
>>>>> library. Every time I have to deal with an angle in an api, I have to go
>>>>> figure out the conventions for that call. Is it in degrees? Is it in
>>>>> radians? What if it is in radians, but I want to think about it in
>>>>> degrees?
>>>>>
>>>>> I ended up writing an Angle type for my own code a few years back, and I
>>>>> have to say it is really wonderful. It has greatly simplified my
>>>>> graphics work. It takes a lot of mental load off of my brain when
>>>>> dealing with Angles.
>>>>>
>>>>> I can of course initialize it either as degrees or radians (or
>>>>> revolutions), but I can also just say things like ‘.threeQuarterTurn’,
>>>>> and then I can get the value back out in whatever format I like. There
>>>>> are also useful additions that let me normalize the angle to different
>>>>> ranges and which let me snap to the nearest multiple of an angle. Both of
>>>>> these are enormously useful for user facing features. I can also do math
>>>>> on angles in a way that makes geometric sense for angles. It is also
>>>>> really useful for interacting with CGVectors in intelligent ways.
>>>>>
>>>>> Using Doubles or CGFloats to represent angles everywhere is just
>>>>> semantically wrong IMHO, and it stops us from adding all of these
>>>>> angle-specific niceties.
>>>>>
>>>>> Happy to provide code if there is interest…
>>>>>
>>>>> Thanks,
>>>>> Jon
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> [email protected] <mailto:[email protected]>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution