尽管投影,谷歌地图仍然绘制正方

时间:2017-08-11 07:31:20

标签: android python google-maps geopy

我试图通过Android在谷歌地图上绘制一个方格。

如果我在geopy服务器上使用VincentyDistance测量250米乘250米距离,则地图上生成的网格显着为矩形而不是方形。

我将此标记为由谷歌地图使用的投影导致不成比例的拉伸造成的,但如果我改为使用谷歌的SphericalUtil.computeOffset,我可以在地图上生成接近完美的正方形。

这是否表明与computeOffset的距离是错误的?或者那个geopy是错的?有人可以帮我理解这种行为吗?

理想情况下我喜欢计算机是服务器端,理想情况下我可以在世界的任何地方生成方格,即使它实际上意味着正方形不是正方形,只要它在地图投影上看起来是方形的。

1 个答案:

答案 0 :(得分:1)

编辑:

  

“这是否表明与computeOffset的距离错误?......”

不,这没错,这是一个预测。预测拉伸,壁球,歪斜......一切

这个单词被投影为一个矩形,是高度的两倍。 360°宽,180°高。 北极和南极(都只是一个popint)被拉伸,好像它们和赤道一样长。

除了...谷歌地图然后压缩该地图,几乎是一个正方形(取决于缩放)。因此,您必须检查Google地图为您提供的界限

您可以从地图边界水平,然后垂直读取度数密度。加载图块后,您可以阅读此内容。如果需要,可以使用AJAX(不包含在此代码中)将此数据发送到服务器

我无法帮助的一件事是屏幕上的像素不是方形的。

好吧,也许您可​​以搜索物理像素密度和因子。也许这会有所帮助:Mobile web: how to get physical pixel size?

举个例子:400x400 px map。中间是红色正方形,是地图宽度和高度的一半。 对不起,这是一个javascript /网站示例,而不是Python / Android。但我想你可以使用相同的原则。

<!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>