Skip to content

pointInShape returns incorrect value for multi-island polygons #26

@bryhoyt

Description

@bryhoyt

For polygons with holes that have sub-polygons (islands) inside the holes, pointInShape will incorrectly return false in many scenarios where it should return true.

In the test below (which is inside a loop on this.paths):

if (!pointInPath && orientation || pointInPath && !orientation) {
  return false;
}

if there is at least one island where the condition !pointInPath && orientation holds true (and if there are multiple non-overlapping islands, there can be at most one which contains the point, so there will always be at least one which does not contain the point) then the function will exit and report the point is not in the shape -- even though it may be in one of the islands.

I've replaced it in my own code with the following, which you're welcome to use. Note that it also handles nested islands:

function pointInSubPolys(point) {
    const indices = [...this.paths.keys()];
    const polys = indices.filter((idx) => this.orientation(idx) && this.pointInPath(idx, point));
    const holes = indices.filter((idx) => !this.orientation(idx) && this.pointInPath(idx, point));
    // Important: just being in a hole poly does not mean it's in the hole, because it
    // could be in an island *inside* the hole. So check the even/odd count.
    const inShape = polys.length && polys.length % 2 !== holes.length % 2;
    return inShape ? polys : undefined;
}

public pointInShape(point) {
    return Boolean(this.pointInSubPolys(point));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions