Googleマップの一般的なメルカトル投影式が正しく機能していない
-
27-09-2019 - |
質問
C#でGoogleマップ用のタイルオーバーレイサーバーを構築しており、緯度からYを計算するためのいくつかの異なるコード例を見つけました。一般的に動作させた後、オーバーレイが適切に並んでいない特定のケースに気付き始めました。これをテストするために、オンラインで見つけたフォーミュラとGoogle MapのMercator Lattoyの変換を比較するために、テストハーネスを作成しました。以下に示すように、特定の場合は一致しません。
ケース#1
ズームアウト:ズームアウトすると問題が最も明白です。間近では、問題はほとんど見えません。
ケース#2
表示境界の上部と下部に近接してください:問題は表示境界の途中で悪化し、エッジに向かって良くなります。この動作は、ケース#1の動作を無効にすることができます
テスト:
Google Mapsページを作成して、Google Map APIの組み込みメルカトル変換を使用して赤い線を表示し、メルカトル変換を行うための参照コードを使用して画像でこれをオーバーレイします。これらの変換は黒い線として表されます。違いを比較します。
結果:赤道http://www.kayak411.com/mercator/mercatorcomparison%20-%20equator.png ノースは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マップクライアントサイドコード:
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);
}
だから、誰もがこれを経験したことがありますか?私が尋ねるあえて、これを解決しましたか?または、単にMercator Project Coordinate Conversionのより良いC#実装を持っていますか?
ありがとう!
解決
提案と支援をありがとうございました。
最終的に私が見つけたのは、それが式や技術的な問題ではないということです。それは方法論の問題だと思います。
LAT/LNG形式で視聴領域を定義することはできず、適切なメルカトル投影でそれを入力することを期待することはできません。それが歪みが起こる場所です。代わりに、メルカトルの正しい眺めボックスを定義し、プロジェクトメルカトルを定義する必要があります。
それをすることは、Googleマップと正しく一致することができました。
他のヒント
ポイントが緯度に沿って補正されるように、長い段階に沿っていくつかのポイントを作成する必要がある場合があります。あなたの例では、ラインの開始と終了時に2つのポイントを実際に投影し、2つを接続しています。
地球のより重要な湾曲により、赤道で問題はより明白になります。同じ理由でズームインしたときは少なくなります。
見て http://code.google.com/apis/maps/documentation/overlays.html#great_circles
GeodSICパラメーターを使用してGoogle Polylinesを作成して、これが違いを生むかどうかを確認してみてください。これはラインに沿ってポイントを追加し、自動的に投影すると思います。
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-tor-openlayer-distances (その他のリンク/説明)