Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion web/src/types/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,17 @@ export class Polygon {
}

public contains(v: Point): boolean {
return this.vertices.some(p => p.x === v.x && p.y === v.y);
// Ray casting algorithm for point-in-polygon test
let inside = false;
for (let i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {
const xi = this.vertices[i].x, yi = this.vertices[i].y;
const xj = this.vertices[j].x, yj = this.vertices[j].y;

const intersect = ((yi > v.y) !== (yj > v.y)) &&
(v.x < (xj - xi) * (v.y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
Comment on lines 65 to 104
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The new implementation correctly identifies points strictly inside the polygon, which fixes the described bug. This is a great improvement!

However, there's a subtle change in behavior for points on the boundary. The previous implementation returned true for vertices, but the new ray-casting algorithm will return false for all points on the boundary, including vertices.

This could lead to unexpected behavior if other parts of the code rely on contains being true for vertices.

To restore the previous behavior for vertices while keeping the new, correct check for interior points, I suggest adding the vertex check back at the beginning of the method. This is a minimal change that addresses the regression for vertices.

Note that with this change, points on an edge that are not vertices will still be considered outside. A full boundary check would be more robust but also more complex.

    public contains(v: Point): boolean {
        // The previous implementation returned true for vertices. To maintain this behavior
        // for vertices while correctly checking for interior points, we can check for
        // vertex containment first. Note that other points on the boundary will still
        // be considered outside with this approach.
        if (this.vertices.some(p => p.x === v.x && p.y === v.y)) {
            return true;
        }

        // Ray casting algorithm for point-in-polygon test
        let inside = false;
        for (let i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {
            const xi = this.vertices[i].x, yi = this.vertices[i].y;
            const xj = this.vertices[j].x, yj = this.vertices[j].y;

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


public forEdge(f: (v0: Point, v1: Point) => void): void {
Expand Down