alexbol99 / flatten-js

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

Infinite Loop when calling unify on polygons #94

Closed cmy235 closed 1 year ago

cmy235 commented 3 years ago

I consistently see this error from the .testInfiniteLoop check. It generally happens when two polygons share points and one is contained inside the other. I am working with 2D geoJSON coordinate data (epsg:4326), see img below for polygons being compared (p0 = dark, p1 = light)

I originally thought was tied to the floating points based on previous issues, but it persists after rounding. Before calls to unify I check that the polygon is valid and the face simple.

I am using v1.2.24 and also tested with 1.2.22.

   const p0 = new Polygon([
        [-81.658177, 28.354585],
        [-81.658176, 28.354642],
        [-81.657906, 28.354638],
        [-81.657907, 28.354582],
        [-81.657908, 28.354526],
        [-81.658178, 28.354529]
    ])

    const p1 = new Polygon([
        [-81.6579063, 28.3546095],
        [-81.657906, 28.354638],
        [-81.658176, 28.3546417],
        [-81.6581764, 28.354613], 
    ])

    unify(p0,p1)
Screen Shot 2021-08-12 at 1 47 43 PM
alexbol99 commented 2 years ago

Hello @cmy235 ,

Sorry for delay with response. Infinite loop happens because of numeric errors when two close segments intersect. I cannot overcome this problem completely, but I can suggest workaround. You may scale you polygons before performing operation:

            const m = new Flatten.Matrix().scale(1e6, 1e6);

            p0 = p0.transform(m);
            p1 = p1.transform(m);

I also found that two polygons have different orientations, it may be fixed like this:

            if ([...p0.faces][0].orientation() != [...p1.faces][0].orientation()) {
                p1 = p1.reverse();
            }

Then unfy will succeed. In this case. Hope it was helpful

Thanks, Alex Bol