2017-08-11 16 views
2

私はアンドロイドを介してGoogleマップに正方形のグリッドを描画しようとしています。Googleマップは投影にもかかわらず正方形を描画します

ジオピーでVincentyDistanceを使用して私のpythonサーバー上の250メートルの距離を測定すると、マップ上の結果のグリッドは正方形ではなくかなり長方形になります。

GoogleのSphericalUtil.computeOffsetを使用すると、マップ上で完全な四角形を生成することができますが、Googleマップで使用される投影が不規則な伸びを引き起こしているために、これをマークします。

これは、computeOffsetからの距離が間違っていることを示唆していますか?それともジオピーが間違っているのですか?誰かが私にこの行動を理解するのを助けることができる?

理想的には計算がサーバサイドであるのが好きで、理想的には、正方形が正方形でない限り、地図投影上で正方形である限り、正方形のグリッドを世界のどこにでも生成できます。

答えて

1

EDIT:

"?これはcomputeOffsetからの距離が間違っていることを示唆しています..."

はありません、それはそれは、投影だ、間違っていないのです。投影は伸び、スカッシュ、スキューなどがあります。

単語は高さの2倍の長方形として投影されます。幅360°、高さ180°。 北と南のポール(ポポントの両方)は、赤道の長さのように引き伸ばされています。

例外を除いて... Googleマップでは、マップがほぼ正方形(ズームに応じて)に縮小されます。したがって、Googleマップが提供する境界を確認する必要があります


マップの境界から水平方向に、垂直方向に密度を読み取ることができます。タイルが読み込まれたら、これを読むことができます。あなたはこのデータをサーバに送ることができます(このコードには含まれていません)

あなたの画面上のピクセルが正方形でない場合、私は助けがたいことがあります。

さて、物理的なピクセルの密度とその要因も検索できます。おそらくこれが役に立ちます:Mobile web: how to get physical pixel size?

例:400x400ピクセルマップ。中央の赤い正方形で、地図の幅と高さの半分です。 申し訳ありませんが、Python/Androidではなく、JavaScript/Webサイトの例です。しかし、私は同じ原則を使うことができると思います。

<!DOCTYPE html> 
<html> 
<head> 
<title>Square on Map</title> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"> 
<meta charset="utf-8"> 
<style> 
    html, 
    body { 
     height: 400px; 
     width: 400px; 
     padding: 0; 
    } 
    #map { 
     height: 80%; 
    } 
</style> 
<script> 
    var map; 
    // return a polyline. If you give 2 points, it will simply be a line 
    function makePolyline(points, color, close) { 
     if (close) { 
      points.push(points[0]); // closed polyline, so duplicate the start point as the endpoint 
     } 
     return new google.maps.Polyline({ 
      path: points, 
      //geodesic: false, 
      strokeColor: color, // example: '#FF0000', 
      strokeOpacity: 1.0, 
      strokeWeight: 2, 
      map: map 
     }); 
    } 

    function initMap() { 
     var myLocation = { 
      lat: 43, 
      lng: -108 
     }; 
     map = new google.maps.Map(document.getElementById('map'), { 
      center: myLocation, 
      zoom: 5 
     }); 

     // wait until the map is loaded before calculating bounds 
     google.maps.event.addListenerOnce(map, 'tilesloaded', function() { 
      var mapWidth = document.getElementById('map').offsetWidth; 
      var mapHeight = document.getElementById('map').offsetWidth; 
      var bounds = map.getBounds(); 
      var NE = bounds.getNorthEast(); 
      var SW = bounds.getSouthWest(); 

      // draw a square half the size of the map (200 X 200 px), in the midle => start at 1/4, stop at 3/4 
      points = [{ 
      lat: SW.lat() + ((NE.lat() - SW.lat()) * 1/4), 
      lng: SW.lng() + ((NE.lng() - SW.lng()) * 1/4) 
      }, 
      { 
      lat: SW.lat() + ((NE.lat() - SW.lat()) * 1/4), 
      lng: SW.lng() + ((NE.lng() - SW.lng()) * 3/4) 
      }, 
      { 
      lat: SW.lat() + ((NE.lat() - SW.lat()) * 3/4), 
      lng: SW.lng() + ((NE.lng() - SW.lng()) * 3/4) 
      }, 
      { 
      lat: SW.lat() + ((NE.lat() - SW.lat()) * 3/4), 
      lng: SW.lng() + ((NE.lng() - SW.lng()) * 1/4) 
      }]; 
      makePolyline(points, '#ff0000', true); 

      // display the numbers in a div. Feel free to not do this 
      document.getElementById('log').innerHTML = 'map width: ' + mapWidth + 'px - map height: ' + mapHeight + 'px<br/>'; 
      document.getElementById('log').innerHTML += 'horizontal: ' + ((NE.lng() - SW.lng())/mapWidth).toFixed(4) + ' degrees/px<br/>'; 
      document.getElementById('log').innerHTML += 'vertical: ' + ((NE.lat() - SW.lat())/mapHeight).toFixed(4) + ' degrees/px<br/>'; 
     }); 
    } 
</script> 
</head> 
<body> 
    <div id="map"></div> 
    <div id="log"></div> 
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap" async defer></script> 
</body> 
</html> 
+0

この興味深いアプローチに感謝します。問題は、ユーザからユーザまで一貫性のあるグリッドが必要なことです。そのため、私はそれをサーバサイドでやっています。 – RedEyes

関連する問題