c# - Google map 的常见墨卡托投影公式无法正常工作

标签 c# mapping gis google-maps mercator

我正在用 C# 为 Google map 构建一个 Tile Overlay 服务器,并找到了几个不同的代码示例来从 Latitude 计算 Y。在让它们正常工作后,我开始注意到某些情况下叠加层没有正确对齐。为了对此进行测试,我制作了一个测试工具来比较 Google Map 的 Mercator LatToY 转换与我在网上找到的公式。如下所示,它们在某些情况下不匹配。

案例 #1

Zoomed Out: The problem is most evident when zoomed out. Up close, the problem is barely visible.

案例#2

Point Proximity to Top & Bottom of viewing bounds: The problem is worse in the middle of the viewing bounds, and gets better towards the edges. This behavior can negate the behavior of Case #1

测试:

I created a google maps page to display red lines using the Google Map API's built in Mercator conversion, and overlay this with an image using the reference code for doing Mercator conversion. These conversions are represented as black lines. Compare the difference.

结果: Equator http://www.kayak411.com/Mercator/MercatorComparison%20-%20Equator.png North Zoomed Out 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

无论屏幕方向如何,在更近的缩放级别上它几乎都消失了。 alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20In.png

代码:

Google map 客户端代码:

            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));
        }

服务器端代码:

Tile Cutter : 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# 实现?

谢谢!

最佳答案

感谢大家的建议和帮助。

我最终发现这不是公式或技术问题,我认为这是方法论问题。

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

这样我就能够正确匹配 Google map 。

关于c# - Google map 的常见墨卡托投影公式无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2656580/

相关文章:

ios - RestKit RKObjectMapping 到 CLLocation

r - 与我的 shapefile 关联的 proj4 字符串是什么?

javascript - 使用 Google Maps API v3 中的 Sprite 标记图标缩放标记大小

c# - 如果类没有构造函数,.Net 将类中的所有值设置为 "default values"是什么?

c# - JIT 编译器与离线编译器

python - 如何映射两个字典中的相同项目并生成其对应键的值列表

r - 使用 R 从一个 url 下载多个文件

c# - 如何将 Web API 添加到现有的 ASP.NET MVC Core 6 Web 应用程序

c# - 在没有命名空间的情况下运行 linq-to-XML 操作

opencv - 3D映射到RGB的深度(Kinect OpenNI深度图到OpenCV RGB凸轮)