Search code examples
openlayers

Openlayers - Get shortest line between two geometries


Using OL4 and Angular 5, I want to calculate the shortest line between two geometries, because I want to draw the shortest line between two geometries.

for example I have two polygons like this:

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 geometry class has getClosestPoint function but it return the closest point of the geometry to a passed point.

I need a similar function but it receive a geometry object instead of point.

Regards.


Solution

  • Actually, Mike's answer is about 95% perfect :) .. so I done some improvements and here is the final code in 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);
      }