Geojson/ turf : merge multiple polygons to one polygon keeping hole
Asked Answered
I

2

7

So I want to merge adjacent polygons in javascript this is what I actually have with my code:

map

I want to remove inside stroke but keep border stroke.

So I want to go from this:

map2

To this:

map3

I want to keep the hole for Paris - I can defined which polygons have to be grouped but I cannot merge them with this code:

var map = L.map('map', {
    center: [46.52863469527167, 2.43896484375],
    zoom: 6,
    maxZoom: 18,
    minZoom: 7
});
$http.get("france.json").then(function (response) {
    $scope.communeFr = response.data.features
    $http.get(apiult).then(function (response) {
        $scope.showCommune = response.data.Liste
        $scope.communeFr.map(x => {
            x.show = false
            for (let i = 0; i < $scope.showCommune .length; i++) {
                if (x.properties.insee == $scope.showCommune[i].insee) {
                    x.show = true
                    return
                }
            }                
        })
        L.geoJson($scope.communeFr, {
            filter: function (feature, latlng) {
                return feature.show 
            }
        }).addTo(map);
    });
    
});

UPDATE - I tried with turf.union but the output is not right:

map4

This is my code

var GroupPolygons = [];    
$scope.communeFr.map(x => {
    x.show = false
    for (let i = 0; i < $scope.showCommune .length; i++) {
        if (x.properties.insee == $scope.showCommune[i].insee) {
            GroupPolygons.push(x)
        }
    }                
})
var union = turf.union(...GroupPolygons)
L.geoJson(union).addTo(map)
Inanity answered 16/6, 2021 at 15:45 Comment(5)
The 2nd and 3rd images don't seem to tie to the 1st ?Hansiain
If you want to merge polygons use @turf/unionFinagle
@RobinMackenzie it's not the same image it's just to show u what I want exactlyInanity
@GrzegorzT. I already try to use turf.union, I guess I do something wrong I will show u my code and what I getInanity
I have created a generic tool to merge geojson features: github.com/abdurrahmanyildiz/geojson-feature-mergerThanasi
H
14

There seems to be an ambiguity in the turf docs concerning union regarding the number of polygons that can be passed as arguments. See here and here. Looks like it has to be two at a time - so this will work:

// feature ids to remove e.g. central Paris
var removeIds = [868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887];

// filter features to remove central Paris
var hole = fc.features.filter(f => !removeIds.includes(f.properties.ID_APUR))

// do the union over each feature
var union = hole[0];
for (let i=1; i<hole.length; i++) {
  union = turf.union(union, hole[i]);
}

I selected a bunch of central Paris to remove and then from the remaining features I start with feature 0 and then turf.join all the other features (from index 1 onward) to this one. Seems inefficient but works...

Small gotcha here:

// new Feature collection with unioned features
var fc2 = {
  "type": "FeatureCollection",
  "features": [union] // note features has to be an array
}

Remember to pass a FeatureCollection to L.geoJson and that the features property needs to be an array - even though in this case it contains a single feature of the merged areas.

Working example:

// center map on Paris
var map = L.map('mapid', {
    center: [48.856, 2.352],
    zoom: 9,
    maxZoom: 18,
    minZoom: 1
});

// add tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

var url = "https://gist.githubusercontent.com/robinmackenzie/937e5bd42a0412c21281f69b8f0c8614/raw/fbed7c2783366463a250e4bb0ebcf3c5f6d54dfe/greaterParis.geo.json";

// get greater Paris definition
fetch(url)
  .then(response => response.json())
  .then(fc => { 

    // feature ids to remove e.g. central Paris
    var removeIds = [868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887];

    // filter features to remove central Paris
    var hole = fc.features.filter(f => !removeIds.includes(f.properties.ID_APUR))

    // do the union over each feature
    var union = hole[0];
    for (let i=1; i<hole.length; i++) {
      union = turf.union(union, hole[i]);
    }

    // new Feature collection with unioned features
    var fc2 = {
      "type": "FeatureCollection",
      "features": [union] // note features has to be an array
    }

    // add to map
    L.geoJson(fc2).addTo(map);
  
  });
#mapid { height: 200px; }
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script src='https://unpkg.com/@turf/[email protected]/turf.min.js'></script>
<div id="mapid"></div>
Hansiain answered 17/6, 2021 at 15:51 Comment(3)
U ARE MY HERO thank you sooooooooooo muchInanity
@Inanity no worries, feel free to upvote if the solution helped you.Hansiain
Thank you Robin. If smb needs to merge features, I have created a generic tool to merge geojson features: github.com/abdurrahmanyildiz/geojson-feature-mergerThanasi
G
1

You can use reduce and turf.union method.

const polygons = [poly1, poly2, poly3, ..., polyn]
const union = polygons.reduce((a, b) => turf.union(a, b), polygons[0])
Girandole answered 19/5 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.