I have a segment defined by 2 LatLon points(A and B) and a third LatLon point (C). I need an alghorithm, formulae, or some code to find the projection point of C on the segment AB (call this point D) so that CD segment is perpendicular to AB...
i few word I've to find the minimum distance between C and AB segment or in other word the height of the triangle ABC.
I'found this question: Find the nearest point on a line and this reply: https://gis.stackexchange.com/a/39176/16839
I've translated the algorithm in Java (GeoPoint is a simple implementation LatLon class and VectorN is a class that mantain an array of doubles and implement basic vector operation like dot product, sum etc...) but it don't seems to work well...
My source for Geopoints coordinates is googleMap... so they are in WGS84 system... and this may be the source of problems... but in my debug I found that results are very inconsistent... a point that stay at 30meters is given as staying at 0.5meters and a point at 18meters is given as 3m away...
Can you help me?
public static GeoPoint GetOrthographicProjection(GeoPoint start, GeoPoint end, GeoPoint offsetpoint) {
double EarthRadius=6371;
// Start node conversion
double sLat = degToRad(start.getLat());
double sLon = degToRad(start.getLng());
double sX = EarthRadius * Math.cos(sLat) * Math.cos(sLon);
double sY = EarthRadius * Math.cos(sLat) * Math.sin(sLon);
double sZ = EarthRadius * Math.sin(sLat);
//End node conversion
double eLat = degToRad(end.getLat());
double eLon = degToRad(end.getLng());
double eX = EarthRadius * Math.cos(eLat) * Math.cos(eLon);
double eY = EarthRadius * Math.cos(eLat) * Math.sin(eLon);
double eZ = EarthRadius * Math.sin(eLat);
//Offsetpoint conversion
double oLat = degToRad(offsetpoint.getLat());
double oLon = degToRad(offsetpoint.getLng());
double oX = EarthRadius * Math.cos(oLat) * Math.cos(oLon);
double oY = EarthRadius * Math.cos(oLat) * Math.sin(oLon);
double oZ = EarthRadius * Math.sin(oLat);
// Create vectors
VectorN p1 = new VectorN(new double[] {sX,sY,sZ});
VectorN p2 = new VectorN(new double[] {eX,eY,eZ});
VectorN o = new VectorN(new double[] {oX,oY,oZ});
// Calculate
/*Vector<Double> u = p2 - p1;
Vector<Double> po = o - p1;
Vector<Double> w2 = po - (u * Vector3.DotProduct(po, u) / Math.Pow(u.Magnitude, 2));
Vector<Double> point = o - w2;*/
VectorN u = p2.minus(p1);
VectorN po = o.minus(p1);
VectorN w2 = po.minus( (u.times(po.dot(u)).times(1 / Math.pow(u.magnitude(), 2))) );
VectorN point = o.minus(w2);
// Convert to latlon
double rlat = radToDegrees(Math.asin(point.cartesian(2) / EarthRadius));
double rlon = radToDegrees(Math.atan2(point.cartesian(1), point.cartesian(0)));
return new GeoPoint(rlat, rlon);
}
Example of result: gp1= 40.8880224061686 , 17.391275949776173 gp2= 40.888020378444516 , 17.39116732031107
output point (that should stay on the segment gp1-gp2) 40.88801433354826 , 17.390843482462408
On gMaps you can see the point (gp1 and gp2 are blue, the output is the red marker... it should be between blue markers... instead is far away...) see this pic: https://i.sstatic.net/bBMd6.png