transform longitude latitude into meters

2020-02-23 11:01发布

问题:

I need a function that maps gps positions to x/y values like this:

getXYpos(GeoPoint relativeNullPoint, GeoPoint p){
   deltaLatitude=p.latitude-relativeNullPoint.latitude;
   deltaLongitude=p.longitude-relativeNullPoint.longitude;
   ...
   resultX=latitude (or west to east) distance in meters from p to relativeNullPoint
   resultY=longitude (or south to north) distance in meters from p to relativeNullPoint
}

i have seen some implementations of "distance of two geoPoints" but they all just calculate the air-line distance. i think the deltaLongitude can be transformed into meters directly but the deltaLatitude depends in the Longitude. does anyone know how this problem can be solved?

回答1:

To start with, I think you have your latitude and longitude reversed. Longitude measures X, and latitude measures Y.

The latitude is easy to turn into a north-south distance. We know that 360 degrees is a full circle around the earth through the poles, and that distance is 40008000 meters. As long as you don't need to account for the errors due to the earth being not perfectly spherical, the formula is deltaLatitude * 40008000 / 360.

The tricky part is converting longitude to X, as you suspected. Since it depends on the latitude you need to decide which latitude you're going to use - you could choose the latitude of your origin, the latitude of your destination, or some arbitrary point in between. The circumference at the equator (latitude 0) is 40075160 meters. The circumference of a circle at a given latitude will be proportional to the cosine, so the formula will be deltaLongitude * 40075160 * cos(latitude) / 360.

Edit: Your comment indicates you had some trouble with the longitude formula; you might have used degrees instead of radians in the call to cos, that's a common rookie mistake. To make sure there's no ambiguity, here's working code in Python.

def asRadians(degrees):
    return degrees * pi / 180

def getXYpos(relativeNullPoint, p):
    """ Calculates X and Y distances in meters.
    """
    deltaLatitude = p.latitude - relativeNullPoint.latitude
    deltaLongitude = p.longitude - relativeNullPoint.longitude
    latitudeCircumference = 40075160 * cos(asRadians(relativeNullPoint.latitude))
    resultX = deltaLongitude * latitudeCircumference / 360
    resultY = deltaLatitude * 40008000 / 360
    return resultX, resultY

I chose to use the relativeNullPoint latitude for the X calculation. This has the benefit that if you convert multiple points with the same longitude, they'll have the same X; north-south lines will be vertical.

Edit again: I should have pointed out that this is a very simple formula and you should know its limitations. Obviously the earth is not flat, so any attempt to map it to XY coordinates will involve some compromises. The formula I derived above works best when the area you're converting is small enough to consider flat, and where the slight curvature and non-parallelism of north-south lines can be ignored. There's a whole science to map projections; if you want to see some possibilities a good place to start would be Wikipedia. This specific projection is known as the Equirectangular projection, with some added scaling.



回答2:

Harvesine function is what you need. Check it out at moveable-types There are Distance, Bearing, Midpoint and other stuff Javascript implementation working really good.

UPDATE

I've found a Java implementation of Harvesine function in another stackoverflow question



回答3:

There are libraries on jstott.me.uk for PHP, Java and Javascript which do this, e.g.

var lld1 = new LatLng(40.718119, -73.995667); // New York
document.write("New York Lat/Long: " + lld1.toString() + "<br />");
var lld2 = new LatLng(51.499981, -0.125313);  // London
document.write("London Lat/Long: " + lld2.toString() + "<br />");
var d = lld1.distance(lld2);
document.write("Surface Distance between New York and London: " + d + "km");