haplo31
haplo31

Reputation: 75

Hide leaflet features out of specified area

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

Upvotes: 1

Views: 898

Answers (1)

tsamaya
tsamaya

Reputation: 396

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/

Upvotes: 1

Related Questions