In last week’s Swift Talk we discussed the required to build a routing graph for our running trail app. To work out where the tracks overlap, we needed to calculate the closest distance from a point to a line segment.

We won’t repeat the math here, but we’ll highlight a detail of the implementation.

For testing purposes we wanted to calculate with `CGPoint`s, which makes it easy to draw the points in a view. In the final app we want to calculate with Core coordinates. It’s important to note that geographic coordinates are coordinates on a sphere, but for our use case, we’ll pretend that the earth is flat — it’s a good enough approximation for the region we’re doing our routing in.

Instead of implementing the vector operations first on `CGPoint`, and then re-writing them on `CLLocationCoordinate2D`, we decided to introduce a simple protocol:

``````protocol Vector2 {
associatedtype Component: Numeric
var x: Component { get }
var y: Component { get }
init(x: Component, y: Component)
}
``````

This protocol represents a vector with two numeric components, `x` and `y`. We’re using an associated type to specify the type of the components: in our case they can be of type `CGFLoat` (for `CGPoint`) or `CLLocationDegrees` (for `CLLocationCoordinate2D`). Since `CGPoint` already has all the protocol requirements, conforming it to `Vector2` is a one-liner:

``````extension CGPoint: Vector2 {}
``````

Now we can to define vector operations on the `Vector2` protocol, for example the dot product and vector addition:

``````extension Vector2 {
func dot(_ other: Self) -> Component {
return x * other.x + y * other.y
}

static func +(l: Self, r: Self) -> Self {
return Self(x: l.x + r.x, y: l.y + r.y)
}
}
``````

Since the operations are defined on the protocol, we get all of them for free when we conform a new type to the protocol; for instance, with `CLLocationCoordinate2D`:

``````extension CLLocationCoordinate2D: Vector2 {
var x: CLLocationDegrees { return longitude }
var y: CLLocationDegrees { return latitude }
init(x: CLLocationDegrees, y: CLLocationDegrees) {
self.init(latitude: y, longitude: x)
}
}
``````

If you’d like to learn more, the first episode in this Collection is public. To follow our progress, you can Subscribe. 🤓

Based Blockchain Network

SHARE
Previous article9 Internet of Things Predictions for 2019