Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将给定图片上的长/宽转换为像素x/y_Javascript_Google Maps_Coordinates_Google Static Maps - Fatal编程技术网

Javascript 将给定图片上的长/宽转换为像素x/y

Javascript 将给定图片上的长/宽转换为像素x/y,javascript,google-maps,coordinates,google-static-maps,Javascript,Google Maps,Coordinates,Google Static Maps,我有一张莫斯科的城市地图。我们用一些艺术元素修改了谷歌地图图像,但GPS坐标和像素之间的关系保持不变 问题:如何将各种数据点的GPS坐标转换为图像中的像素坐标 理想情况下,我可以用Javascript实现这一点,但PHP也可以 我知道在小比例尺上(例如在城市比例尺上),制作简单(有必要了解什么地理坐标有一个图片角,然后分别了解OX和OY轴上图片地理坐标中一个像素的“价格”) 但在大尺度(国家尺度)上,一个像素的“价格”将不是一个常数,并且会有足够大的变化,上述方法无法应用 如何解决国家层面的问

我有一张莫斯科的城市地图。我们用一些艺术元素修改了谷歌地图图像,但GPS坐标和像素之间的关系保持不变

问题:如何将各种数据点的GPS坐标转换为图像中的像素坐标

理想情况下,我可以用Javascript实现这一点,但PHP也可以


我知道在小比例尺上(例如在城市比例尺上),制作简单(有必要了解什么地理坐标有一个图片角,然后分别了解OX和OY轴上图片地理坐标中一个像素的“价格”)

但在大尺度(国家尺度)上,一个像素的“价格”将不是一个常数,并且会有足够大的变化,上述方法无法应用

如何解决国家层面的问题


更新:


我不使用API谷歌地图,我只有:对象的地理坐标(它们来自谷歌地图),我的网站上还有一张简单的图片*。gif,其中我必须绘制一个与地理坐标相对应的点。

如果假设每个像素位于同一区域,那么下面关于将距离转换为经度/纬度坐标的文章可能会对您有所帮助:


您需要公式将纬度和经度转换为直角坐标。有很多选择,每一个都会以不同的方式扭曲地图。Wolfram MathWorld有一个很好的收藏:


按照“另请参阅”链接进行操作。

您可能会看到,它是从js移植到python的。

您正在处理的转换与此有关,这就是如何将我们世界的球面转换为二维渲染的。有多种方法(投影)可以在二维曲面上渲染世界

