Convert long/lat to pixel x/y on a given picture

后端 未结 10 1269
遇见更好的自我
遇见更好的自我 2020-11-29 15:50

I have a city map of Moscow. We modified a Google Maps image with some artistic elements, but the relation between GPS coordinates and pixels remains the same.

相关标签:
10条回答
  • 2020-11-29 16:27

    You will have to implement the Google Maps API projection in your language. I have the C# source code for this:

    public class GoogleMapsAPIProjection
    {
        private readonly double PixelTileSize = 256d;
        private readonly double DegreesToRadiansRatio = 180d / Math.PI;
        private readonly double RadiansToDegreesRatio = Math.PI / 180d;
        private readonly PointF PixelGlobeCenter;
        private readonly double XPixelsToDegreesRatio;
        private readonly double YPixelsToRadiansRatio;
    
        public GoogleMapsAPIProjection(double zoomLevel)
        {
            var pixelGlobeSize = this.PixelTileSize * Math.Pow(2d, zoomLevel);
            this.XPixelsToDegreesRatio = pixelGlobeSize / 360d;
            this.YPixelsToRadiansRatio = pixelGlobeSize / (2d * Math.PI);
            var halfPixelGlobeSize = Convert.ToSingle(pixelGlobeSize / 2d);
            this.PixelGlobeCenter = new PointF(
                halfPixelGlobeSize, halfPixelGlobeSize);
        }
    
        public PointF FromCoordinatesToPixel(PointF coordinates)
        {
            var x = Math.Round(this.PixelGlobeCenter.X
                + (coordinates.X * this.XPixelsToDegreesRatio));
            var f = Math.Min(
                Math.Max(
                     Math.Sin(coordinates.Y * RadiansToDegreesRatio),
                    -0.9999d),
                0.9999d);
            var y = Math.Round(this.PixelGlobeCenter.Y + .5d * 
                Math.Log((1d + f) / (1d - f)) * -this.YPixelsToRadiansRatio);
            return new PointF(Convert.ToSingle(x), Convert.ToSingle(y));
        }
    
        public PointF FromPixelToCoordinates(PointF pixel)
        {
            var longitude = (pixel.X - this.PixelGlobeCenter.X) /
                this.XPixelsToDegreesRatio;
            var latitude = (2 * Math.Atan(Math.Exp(
                (pixel.Y - this.PixelGlobeCenter.Y) / -this.YPixelsToRadiansRatio))
                - Math.PI / 2) * DegreesToRadiansRatio;
            return new PointF(
                Convert.ToSingle(latitude),
                Convert.ToSingle(longitude));
        }
    }
    

    Source:

    http://code.google.com/p/geographical-dot-net/source/browse/trunk/GeographicalDotNet/GeographicalDotNet/Projection/GoogleMapsAPIProjection.cs

    0 讨论(0)
  • 2020-11-29 16:27

    You need formulas to convert latitude and longitude to rectangular coordinates. There are a great number to choose from and each will distort the map in a different way. Wolfram MathWorld has a good collection:

    http://mathworld.wolfram.com/MapProjection.html

    Follow the "See Also" links.

    0 讨论(0)
  • 2020-11-29 16:28

    The key to all of this is understanding map projections. As others have pointed out, the cause of the distortion is the fact that the spherical (or more accurately ellipsoidal) earth is projected onto a plane.

    In order to achieve your goal, you first must know two things about your data:

    1. The projection your maps are in. If they are purely derived from Google Maps, then chances are they are using a spherical Mercator projection.
    2. The geographic coordinate system your latitude/longitude coordinates are using. This can vary, because there are different ways of locating lat/longs on the globe. The most common GCS, used in most web-mapping applications and for GPS's, is WGS84.

    I'm assuming your data is in these coordinate systems.

    The spherical Mercator projection defines a coordinate pair in meters, for the surface of the earth. This means, for every lat/long coordinate there is a matching meter/meter coordinate. This enables you to do the conversion using the following procedure:

    1. Find the WGS84 lat/long of the corners of the image.
    2. Convert the WGS lat/longs to the spherical Mercator projection. There conversion tools out there, my favorite is to use the cs2cs tool that is part of the PROJ4 project.
    3. You can safely do a simple linear transform to convert between points on the image, and points on the earth in the spherical Mercator projection, and back again.

    In order to go from a WGS84 point to a pixel on the image, the procedure is now:

    1. Project lat/lon to spherical Mercator. This can be done using the proj4js library.
    2. Transform spherical Mercator coordinate into image pixel coordinate using the linear relationship discovered above.

    You can use the proj4js library like this:

    // include the library
    <script src="lib/proj4js-combined.js"></script>  //adjust the path for your server
                                                     //or else use the compressed version
    // creating source and destination Proj4js objects
    // once initialized, these may be re-used as often as needed
    var source = new Proj4js.Proj('EPSG:4326');    //source coordinates will be in Longitude/Latitude, WGS84
    var dest = new Proj4js.Proj('EPSG:3785');     //destination coordinates in meters, global spherical mercators projection, see http://spatialreference.org/ref/epsg/3785/
    
    
    // transforming point coordinates
    var p = new Proj4js.Point(-76.0,45.0);   //any object will do as long as it has 'x' and 'y' properties
    Proj4js.transform(source, dest, p);      //do the transformation.  x and y are modified in place
    
    //p.x and p.y are now EPSG:3785 in meters
    
    0 讨论(0)
  • 2020-11-29 16:30

    You may have a look at code that used on gheat, it's ported from js to python.

    0 讨论(0)
提交回复
热议问题