Openlayers - 获取两个几何之间的最短线

Openlayers - Get shortest line between two geometries

使用OL4和Angular5,我想计算两个几何之间的最短线,因为我想画两个几何之间的最短线。

例如我有两个这样的多边形:

const geom1 = new ol_geom_Polygon([[[39.08317178, 34.94428969], [40.15753633, 35.19891679], 
        [40.09419625, 35.46617166], [39.0198317, 35.21154456], [39.08317178, 34.94428969]]]);

const geom2 = new ol_geom_Polygon([[[42.06884752, 37.70855705], [41.28393081, 37.41465862], 
        [41.93091268, 36.88185002], [42.06884752, 37.70855705]]]);

OL4 几何体 class 具有 getClosestPoint 功能,但它 return 几何体中最接近通过点的点。

我需要类似的功能,但它接收的是几何对象而不是点。

此致。

我认为任何最短的线都将始终包含其中一个线串的顶点之一(对于多边形,线串将是外环),因此这些坐标中的任何一个给出最接近的最近点就是最短线。我已经检查了 getClosestPoint 的源代码,它使用了一个简单的毕达哥拉斯距离计算,因此在调用这样的函数之前,应该将几何图形转换为地图坐标,其中 returns 从 geom1 到 geom2 的一条线,其中几何图形可以是单个多边形 and/or 单个线串。

function getShortestLine(geom1, geom2) {

    var result;
    var distanceSq = Infinity;

    (geom1.getLinearRing ? geom1.getLinearRing(0) : geom1).getCoordinates().forEach(function(coordinates) {
        var closest = geom2.getClosestPoint(coordinates);
        var distanceNew = Math.pow(closest[0]-coordinates[0],2) + Math.pow(closest[1]-coordinates[1],2);
        if (distanceNew < distanceSq) {
            distanceSq = distanceNew;
            result = [ coordinates, closest ];
        }
    });

    (geom2.getLinearRing ? geom2.getLinearRing(0) : geom2).getCoordinates().forEach(function(coordinates) {
        var closest = geom1.getClosestPoint(coordinates);
        var distanceNew = Math.pow(closest[0]-coordinates[0],2) + Math.pow(closest[1]-coordinates[1],2);
        if (distanceNew < distanceSq) {
            distanceSq = distanceNew;
            result = [ closest, coordinates ];
        }
    });

    return new ol.geom.LineString(result);

}

实际上,Mike 的回答大约有 95% 完美:) ..所以我做了一些改进,这是 TypeScript 中的最终代码:

  public getShortestLine(geom1: ol_geom_Geometry, geom2: ol_geom_Geometry): ol_geom_LineString {
    if (geom1.getType() === 'Point' && geom2.getType() === 'Point') {
      return new ol_geom_LineString([(geom1 as ol_geom_Point).getCoordinates(), (geom2 as ol_geom_Point).getCoordinates()]);
    }

    let result = [];
    let distanceSq = Infinity;

    let geom1Coordinates = [];
    if (geom1.getType() === 'Polygon') {
      geom1Coordinates = (geom1 as ol_geom_Polygon).getLinearRing(0).getCoordinates();
    } else if (geom1.getType() === 'Point') {
      geom1Coordinates = [(geom1 as ol_geom_Point).getCoordinates()];
    } else {
      geom1Coordinates = (geom1 as any).getCoordinates();
    }

    let geom2Coordinates = [];
    if (geom2.getType() === 'Polygon') {
      geom2Coordinates = (geom2 as ol_geom_Polygon).getLinearRing(0).getCoordinates();
    } else if (geom2.getType() === 'Point') {
      geom2Coordinates = [(geom2 as ol_geom_Point).getCoordinates()];
    } else {
      geom2Coordinates = (geom2 as any).getCoordinates();
    }

    geom1Coordinates.forEach(coordinates => {
      const closest = geom2.getClosestPoint(coordinates);
      const distanceNew = Math.pow(closest[0] - coordinates[0], 2) + Math.pow(closest[1] - coordinates[1], 2);
      if (distanceNew < distanceSq) {
        distanceSq = distanceNew;
        result = [coordinates, closest];
      }
    });

    geom2Coordinates.forEach(coordinates => {
      const closest = geom1.getClosestPoint(coordinates);
      const distanceNew = Math.pow(closest[0] - coordinates[0], 2) + Math.pow(closest[1] - coordinates[1], 2);
      if (distanceNew < distanceSq) {
        distanceSq = distanceNew;
        result = [closest, coordinates];
      }
    });

    return new ol_geom_LineString(result);
  }