我正在为C#中的Google地图构建一个Tile Overlay服务器,并找到了一些用于从Latitude计算Y的不同代码示例。让他们一般工作后,我开始注意到某些情况下覆盖层没有正确排列。为了测试这一点,我制作了一个测试工具来比较Google Map的Mercator LatToY转换与我在网上找到的公式。如下所示,在某些情况下它们不匹配。
案例#1
缩小:问题最多 缩小时显而易见。快了, 问题几乎不可见。
案例#2
点接近顶部&底部 观看界限:问题更严重 在观看范围的中间, 并朝着边缘变得更好。 此行为可以否定行为 案例#1
测试:
我创建了一个谷歌地图页面 使用Google地图显示红线 API内置墨卡托转换, 并用图像覆盖它 做墨卡托的参考代码 转换。这些转换是 表示为黑线。相比 差异。
结果: Equator http://www.kayak411.com/Mercator/MercatorComparison%20-%20Equator.png North Zoomed Out http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out.png
当您放大时,问题在视觉上会变大但在数值上会变小: alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Midway.png
无论屏幕方向如何,它都会在更接近的缩放级别消失。 alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20In.png
守则:
Google Maps客户端代码:
var lat = 0;
for (lat = -80; lat <= 80; lat += 5) {
map.addOverlay(new GPolyline([new GLatLng(lat, -180), new GLatLng(lat, 0)], "#FF0033", 2));
map.addOverlay(new GPolyline([new GLatLng(lat, 0), new GLatLng(lat, 180)], "#FF0033", 2));
}
服务器端代码:
瓷砖切割机: http://mapki.com/wiki/Tile_Cutter
OpenStreetMap Wiki: http://wiki.openstreetmap.org/wiki/Mercator
protected override void ImageOverlay_ComposeImage(ref Bitmap ZipCodeBitMap)
{
Graphics LinesGraphic = Graphics.FromImage(ZipCodeBitMap);
Int32 MapWidth = Convert.ToInt32(Math.Pow(2, zoom) * 255);
Point Offset =
Cartographer.Mercator2.toZoomedPixelCoords(North, West, zoom);
TrimPoint(ref Offset, MapWidth);
for (Double lat = -80; lat <= 80; lat += 5)
{
Point StartPoint = Cartographer.Mercator2.toZoomedPixelCoords(lat, -179, zoom);
Point EndPoint = Cartographer.Mercator2.toZoomedPixelCoords(lat, -1, zoom);
TrimPoint(ref StartPoint, MapWidth);
TrimPoint(ref EndPoint, MapWidth);
StartPoint.X = StartPoint.X - Offset.X;
EndPoint.X = EndPoint.X - Offset.X;
StartPoint.Y = StartPoint.Y - Offset.Y;
EndPoint.Y = EndPoint.Y - Offset.Y;
LinesGraphic.DrawLine(new Pen(Color.Black, 2),
StartPoint.X,
StartPoint.Y,
EndPoint.X,
EndPoint.Y);
LinesGraphic.DrawString(
lat.ToString(),
new Font("Verdana", 10),
new SolidBrush(Color.Black),
new Point(
Convert.ToInt32((width / 3.0) * 2.0),
StartPoint.Y));
}
}
protected void TrimPoint(ref Point point, Int32 MapWidth)
{
point.X = Math.Max(point.X, 0);
point.X = Math.Min(point.X, MapWidth - 1);
point.Y = Math.Max(point.Y, 0);
point.Y = Math.Min(point.Y, MapWidth - 1);
}
那么,有没有人经历过这个?我敢问,解决了这个问题?或者只是有一个更好的墨卡托项目坐标转换的C#实现?
谢谢!
答案 0 :(得分:1)
谢谢大家的建议和帮助。协助。
我最终发现,这不是一个公式或技术问题,我认为这是一个方法论问题。
您无法以Lat / Lng格式定义查看区域,并希望使用适当的墨卡托投影填充它。这就是失真发生的地方。相反,您必须在墨卡托中定义正确的查看框,并投影墨卡托。
这样做我能够正确匹配Google地图。
答案 1 :(得分:0)
您可能需要沿着长度创建多个点,以便沿纬度相应地投影点。在您的示例中,您只是在行的开头和结尾处实际投影两个点并连接两个点。
由于地球的曲率更加明显,赤道上的问题将更加明显。放大时出于同样的原因,它会更少。
查看http://code.google.com/apis/maps/documentation/overlays.html#Great_Circles
尝试使用geodsic参数创建Google折线,看看这是否有所不同。我认为这会在线上添加点并自动投影:
var lat = 0;
var polyOptions = {geodesic:true};
for (lat = -80; lat <= 80; lat += 5) {
map.addOverlay(new GPolyline([new GLatLng(lat, -180), new GLatLng(lat, 0)], "#FF0033", 2, polyOptions));
map.addOverlay(new GPolyline([new GLatLng(lat, 0), new GLatLng(lat, 180)], "#FF0033", 2, polyOptions));
}
由于类似的原因,因为我在OpenLayers中的所有距离测量都是错误的,所以我必须阅读此内容:http://geographika.co.uk/watch-out-for-openlayer-distances(更多链接/解释)