如果您的地图只使用特定的投影(很流行),您应该能够找到方程式、一些示例代码和/或一些库(例如,一个墨卡托解-。如果不这样做,我相信您可以找到其他示例-。如果您的图像不是地图使用墨卡托投影,您需要确定它使用什么投影来找到正确的平移方程


如果您试图支持多个地图投影(您希望支持使用不同投影的多个不同地图),那么您肯定想使用类似的库,但我不确定您会在Javascript或PHP中找到什么。

所有这些的关键是理解。正如其他人所指出的,造成扭曲的原因是球形(或更准确地说是椭圆形)地球投影到一个平面上的事实

为了实现目标,您首先必须了解有关数据的两件事:

  • 你的地图所处的投影。如果它们纯粹是从中派生出来的,那么它们很可能是在使用一个投影
  • 您的纬度/经度坐标所使用的地理坐标系。这可能会有所不同,因为在地球上定位纬度/经度的方法不同。在大多数web地图应用程序和GPS中使用的最常见的GCS是
  • 我假设你的数据在这些坐标系中

    球面墨卡托投影为地球表面定义了一个以米为单位的坐标对。这意味着,对于每个lat/long坐标,都有一个匹配的米/米坐标。这使您能够使用以下步骤进行转换:

  • 找到图像角的WGS84 lat/long
  • 将WGS lat/longs转换为球形墨卡托投影。有很多转换工具,我最喜欢的是使用cs2cs工具,它是投影的一部分
  • 您可以安全地执行简单的线性变换,在图像上的点与球形墨卡托投影中的地球上的点之间进行转换,然后再进行转换
  • 为了从WGS84点变为图像上的像素,程序如下:

  • 将lat/lon投影到球形墨卡托。可以使用
  • 使用上面发现的线性关系将球面墨卡托坐标转换为图像像素坐标
  • 您可以像这样使用proj4js库:

    // 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
    
    //包含该库
    //调整服务器的路径
    //或者使用压缩版本
    //创建源和目标Proj4js对象
    //一旦初始化,它们可以根据需要重复使用
    var source=new Proj4js.Proj('EPSG:4326');//源坐标将以经度/纬度WGS84表示
    var dest=new Proj4js.Proj('EPSG:3785');//以米为单位的目标坐标,全局球形墨卡托投影,请参见http://spatialreference.org/ref/epsg/3785/
    //转换点坐标
    var p=new Proj4js.Point(-76.0,45.0);//任何对象只要具有“x”和“y”属性就可以
    Proj4js.transform(source,dest,p);//执行转换。x和y被就地修改
    //p、 x和p.y现在是EPSG:3785米
    
    那么您想获取纬度/经度坐标,并找出该位置图像上的像素坐标

    主GMap2类提供与显示地图上的像素和lat/long坐标之间的转换:

    Gmap2.fromLatLngToContainerPixel(latlng)
    
    例如:

    var gmap2 = new GMap2(document.getElementById("map_canvas"));
    var geocoder = new GClientGeocoder();
    
    geocoder.getLatLng( "1600 Pennsylvania Avenue NW Washington, D.C. 20500",
        function( latlng ) {
            var pixel_coords = gmap2.fromLatLngToContainerPixel(latlng);
    
            window.alert( "The White House is at pixel coordinates (" + 
                pixel_coodrs.x + ", " + pixel_coords.y + ") on the " +
                "map image shown on this page." );
        }
    );
    
    因此,假设您的地图图像是Google地图显示的屏幕抓取,那么这将为您提供该图像上正确的像素坐标(lat/long坐标)

    如果你抓取瓷砖图像并自己将它们缝合在一起,事情会变得更加棘手,因为整个瓷砖集的区域将位于显示地图的区域之外

    在这种情况下,需要使用左上图像平铺的左和顶部值作为从LatlNgtoContainerPixel(latlng:GLatLng)提供给您的坐标的偏移,从x坐标减去左坐标,从y坐标减去顶部坐标
    GMap2.fromLatLngToDivPixel(latlng:GLatLng)
    
    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));
        }
    }
    
    var map = new OpenLayers.Map({
                div:"map-id",
                allOverlays: true
        });
        var osm = new OpenLayers.Layer.OSM("OpenStreeMao");
        var gmap = new OpenLayers.Layer.Google("Google Streets", {visibility: false});
    
        map.addLayers([osm,gmap]);
    
        var vectorLayer = new OpenLayers.Layer.Vector("IconLayer");
    
    
        var lonlatObject = new OpenLayers.LonLat(24.938622,60.170421).transform(
                new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()
        );
        console.log(lonlatObject);
    
        var point = new OpenLayers.Geometry.Point(lonlatObject.lon, lonlatObject.lat);
        console.log(point);
    
        var point2 = new OpenLayers.Geometry.Point(lonlatObject.x, lonlatObject.y);
        console.log(point2);
    
        var feature = new OpenLayers.Feature.Vector(point, null, {
            externalGraphic:  "http://cdn1.iconfinder.com/data/icons/SUPERVISTA/networking/png/72/antenna.png",
            graphicWidth: 72,
            graphicHeight: 72,
            fillOpacity: 1
        });
    
    
        vectorLayer.addFeatures(feature);
    
        map.addLayer(vectorLayer);
    
    
        map.setCenter(
                new OpenLayers.LonLat(24.938622,60.170421).transform(
                new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()
                ),
                12);
    
         map.addControl(new OpenLayers.Control.LayerSwitcher());
    
    // Adapted from : http://blog.cppse.nl/x-y-to-lat-lon-for-google-maps
    
    
    window.geo = {
    
        glOffset: Math.pow(2,28), //268435456,
        glRadius:  Math.pow(2,28) / Math.PI,
        a: Math.pow(2,28),
        b: 85445659.4471,
        c: 0.017453292519943,
        d: 0.0000006705522537,
        e: Math.E, //2.7182818284590452353602875,
        p: Math.PI / 180,
    
        lonToX: function(lon) {
            return Math.round(this.glOffset + this.glRadius * lon * this.p);
        },
    
        XtoLon: function(x) {
            return -180 + this.d * x;
        },
    
        latToY: function(lat) {
            return Math.round(this.glOffset - this.glRadius *
                              Math.log((1 + Math.sin(lat * this.p)) /
                              (1 - Math.sin(lat * this.p))) / 2);
        },
    
        YtoLat: function(y) {
            return Math.asin(Math.pow(this.e,(2*this.a/this.b - 2*y/this.b)) /
                                     (Math.pow(this.e, (2*this.a/this.b - 2*y/this.b))+1) -
                                     1/(Math.pow(this.e, (2*this.a/this.b - 2*y/this.b))+1)
                            ) / this.c;
        },
    
        deltaLonPerDeltaX: function(deltaX, zoom) {
            // 2^(7+zoom) pixels <---> 180 degrees
            return deltaX * 180 / Math.pow(2, 7+zoom);
        },
    
        deltaLatPerDeltaY: function(deltaY, zoom, startLat) {
            // more complex because of the curvature, we calculte it by difference
            var startY = this.latToY(startLat),
                endY = startY + deltaY * Math.pow(2, 28-7-zoom),
                endLat = this.YtoLat(endY);
    
            return ( endLat - startLat ); // = deltaLat
        }
    }