Search code examples
javascriptangularjsleafletpolygonangular-leaflet-directive

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.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
  ]
]

The child is drawn inside the parent area as shown in the picture: enter image description here

Using Ray Casting algorithm to determine if the point lies inside polygon I 'm not able to determine as the result I'm getting is false. Please let me know where I'm doing wrong or any other way to determine the solution.Thanks


Solution

  • 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));
        }
    }