alexbol99 / flatten-js

Javascript library for 2d geometry
MIT License
535 stars 56 forks source link

Infinite Loop when calling unify for multipolygon with touching faces #171

Closed axtavt closed 3 months ago

axtavt commented 3 months ago

Attempt to unify polygons when one of them is a particular multipolygon with touching faces (valid) causes Error: Cannot complete boolean operation:

const a = new Flatten.Polygon([
    [
        point(70, 10),
        point(80, 10),
        point(80, 50),
        point(70, 50),
    ],
    [
        point(90, 10),
        point(100, 10),
        point(100, 50),
        point(90, 50),
    ],
    [
        point(100, 0),
        point(120, 0),
        point(120, 10),
        point(100, 10),
    ],
]);
const b = new Flatten.Polygon([ point(0, 0), point(100, 0), point(100, 10), point(0, 10) ]);

const c = Flatten.BooleanOperations.unify(a, b); // Error: Cannot complete boolean operation

It's caused by incorrect heaviour of ray_shoot() for such a mutlipolygon:

const polygon = new Flatten.Polygon();
polygon.addFace([ point(90, 10), point(100, 10), point(100, 50), point(90, 50) ]);
polygon.addFace([ point(100, 0), point(120, 0), point(120, 10), point(100, 10) ]);

let contains = ray_shoot(polygon, point(85, 10)); // should be OUTSIDE, returns INSIDE instead
axtavt commented 3 months ago

Created PR #172

axtavt commented 3 months ago

Case 2 - incorrect result of ray_shoot() for polygon with self-touching face:

const polygon = new Flatten.Polygon();
polygon.addFace([
    point(90, 10), point(100, 10), point(100, 50), point(110, 50), point(110, 10), point(100, 10), point(100, 0),
    point(120, 0), point(120, 60), point(90, 60)
]);

let contains = ray_shoot(polygon, point(85, 10)); // should be OUTSIDE, returns INSIDE instead
axtavt commented 3 months ago

Created PR #173

alexbol99 commented 3 months ago

Hi @axtavt , Thank you so much for your contribution I will check your PR's

alexbol99 commented 3 months ago

Hello @axtavt , You PR is great but I made a small change: when sorting intersection points, I added sorting by face_index and then by edge arc_length, that ensure that two points originated from same edges, will be neighbors in sorted array. Then if the first point is counted, second one is ignored. Thank you for noticing and fixing this problem.

alexbol99 commented 3 months ago

Fixed release in v1.5.2