Open phranck opened 5 years ago
Hi @phranck,
This should be possible with func alongTrackDistance(toPath path: (start: Coordinate, end: Coordinate)) -> Distance
.
However, This function returns the distance from start
on your path. You could then calculate the initial bearing for your path and travel the calculated distance with this bearing from your start point to get a point on your path. Some sample code:
let p1, p2, p3: Coordinate
let distance = p3.alongTrackDistance(toPath: (start: p1, end: p2))
let bearing = p1.bearing(to: p2)
let pointOnPath = destination(with: distance, bearing: bearing)
@florianreinhart Yeah, that was my initial thought, too. However, this is more an approximation method than a direct calculation. (-;
It should be quite accurate on a sphere (which is the model that is used for the calculation).
You could try doing the coordinate calculation with MKMapPoint
s and calculate the "Lotfußpunkt".
Yeah, using MKMapPoint
's was my first attempt. Unfortunately, MapKit
fails when it comes to calculation around the anti meridian. It can't deal with that and provides one with weird results!
Anyways, I think I'll go with the approximation method. (-;
should be quite accurate on a sphere
This is key! So, while handling with MKMapPoint
's which represents points on a flattened earth with parallel longitudes I think I can't use your functions, can I? 🤔
Oh yeah! You need to convert your MKMapPoint
s to CLLocationCoordinate2D
. The Coordinate
type of this library is equivalent to CLLocationCoordinate2D
.
Just to illustrate - This is the code I use for getting the perpendicular point. As mentioned, it works very well, but for lines crossing -180/180.
private func closestPointInLine(withStartPoint p1: MKMapPoint, endPoint p2: MKMapPoint, touchPoint pt: MKMapPoint, allowedPerimeter: Double) -> MKMapPoint? {
let lineLength = distance(from: p1, to: p2)
var u = ((pt.x - p1.x) * (p2.x - p1.x)) + ((pt.y - p1.y) * (p2.y - p1.y))
u = u / pow(lineLength, 2)
if u >= 0 && u <= 1 {
let px = p1.x + u * (p2.x - p1.x)
let py = p1.y + u * (p2.y - p1.y)
let p = MKMapPoint(x: px, y: py)
let touchDistance = distance(from: pt, to: p)
if touchDistance <= allowedPerimeter {
return p
}
}
return nil
}
private func distance(from p1: MKMapPoint, to p2: MKMapPoint) -> Double {
return sqrt(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2))
}
Hey @florianreinhart!
First: Thank you very much for this great collection of useful geodesy functions!
This isn't a real issue but more a question. I'm currently struggling on calculating the perpendicular point of a line (p1, p2) and a point (p3) near the line.
Background: We are using
MKPolyLine
to draw lines on the map. The user should be able to tap (p3) on (or near to) a line segment (p1, p2). Now I need the closest point in the line (the perpendicular point) to the touch point, to show a popup with detailed informations at this line point. It should look like this:Now I'm asking myself if this is possible with your functions? Maybe I'm missing something, unfortunately I don't find a solution...
Question: Is this calculation possible with your library or is an entire new function needed to get the result?
Thanks in advance!