Skip to content Skip to sidebar Skip to footer

Check If A Polygon Point Is Inside Another In Leaflet

I'm having two sets of polygon coordinates selected from leaflet geoJSON map. The parent and child coordinates are coordinates are: var parentCoordinates=[ [ 32.0589822

Solution 1:

I've had good experience with Turf. It works well, is well documented and the examples are already shown with leaflet.

For your problem, you could use turf.within with parentCoordinates as turf.polygon and childCoordinates as an array of turf.point :

var parentPolygon = turf.polygon([parentCoordinates]);

var inside = true;
childCoordinates.forEach(function(coordinates) {
    point = turf.point(coordinates);
    if (!turf.inside(point, parentPolygon)){
      alert("Oh no! "+ coordinates + " isn't in polygon");
      inside = false;
    }
});

alert("Child polygon inside parent polygon ? " + inside);

Here's a Fiddle example.


Solution 2:

I tried with your algorithm and another found here https://rosettacode.org/wiki/Ray-casting_algorithm and both return the right value.

Maybe this fiddle can help you in the implementation :

https://jsfiddle.net/4psL2hoo/1/

Your algo

// Data
var parentCoordinates=[
    [
        32.05898221582174,
        -28.31004731142091
    ],
    [
        32.05898221582174,
        -28.308044824292978
    ],
    [
        32.06134255975485,
        -28.308044824292978
    ],
    [
        32.06134255975485,
        -28.31004731142091
    ],
    [
        32.05898221582174,
        -28.31004731142091
    ]
]
var childCoordinates=[
  [
    32.059904895722866,
    -28.30970726909422
  ],
  [
    32.059904895722866,
    -28.308743809931784
  ],
  [
    32.06089194864035,
    -28.308743809931784
  ],
  [
    32.06089194864035,
    -28.30970726909422
  ],
  [
    32.059904895722866,
    -28.30970726909422
  ]
]

// Other algo
function test(point, vs) {
    // ray-casting algorithm based on
    // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html

    var x = point[0], y = point[1];

    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i][0], yi = vs[i][1];
        var xj = vs[j][0], yj = vs[j][1];

        var intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }

    return inside;
};

for (var i = 0; i < childCoordinates.length; i++) {
     var testPoint = childCoordinates[i];
     console.log(JSON.stringify(testPoint) + '\tin parentCoordinate\t' + test(testPoint, parentCoordinates));
}

Rosetta code algo

//https://rosettacode.org/wiki/Ray-casting_algorithm
function contains(bounds, lat, lng) {
    //https://rosettacode.org/wiki/Ray-casting_algorithm
    var count = 0;
    for (var b = 0; b < bounds.length; b++) {
        var vertex1 = bounds[b];
        var vertex2 = bounds[(b + 1) % bounds.length];
        if (west(vertex1, vertex2, lng, lat))
            ++count;
    }
    return count % 2;

    /**
     * @return {boolean} true if (x,y) is west of the line segment connecting A and B
     */
    function west(A, B, x, y) {
        if (A.y <= B.y) {
            if (y <= A.y || y > B.y ||
                x >= A.x && x >= B.x) {
                return false;
            } else if (x < A.x && x < B.x) {
                return true;
            } else {
                return (y - A.y) / (x - A.x) > (B.y - A.y) / (B.x - A.x);
            }
        } else {
            return west(B, A, x, y);
        }
    }
}

var square = {name: 'square', bounds: [{x: 32.05898221582174, y: -28.31004731142091}, {x: 32.05898221582174, y: -28.308044824292978}, {x: 32.06134255975485, y: -28.308044824292978}, {x: 32.06134255975485, y: -28.31004731142091}]};

var shapes = [square];
var testPoints = [{lng: 32.059904895722866, lat: -28.30970726909422}, {lng: 32.059904895722866, lat: -28.308743809931784}, {lng: 32.06089194864035, lat: -28.308743809931784},
    {lng: 32.06089194864035, lat: -28.30970726909422}];

for (var s = 0; s < shapes.length; s++) {
    var shape = shapes[s];
    for (var tp = 0; tp < testPoints.length; tp++) {
        var testPoint = testPoints[tp];
        console.log(JSON.stringify(testPoint) + '\tin ' + shape.name + '\t' + contains(shape.bounds, testPoint.lat, testPoint.lng));
    }
}

Solution 3:

You can try Leaflet's api for that - contains . You create a parent polygon with LatLngBounds and then child too.

parentPolygon.contains(childPolygon)

Post a Comment for "Check If A Polygon Point Is Inside Another In Leaflet"