2

I wanted to know if there is a way to split a polygon using JavaScript. So I have a web map which uses Leaflet API, and the user needs to cut polygons which are shown in the map using a straight line. I was hoping there would be a JavaScript library something JSTS or Turf but if that isn't possible an algorithm would do just fine.

  • Why is Turf not suitable? – TomazicM May 8 at 16:36
  • I am pretty sure I have gone through the whole turf.js documentation and I haven't found any method that would deal with every type of polygon. I hope I am wrong because that means I have wasted 3 days of research. – silvio progonati May 8 at 18:00
  • This is not as simple as I thought, but it was a nice challenge. See one possible answer below. – TomazicM May 14 at 20:49
1

Below is one possible solution using Turf library. Solution is not exact since Turf does not have method to split polygon with line and get as result two split polygons.

The closest method is turf.difference(poly1, poly2), which cuts out second polygon from first. If second polygon is very thin and long rectangle (line with small 'height'), this can be used as split method, where first polygon is split by second.

This is done in two steps. First step is to 'fatten' dividing line to one side (let's call it upper), cut polygon by it and take into account split polygon one the other (lower) side of the line. Then dividing line is 'fattened' to the other side (lower), polygon is cut by it and split polygon on upper side is taken into account.

Code below has been tested, but is more or less proof of concept and not very robust. Parameters polygon and line are considered to be geometries.

function cutPolygon(polygon, line, direction, id) {
  var i = -1;
  var j;
  var polyCoords = [];
  var retVal = null;

  if ((polygon.type != 'Polygon') || (line.type != 'LineString')) return retVal;
  if (line.coordinates.length != 2) return retVal;

  var intersectPoints = turf.lineIntersect(polygon, line);
  var nPoints = intersectPoints.features.length;
  if ((nPoints == 0) || ((nPoints % 2) != 0)) return retVal;

  var offsetLine = turf.lineOffset(line, (0.01 * direction), {units: 'kilometers'});
  var thickLineCorners = turf.featureCollection([line, offsetLine]);
  var thickLinePolygon = turf.convex(turf.explode(thickLineCorners));

  var clipped = turf.difference(polygon, thickLinePolygon);

  for (j = 0; j < clipped.geometry.coordinates.length; j++) {
    var polyg = turf.polygon(clipped.geometry.coordinates[j]);
    var overlap = turf.lineOverlap(polyg, line, {tolerance: 0.005});
    if (overlap.features.length > 0) {
      polyCoords[++i] = turf.coordAll(polyg);
    };
  };

  if (i == 0)
    retVal = turf.polygon(polyCoords, {id: id});
  else if (i > 0) {
    retVal = turf.multiPolygon([polyCoords], {id: id});
  }

  return retVal;
};

var upperCut = cutPolygon(polygon, line, 1, 'upper');
var lowerCut = cutPolygon(polygon, line, -1, 'lower');

Working fiddle is available at https://jsfiddle.net/TomazicM/2rdbcmL0/. If line is drawn across polygon, it will be split along line.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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