Обычные формулы проекции Меркатора для Карт Google не работают должным образом - PullRequest
6 голосов
/ 17 апреля 2010

Я создаю сервер Tile Overlay для карт Google в C # и нашел несколько различных примеров кода для вычисления Y из Локатора. После того, как я заставил их работать в целом, я начал замечать некоторые случаи, когда наложения не выравнивались должным образом. Чтобы проверить это, я сделал тестовый набор, чтобы сравнить преобразование Mercator LatToY в Google Map с формулами, которые я нашел в Интернете. Как вы можете видеть ниже, в некоторых случаях они не совпадают.

Дело № 1

Уменьшено: проблема наиболее очевидно, когда уменьшено. Близко, проблема едва заметна.

Дело № 2

Точка Близость к верху и низу границы просмотра: проблема хуже в середине просмотра границ, и становится лучше к краям. Такое поведение может свести на нет поведение Дело № 1

Тест:

Я создал страницу карт Google для отображать красные линии с помощью Google Map API встроенный в преобразователь Mercator, и наложить это на изображение с помощью код ссылки для выполнения меркатора преобразование. Эти преобразования представлены в виде черных линий. сравнить разница.

Результаты: Экватор http://www.kayak411.com/Mercator/MercatorComparison%20-%20Equator.png Север уменьшен http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out.png

Проверьте самые верхние и самые нижние строки: Пример North Top & Bottom http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out%20-%20TopAndBottom.png

Проблема становится визуально больше, но численно меньше при увеличении: альтернативный текст http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Midway.png

И все это почти исчезает при увеличении масштаба независимо от ориентации экрана. альтернативный текст 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 # преобразования координат проекта Mercator?

Спасибо!

Ответы [ 2 ]

1 голос
/ 04 мая 2010

Спасибо всем за ваши предложения и помощь.

В конце концов я обнаружил, что это не формула или техническая проблема, я считаю, что это проблема методологии.

Вы не можете определить область просмотра в формате Lat / Lng и ожидать, что она заполнится соответствующими проекциями Mercator. Вот где происходит искажение. Вместо этого вы должны определить правильное поле просмотра в Mercator и проект Mercator.

Благодаря этому я смог правильно сопоставить карты Google.

0 голосов
/ 03 мая 2010

Возможно, вам придется создать несколько точек вдоль долготы, чтобы точки были правильно спроецированы вдоль широты.В ваших примерах вы действительно проецируете только две точки в начале и конце линии и соединяете их.

Проблема будет более очевидной на экваторе из-за более значительной кривизны Земли.Это будет меньше при увеличении по той же причине.

Посмотрите на http://code.google.com/apis/maps/documentation/overlays.html#Great_Circles

Попробуйте создать свои полилинии Google с параметром geodsic, чтобы увидеть, если это что-то меняет.Я думаю, что это добавляет точки вдоль линии и проецирует их автоматически:

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 (больше ссылок/ объяснения)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...