2

I am getting some weird result with turf.mask().

This is the polygon I am trying to run the mask() function with: https://gist.githubusercontent.com/Stophface/50155878441205412001247878f58b63/raw/324021868304f96c795e7d8cd18ec2c6f45ee842/polygon.geojson

Raw data

According to the docs, if the mask is undefined, the world extent is used. The result of turf.mask(polygon, undefined) is this

Result of mask

https://gist.githubusercontent.com/Stophface/50155878441205412001247878f58b63/raw/5e71fc1c4e4d6815cfa22e15eb1bf10c9208231f/mask_result.geojson

So it is filling the interior ring Why is it doing that?

The data for the second code snippet of the accepted answere (because I deleted the original question) https://gist.github.com/Stophface/5f0cf7a28466d47f07c83d6d26eba078

2
  • Definition of Turf.js mask method states that it "returns a polygon exterior ring with holes". What you want to have is "antihole" in a hole, which mask is not capable of. Such a polygon would be multipolygon, see stackoverflow.com/questions/74660981/….
    – TomazicM
    Commented Feb 8, 2023 at 15:45
  • @TomazicM Hm... Is there any way I can achieve that?
    – four-eyes
    Commented Feb 8, 2023 at 15:59

1 Answer 1

2

There might be simpler way of solving this problem by using some library, but one possible way with only Turf.js would be to:

  • create array of outer liner rings and array of inner linear rings of polygon (with later reverse coordinate order);
  • create multi polygon from outer linear rings and mask it;
  • get linear rings of created masked polygon and append saved inner liner rings;
  • create multi polygon from this array of rings.

Code could then look something like this:

var coords = turf.getCoords(polygon);

var outerRings = [];
var innerRings = [];

coords.forEach(function(polyCoords) {
  polyCoords.forEach(function(linearRing, i) {
    if (i == 0)
      outerRings.push(linearRing);
    else {
      var poly = turf.rewind(turf.polygon([linearRing]));
      innerRings.push(turf.getCoords(poly)[0]);
    }
  })
});
var outerRingsPoly = turf.multiPolygon([outerRings]);

var maskedOuterRingsPoly = turf.mask(outerRingsPoly);
var maskedOuterRings = turf.getCoords(maskedOuterRingsPoly);
var allRings = maskedOuterRings.concat(innerRings);

var finalPoly = turf.multiPolygon([allRings]);

Result then looks like this:

enter image description here

EDIT: When testing again with GeoJSON with several holes, turf.js complained executing var coords = turf.getCoords(polygon), so I had to change logic a bit.

Here is modified code:

var outerRings = [];
var innerRings = [];

turf.geomEach(polygon, function(geom) {
  geom.coordinates[0].forEach(function(linearRing, i) {
    if (i == 0)
      outerRings.push(linearRing);
    else {
      var poly = turf.rewind(turf.polygon([linearRing]));
      innerRings.push(turf.getCoords(poly)[0]);
    }
  });
});

var outerRingsPoly = turf.multiPolygon([outerRings]);

var maskedOuterRingsPoly = turf.mask(outerRingsPoly);
var maskedOuterRings = turf.getCoords(maskedOuterRingsPoly);
var allRings = maskedOuterRings.concat(innerRings);

var finalPoly = turf.multiPolygon([allRings]);

And here the result:

enter image description here

7
  • That works really very well. I build a more complex function handling more cases upon your answer and posted it here too, for others to reuse. However, there is one case which I cannot seem to handle. When there is a hole in an Polygon, that exceeds the polygons boundaries. In my posted answer this is the case with the square geometry. Do you have a hot hint, how to handle this situation?
    – four-eyes
    Commented Feb 20, 2023 at 19:00
  • GIS SE site has policy of focused questions, which means one question per question. If you have a new/additional question, please post it as a separate question.
    – TomazicM
    Commented Feb 20, 2023 at 19:24
  • I deleted my previous follow up question and here is a new one gis.stackexchange.com/questions/452807/…
    – four-eyes
    Commented Feb 24, 2023 at 11:19
  • See modified answer.
    – TomazicM
    Commented Feb 24, 2023 at 11:22
  • Thanks a lot. Displaying it somewhere else than geojson.io works!
    – four-eyes
    Commented Feb 24, 2023 at 12:03

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.