8

I have a line that exists between two latlon positions, and a point on a certain latlon position. What I want to know is what the nearest point on that line is (in respect to the other point). So a latlon position on that line.

I know how to do the basic math, but I just can't get my head around the latlong calculation. Can anyone help me or give me some pointers on how to do it?

Thanks

hutsend
  • 91
  • 4

1 Answers1

1

This is the code I made using a Vector3 type. Isn't exactly spot on but close enough for further calculations:

    public static LatLon GetOrthographicProjecten(LatLon start, LatLon end, LatLon offsetpoint)
    {
        #region Start node conversion

        var sLat = DegreesToRadians(start.Lat);
        var sLon = DegreesToRadians(start.Lon);

        var sX = EarthRadius * Math.Cos(sLat) * Math.Cos(sLon);
        var sY = EarthRadius * Math.Cos(sLat) * Math.Sin(sLon);
        var sZ = EarthRadius * Math.Sin(sLat);

        #endregion

        #region End node conversion

        var eLat = DegreesToRadians(end.Lat);
        var eLon = DegreesToRadians(end.Lon);

        var eX = EarthRadius * Math.Cos(eLat) * Math.Cos(eLon);
        var eY = EarthRadius * Math.Cos(eLat) * Math.Sin(eLon);
        var eZ = EarthRadius * Math.Sin(eLat);

        #endregion

        #region Offsetpoint conversion

        var oLat = DegreesToRadians(offsetpoint.Lat);
        var oLon = DegreesToRadians(offsetpoint.Lon);

        var oX = EarthRadius * Math.Cos(oLat) * Math.Cos(oLon);
        var oY = EarthRadius * Math.Cos(oLat) * Math.Sin(oLon);
        var oZ = EarthRadius * Math.Sin(oLat);

        #endregion

        // Create vectors
        var p1 = new Vector3(sX, sY, sZ);
        var p2 = new Vector3(eX, eY, eZ);
        var o = new Vector3(oX, oY, oZ);

        // Calculate
        var u = p2 - p1;
        var po = o - p1;
        var w2 = po - (u * Vector3.DotProduct(po, u) / Math.Pow(u.Magnitude, 2));
        var point = o - w2;

        // Convert to latlon
        var rlat = RadiansToDegrees(Math.Asin(point.Z / EarthRadius));
        var rlon = RadiansToDegrees(Math.Atan2(point.Y, point.X));

        return new LatLon(rlat, rlon);
    }
hutsend
  • 91
  • 4
  • The earthradius is 6371km, at least that's what I used. RadiansToDegrees and vice verse speak for themselfs I guess.. – hutsend Nov 02 '12 at 15:32
  • How does this code ensure the projected point actually lies between the two endpoints of the segment? – whuber Jul 16 '13 at 20:41
  • You're right whuber. It doesn't. In the code I eventually used this is implemented. I'll see if I can find that snippet and post it here. – hutsend Sep 02 '13 at 17:39