2

In old turfjs versions, it was possible to intersect a line and a polygon, like in this example.

But changing the turf.js version to the last one makes it fail, as shown in this other example.

The docs say that the intersect function works only with two polygons, so the error is documented.

Is it possible to use some other function to do that? Is there any example around there showing how to do it?

5 Answers 5

2

==EDIT==

A better soulution, that works with multilinestrings and multiple intersections, is using lineSplit, as shown in this example. Just iterate through the splitted lines and take only one each two of them.


I found the answer, which is combining lineIntersect and lineSlice:

let intersectionPoints = turf.lineIntersect(line, poly);
let intersectionPointsArray = intersectionPoints.features.map(d => {return d.geometry.coordinates});

let intersection = turf.lineSlice(turf.point(intersectionPointsArray[0]), turf.point(intersectionPointsArray[1]), line);

As I mention in the example, this will work with only one part of the line intersecting the polygon. If the line goes in and out several times, the method must be applied as many times as needed.

7
  • 1
    I was playing with JSTS instead. As you seem to work only with Turf, I put the example link just as an addition bl.ocks.org/ThomasG77/d66f1040960646abf56c90ae5e759b8a
    – ThomasG77
    Commented Jul 24, 2018 at 14:23
  • @ThomasG77 Thank you. It works better. I'm trying to use it with ES6 but I can't find how. A similar solution like this doesn't work: github.com/DenisCarriere/jsts-es6-example/blob/master/… Commented Jul 25, 2018 at 12:48
  • 1
    Try codesandbox.io/s/0m4mj899rv Same version as before but ES6 based (took some shortcuts but enough for the demonstration)
    – ThomasG77
    Commented Jul 25, 2018 at 15:33
  • 1
    The problem is that the import { io } from "jsts"; part doesn't work. All the examples I see use something like import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader', but then, the intersection function does not exist. Commented Jul 26, 2018 at 9:13
  • 1
    "The problem is that the import { io } from "jsts"; part doesn't work" Not sure why you are saying that. It works on my side (using Google Chrome). For import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader', like you, I was also not able to make it works (I thinkd related to the fact Node vs browser/webpack context)
    – ThomasG77
    Commented Jul 26, 2018 at 14:04
2

Since 2018, this has been easily possible with @turf/boolean-intersects:

import booleanIntersects from '@turf/boolean-intersects';
booleanIntersects(feature1, feature2)
1

I would take a look at TurfJs lineOverlap: https://turfjs.org/docs/#lineOverlap. From the docs:

"Takes any LineString or Polygon and returns the overlapping lines between both features."

From my understanding the overlap of polygon and a line is the part of the line which is inside the polygon.

1
  • I think lineOverlap is to find lines the two geometries in have in common, different than intersection. Commented Aug 7, 2021 at 2:25
1

I ran into this today at work, an example with modern turf


/**
 *
 * @param {LineString | MultiLineString} lineOrMultiLine input line or multiline
 * @param {Polygon | MultiPolygon} polygonOrMultiPolygon input polygon or multipolygon
 * @returns {FeatureCollection} a multiLineString with all the lines inside the polygon
 */

function linesInPolygon(lineOrMultiLine, polygonOrMultiPolygon) {
  // because line split does not accept multiLineString we flatten in case there are multilines
  const lines = turf.flatten(lineOrMultiLine);
  const linesInside = [];
  for (const line of lines.features) {
    // split line by polygon
    const split = turf.lineSplit(line, polygonOrMultiPolygon);
    for (const part of split.features) {
      // check which parts have a start inside the polygon
      const start = turf.booleanPointInPolygon(
        turf.point(part.geometry.coordinates[0]),
        polygonOrMultiPolygon
      );
      if (start) {
        linesInside.push(part);
      }
    }
  }
  // return as a featureCollection of lines
  return turf.featureCollection(linesInside);
}

ESM Version:

import lineSplit from '@turf/line-split';
import { point, featureCollection } from '@turf/helpers';
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
import flatten from '@turf/flatten';

/**
 *
 * @param {LineString | MultiLineString} lineOrMultiLine input line or multiline
 * @param {Polygon | MultiPolygon} polygonOrMultiPolygon input polygon or multipolygon
 * @returns {FeatureCollection} a multiLineString with all the lines inside the polygon
 */
export function linesInPolygon(lineOrMultiLine, polygonOrMultiPolygon) {
  // because line split does not accept multiLineString we flatten in case there are multilines
  const lines = flatten(lineOrMultiLine);
  const linesInside = [];
  for (const line of lines.features) {
    // split line by polygon
    const split = lineSplit(line, polygonOrMultiPolygon);
    for (const part of split.features) {
      // check which parts have a start inside the polygon
      const start = booleanPointInPolygon(
        point(part.geometry.coordinates[0]),
        polygonOrMultiPolygon
      );
      if (start) {
        linesInside.push(part);
      }
    }
  }
  // return as a featureCollection of lines
  return featureCollection(linesInside);
}
1

Turf used to use the JSTS package to find the intersection, but switched over at some point.

An example with JSTS:

import { GeometryObject } from 'geojson';
import * as jsts from 'jsts';

export function intersect(geom1: GeometryObject, geom2: GeometryObject) {

  const reader = new jsts.io.GeoJSONReader();
  const jstsGeometry1 = reader.read(geom1);
  const jstsGeometry2 = reader.read(geom2);

  const intersection = getIntersection(jstsGeometry1, jstsGeometry2);
  if (hasIntersection(intersection)) {
    const writer = new jsts.io.GeoJSONWriter();
    return writer.write(intersection) as GeometryObject;
  } else {
    return undefined;
  }
}


function getIntersection(geom1: jsts.geom.Geometry, geom2: jsts.geom.Geometry) {
  try {
    return geom1.intersection(geom2);
  } catch (ex) {
    if (ex?.name === 'TopologyException') {
      // Self-intersecting polygons are not supported. We handle this as 'no intersection'
      return undefined;
    }

    throw ex;
  }
}

function hasIntersection(jstsGeometry: jsts.geom.Geometry) {
  return jstsGeometry != null && jstsGeometry.getCoordinates().length > 0;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.