在阅读了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)是可以的,距离一个街区不是。
答案 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),或任何同态坐标系(相对于屏幕的像素坐标,相对于图层原点的像素坐标),您将没有问题