将(旋转)ImageOverlay内的X和Y坐标转换为纬度和经度

时间:2018-03-07 12:29:17

标签: javascript angular typescript leaflet angular-leaflet-directive

在阅读了Projection documentation以及一些失败尝试测试之后,我发现自己无法找到解决此问题的方法。

我找到的解决方案是因为x和y坐标是参考墨卡托地图投影这一事实,但在这种情况下,我将它们放置在放置在地图上的图层上的本地图像中。

假设我有一张400px * 200px的灰色图像,使用ImageOverlay.Rotated放置在传单地图上,位置为:

var topleft = L.latLng(41.604766, 0.606402);
var topRight = L.latLng(41.605107, 0.606858);
var bottomleft = L.latLng(41.604610, 0.606613);

此图像使用左上角,右上角和左下角坐标作为参考放置在地图上。

结果是一个略微向北旋转的矩形。

如果我知道我将手机放在像素100,50(左边的角落)上  原始图像),我如何将这个笛卡尔坐标转换为经度和经度,以便我的地图显示它?

如果它是一个与北方完全对齐的矩形,我想我可以得到topLeft和bottomLeft角之间的º差异,除以像素数,然后将结果与我的手机的Y相乘得到纬度。使用先前的值,我将它乘以我手机的X来获取手机的经度。

但是考虑到形状是旋转的,世界并不平坦,我在地理和三角测量方面非常糟糕,我不确定它是否足够精确。

最后我们谈到的是手机,而不是建筑物。离开几米(2-4)是可以的,距离一个街区不是。

1 个答案:

答案 0 :(得分:3)

哦,你在谈论我自己的Leaflet.ImageOverlay.Rotated。我很乐意帮忙。

您应该查看其source code。所有的数学都在那里。让我们来看看那段代码:

    var pxTopLeft    = this._map.latLngToLayerPoint(this._topLeft);
    var pxTopRight   = this._map.latLngToLayerPoint(this._topRight);
    var pxBottomLeft = this._map.latLngToLayerPoint(this._bottomLeft);

这是将三个lat-long坐标转换为屏幕相对像素坐标Leaflet tutorial about creating subclasses of L.Layer对“图层点”的含义有很好的解释。

您可以将这些计算替换为您想要的任何其他重新投影,假设您在平面上工作而不是在大地水准面上。换句话说:您可能希望将lat-long坐标转换为EPSG:3857球形墨卡托坐标(这是Leaflet使用的显示投影)。如果这样做,您可以稍后将插值的EPSG:3857坐标转换为EPSG:4326“普通纬度 - 经度”坐标。

    // Calculate the skew angles, both in X and Y
    var vectorX = pxTopRight.subtract(pxTopLeft);
    var vectorY = pxBottomLeft.subtract(pxTopLeft);

CSS变换需要倾斜角度才能正确扭曲图像。这可能违反直觉,但ImageOverlay.Rotated使用CSS's skew()而不是rotate。但是你不需要倾斜角度,你只需要那些差分向量。

如果你想要看到它,vectorX是一个2D矢量,它沿着图像的顶部(从左到右),而vectorY是一个沿着左边的2D矢量一边(从上到下)。

这些向量允许您获取图像中任何点的屏幕坐标,假设输入范围为([0..1],[0..1])(0为顶部或左侧)图像,1是底部或右边)。但是你可能不希望相对于图像的高度/宽度使用数字,因为在你的问题中你提到了像素。所以让我们抓住像素。

    var imgW = this._rawImage.width;
    var imgH = this._rawImage.height;

好。我们从ImageOverlay.Rotated中提取了所需的所有数学部分。

现在,如果您将前面的矢量除以像素中的图像尺寸...

    var vectorXperPx = vectorX.divideBy(imgW);
    var vectorYperPx = vectorY.divideBy(imgW);

这些矢量从原始图像的一个像素到左侧(x)或下方(y)的像素。因此,给定原始图像的像素(x,y),相对于图像角的投影矢量将是:

    var deltaVector = 
               xPixelCoordinate.scaleBy(vectorXPerPx)
          .add(yPixelCoordinate.scaleBy(vectorYPerPx))

这是屏幕坐标中的矢量,从图像的左上角到图像的(xPixelCoordinate,yPixelCoordinate)像素。

现在添加图像左上角的屏幕坐标,然后设置:

    var finalCoordinateForImagePixel = pxTopLeft.add(deltaVector);

当我们使用latLngToLayerPoint时,结果将相对于该参照系。想要回来吗?易:

    var finalCoordinateForImagePixelInLatLong = 
           map.layerPointToLatLng(finalCoordinateForImagePixel);
  

但是考虑到形状是旋转的,世界并不平坦,我在地理和三角测量方面非常糟糕,我不确定它是否足够精确。

如果您使用Leaflet用于显示的坐标参照系(EPSG:3857),或任何同态坐标系(相对于屏幕的像素坐标,相对于图层原点的像素坐标),您将没有问题

相关问题