1
votes

I'm trying to hide some leaflet features outside of a defined area.

I have a leaflet map displaying rivers as features on a RiverLayer and a circleLayer used to draw an area around the current center of the map.

Each river is separated in multiple parts inside my database and I retrieve only the parts intersecting with my current circle area.

The result look like this: exampleRivers

The rivers are showing outside the area, because I selected the parts intersecting with it. I could select in my database all the parts within the area but I would lose the parts that are not entirely inside the area.

Calculating the intersection point for each part concerned in order to adjust the coordinates would be a solution but a complex one.

In fact, I would prefer to simply hide these overflows on the client side but I can't find a solution.

Is there a possibility with leaflet to do something like this?

Thanks for you time

1
I would definitely look at turf to crop data before displaying it turfjs.orgtsamaya
Yeah i saw turf and it could be a solution. But it seems I would need to do a lot of calculations myself (for a river part, I would need to filter each geojson point to verify the distance, remove the points outside the area, calculate the intersection point between my circle and my river part, and add this intersection point to the start or end of the river part depending on the distance from each...). Or maybe there is an existing function in Turf but I didn't found it.haplo31
indeed it would be easy with a square or rectangle with the clip function turfjs.org/docs/#bboxClip . with point and polygon pointsWithin is doing the job turfjs.org/docs/#pointsWithinPolygontsamaya
Pls share a online demo f.e. on jsfiddle.netFalke Design

1 Answers

1
votes

Here is an example using turfJS using the booleanWithin and lineSplit functions. enter image description here

I did the example on a simple basic HTML and Vanilla JS. I added another linestring on the "river" to simulate an outside the circle river


var mymap = L.map('mapid').setView([43.63458105967136, 1.1613321304321291], 13);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 20,
    attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors',
}).addTo(mymap);

var center = [43.63458105967136, 1.1613321304321291];
var radius = 1500;

// L.circle(center, radius, {
//     color: '#ff4081', fillColor: '#ff4081', fillOpacity: 0.5
// }).addTo(mymap);

var riverGeoJSON = [
    { "type": "Feature", "geometry": { "coordinates": [[1.159444487444759, 43.633815447205706], [1.160243520516838, 43.634633600388156], [1.160731009187281, 43.6350432633719], [1.161774921971743, 43.63541373375439], [1.162079879908259, 43.63564209781788], [1.162320030539753, 43.635959368371424], [1.162373764624914, 43.636409391647234], [1.161800286153361, 43.637212422659154], [1.160910734693605, 43.63832601539633], [1.160651867030764, 43.63886255455486], [1.160332394101095, 43.639317964879666], [1.159189872203288, 43.640743176542664], [1.158053840843969, 43.641810274789506], [1.156922548158863, 43.642651534145514], [1.155851918485514, 43.64349381183714], [1.155156982509935, 43.644214650781954], [1.15326441791592, 43.64594659208024], [1.152374775964331, 43.6470151231795], [1.151428904349222, 43.64790448439313], [1.151107886218696, 43.64840394819371]], "type": "LineString" } },
    { "type": "Feature", "geometry": { "coordinates": [[1.156570800342349, 43.632121495293006], [1.158291185472127, 43.63272397754135], [1.158901458643683, 43.633090727638866], [1.159444487444759, 43.633815447205706]], "type": "LineString" } },
    { "type": "Feature", "geometry": { "coordinates": [[1.168152938761366, 43.62917262321181], [1.167467920251437, 43.62939958202886], [1.166101976396903, 43.62960874939632], [1.164673843635074, 43.629863651007135], [1.163738326615552, 43.63021236020524], [1.163236303364402, 43.630566588076604], [1.162728104605807, 43.63119071739829], [1.161282685092185, 43.632253508072225], [1.160336935333006, 43.633151033736986], [1.159444487444759, 43.633815447205706]], "type": "LineString" } },
    {
        "type": "Feature",
        "properties": {},
        "geometry": {
            "type": "LineString",
            "coordinates": [
                [
                    1.0526275634765625,
                    43.550289946081115
                ],
                [
                    1.07940673828125,
                    43.63334186269
                ],
                [
                    1.0764884948730469,
                    43.6336524704596
                ]
            ]
        }
    }
];
// L.geoJSON(riverGeoJSON, {}).addTo(mymap);

var centerGeoJSON = [center[1], center[0]];
var radiusGeoJSON = radius / 1000;
var options = { steps: 50, units: 'kilometers' };
var circleGeoJSON = turf.circle(centerGeoJSON, radiusGeoJSON, options);

L.geoJSON(circleGeoJSON, {}).addTo(mymap);

var riverClipped = {}

for (let index = 0; index < riverGeoJSON.length; index++) {
    const feature = riverGeoJSON[index];
    var within = turf.booleanWithin(feature, circleGeoJSON);
    console.log({ within });
    var split = turf.lineSplit(feature, circleGeoJSON);
    console.log({ split });
    if (within && split.features.length === 0) {
        L.geoJSON(feature, {}).addTo(mymap);
    } else {
        L.geoJSON(split.features[0], {}).addTo(mymap);
    }


}


Circle is calculated with turfJS to have a valid GeoJSON feature. This feature is then used as a splitter.

When line is completely inside the circle, the within function returns true, the split function doesn't return a split feature.

When line is completely outside the circle, the within function is false and the split function doesn't return a split feature.

When the line intersect the circle, the within function returns false, and the first feature from the split feature collection is the one inside the circle.

Complete source code on JSFiddle: https://jsfiddle.net/tsamaya/6sc58m7u/