6

我正在用 C# 为 Google 地图构建一个 Tile Overlay 服务器,并找到了一些不同的代码示例用于从纬度计算 Y。在让它们正常工作后,我开始注意到某些情况下覆盖层没有正确排列。为了测试这一点,我做了一个测试工具来比较谷歌地图的墨卡托 LatToY 转换和我在网上找到的公式。正如您在下面看到的,它们在某些情况下不匹配。

情况1

缩小:缩小时问题最为明显。近距离观察,几乎看不到问题。

案例#2

点接近查看边界的顶部和底部:问题在查看边界的中间更严重,并且在边缘变得更好。这种行为可以否定案例#1的行为

考试:

我创建了一个谷歌地图页面,使用谷歌地图 API 的内置墨卡托转换来显示红线,并使用参考代码进行墨卡托转换将其覆盖在图像上。这些转换用黑线表示。比较差异。

结果: 赤道 http://www.kayak411.com/Mercator/MercatorComparison%20-%20Equator.png 北方缩小 http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out。 PNG

查看最顶层和最底层的行: North Top & Bottom Example http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out%20-%20TopAndBottom.png

当您放大时,问题会在视觉上变大,但在数值上会变小: alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Midway.png

无论屏幕方向如何,它都会在更近的缩放级别消失。 替代文字 http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20In.png

编码:

谷歌地图客户端代码:

            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 维基: 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# 实现?

谢谢!

4

2 回答 2

1

谢谢大家的建议和帮助。

我最终发现这不是一个公式或技术问题,我相信这是一个方法问题。

您不能以 Lat/Lng 格式定义查看区域,并期望使用适当的墨卡托投影填充它。这就是失真发生的地方。相反,您必须在墨卡托中定义正确的查看框,并投影墨卡托。

这样做我能够正确匹配谷歌地图。

于 2010-05-04T16:09:53.723 回答
0

您可能必须沿经度创建多个点,以便沿纬度正确投影这些点。在您的示例中,您实际上只是在线条的起点和终点投射两个点并将两者连接起来。

由于地球的曲率更大,这个问题在赤道会更加明显。出于同样的原因,放大时它会更小。

看看http://code.google.com/apis/maps/documentation/overlays.html#Great_Circles

尝试使用测地线参数创建您的 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(更多链接/说明)

于 2010-05-03T08:54:35.087 回答