【问题标题】:OpenLayers 3: How to calculate distance between 2 points?OpenLayers 3:如何计算两点之间的距离?
【发布时间】:2014-09-27 05:04:51
【问题描述】:

使用 OpenLayers 3,如何确定 Spherical Mercator (SRID: 3857) 投影中两点之间的距离?

我知道在 OpenLayers 2 中使用了 distanceTo

point1.distanceTo(point2)

我查看了OpenLayers 3 docs,但没有找到类似的东西...

【问题讨论】:

    标签: javascript openlayers-3


    【解决方案1】:

    您可以使用 Sphere 对象计算两个坐标之间的距离,如下所示:

    var distance = ol.sphere.WGS84.haversineDistance([0,0],[180,0]); 
    //20037508.34 meters 
    

    Sphere 还提供了各种算法来计算距离,如余弦、等距矩形等。 您还可以创建具有不同椭球半径的 Sphere 对象。

    不知道为什么文档不在线,但是你可以从球体对象的源代码中查看可用的方法:https://github.com/openlayers/ol3/blob/master/src/ol/sphere.js

    我个人认为查看源代码是找到有关 OpenLayers3 答案的最佳方式;)

    【讨论】:

    • 该函数适用于世界测地线系统(wgs84 或 epsg4326)。如果需要,请使用 ol.proj.transform(coordinates, 'EPSG:3857', 'EPSG:4326')。
    • 需要注意的是,ol.sphere.WGS84.haversineDistance 在 ol3 生产代码中不可用(当前为 3.2.0)。事实上,该方法没有被标记为稳定,因此它只能在ol-debug.js 中使用。这也是它没有出现在文档中的原因。
    • With #3222 ol.Sphere.haversineDistance 现在被标记为 API 方法:openlayers.org/en/master/apidoc/… 另请查看更新示例:openlayers.org/en/master/examples/measure.html
    • 注意大小写:ol.sphere 应该是ol.Sphere
    • haversineDistance 需要在 ol.Sphere 的实例上调用(它不是静态的)。我确实喜欢这样: var wgs84Sphere = new ol.Sphere(6378137); var 距离 = wgs84Sphere.haversineDistance([lon1, lat1], [lon2, lat2]); // 以米为单位
    【解决方案2】:

    我正在使用一个相当简单的解决方案。我在两点之间实例化一个 ol.geom.LineString 对象并计算线的长度:

            this.distanceBetweenPoints = function(latlng1, latlng2){
                var line = new ol.geom.LineString([latlng1, latlng2]);
                return Math.round(line.getLength() * 100) / 100;
            };
    

    然后您可以使用某种格式获得可读值:

            this.formatDistance = function(length) {
                if (length >= 1000) {
                    length = (Math.round(length / 1000 * 100) / 100) +
                    ' ' + 'km';
                } else {
                    length = Math.round(length) +
                    ' ' + 'm';
                }
                return length;
            }
    

    编辑:新的计算方法

    实际上,关于您使用的投影,距离可能是错误的。 我们在 ol3 的 github 上对此进行了相当长的讨论,你可以在那里看到: https://github.com/openlayers/ol3/issues/3533

    总而言之,您需要使用该函数才能获得精确的计算:

    /**
     * format length output
     * @param {ol.geom.LineString} line
     * @return {string}
     */
    export default function mapFormatLength(projection, line) {
      var length;
      var coordinates = line.getCoordinates();
      length = 0;
      for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
        var c1 = ol.proj.transform(coordinates[i], projection, 'EPSG:4326');
        var c2 = ol.proj.transform(coordinates[i + 1], projection, 'EPSG:4326');
        length += mapConst.wgs84Sphere.haversineDistance(c1, c2);
      }
      var output;
      if (length > 1000) {
        output = (Math.round(length / 1000 * 100) / 100) +
        ' ' + 'km';
      } else {
        output = (Math.round(length * 100) / 100) +
        ' ' + 'm';
      }
      return output;
    }
    

    【讨论】:

    • 有什么办法可以避免使用 mapConst.wgs84Sphere.haversineDistance?它在生产版本中不可用。
    • 我猜在新版本的openlayer中,他们引入了一种在api中获取正确长度的方法
    【解决方案3】:

    只是添加一个选项。这不依赖于 ol3。

    function toRad(x) {return x * Math.PI / 180;}
    
    function SphericalCosinus(lat1, lon1, lat2, lon2) {
    
        var R = 6371; // km
        var dLon = toRad(lon2 - lon1),
            lat1 = toRad(lat1),
            lat2 = toRad(lat2),
            d = Math.acos(Math.sin(lat1)*Math.sin(lat2) + Math.cos(lat1)*Math.cos(lat2) * Math.cos(dLon)) * R;
    
    
        return d;
    }
    

    【讨论】:

    • 我刚刚遇到这个,它看起来很简单,但我得到的结果对于我正在测量的距离来说似乎太高了。我不想提出新问题,但想知道您是否可以帮助我调试它,请@JonatasWalker?
    • 为您服务@dvmac01。你在用EPSG:4326吗?
    • 直到你提到它;)这似乎已经成功了。它仍然返回比其他地方报告的(谷歌地图/维基百科)略高的测量值,但如果有的话,它可能太准确了吗?一位同事将我引向这篇文章:en.wikipedia.org/wiki/Coastline_paradox 这解释了问题,所以我正在考虑某种平滑方法,不知道您是否可以提出建议,但感谢您的提示!
    • 可能值得注意的是,这会返回一个以公里为单位的值!
    【解决方案4】:

    我为自己写了这个我希望它会很有用,它以米为单位返回距离:

    function getCoordsDistance(firstPoint, secondPoint, projection) {
        projection = projection || 'EPSG:4326';
    
        length = 0;
        var sourceProj = mapObj.getView().getProjection();
        var c1 = ol.proj.transform(firstPoint, sourceProj, projection);
        var c2 = ol.proj.transform(secondPoint, sourceProj, projection);
    
        var wgs84Sphere = new ol.Sphere(6378137);
        length += wgs84Sphere.haversineDistance(c1, c2);
    
        return length;
    }
    

    【讨论】:

      【解决方案5】:
      function getCoordsDistance(latlng1, latlng2) {
      
          var markers = [];
      
          markers.push(ol.proj.transform(latlng1, 'EPSG:4326', map.getView().getProjection()));
          markers.push(ol.proj.transform(latlng2, 'EPSG:4326', map.getView().getProjection()));
      
          var line = new ol.geom.LineString(markers, 'XY');
          var length = Math.round(line.getLength() * 100) / 100;
      
          if (length >= 1000) {
              length = (Math.round(length / 1000 * 100) / 100) +
                  ' ' + 'km';
          } else {
              length = Math.round(length) +
                  ' ' + 'm';
          }
          return length;
      }
      

      【讨论】:

      • 您的结果将以投影单位表示,而不是真正的米或公里。根据所使用的投影,一条横穿格陵兰的线会给出与横穿非洲的线类似的结果,但实际上格陵兰比非洲小得多,因此真正的距离会更短。 ol.Sphere.getLength() 或 .haversineDistance() 给出圆形行星上最短的真实距离。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 2011-04-23
      • 2014-11-14
      • 1970-01-01
      相关资源
      最近更新 更多