21re / rust-geo-booleanop

Rust implementation of the Martinez-Rueda Polygon Clipping Algorithm
MIT License
95 stars 28 forks source link

Panic "assembly segments must be eulierian" when taking difference of two Multipolygons. #37

Open RevolutionXenon opened 10 months ago

RevolutionXenon commented 10 months ago

I am getting the error "assembly segments must be eulierian" when taking the difference of two multipolygons.

I have graphed my two multipolygons in Desmos: image

I am taking the difference between the red and the blue multipolygons, such that I expect the result to be the small red triangle.

Here's the two multipolygons as rust objects:

    let red = MultiPolygon::new(
        vec![
            Polygon::new ( 
                LineString(vec![
                    Coord { x: -1.3119198, y: 0.9937218 }, 
                    Coord { x: -1.3202608, y: 1.0020628 }, 
                    Coord { x: -1.3415047, y: 0.95909566 }, 
                    Coord { x: -1.3119198, y: 0.9937218 },
                ]), 
                vec![]
            ), 
            Polygon::new ( 
                LineString(vec![
                    Coord { x: -1.2180908, y: 1.1035395 }, 
                    Coord { x: -1.1915252, y: 1.1346318 }, 
                    Coord { x: -1.2249147, y: 1.1949053 }, 
                    Coord { x: -1.252885, y: 1.1383337 }, 
                    Coord { x: -1.2180908, y: 1.1035395 },
                ]), 
                vec![]
            ),
        ]
    );
    let blue = MultiPolygon::new(
        vec![
            Polygon::new ( LineString(vec![
                Coord { x: -1.1199157, y: 1.0053644 }, 
                Coord { x: -1.2621856, y: 1.2621856 }, 
                Coord { x: -1.3197794, y: 1.2052281 }, 
                Coord { x: -1.1199157, y: 1.0053644 }]), 
                vec![]
            ),
        ]
    );

Whatever is causing this operation to fail is subtle enough that what I have for you here is not enough decimal places to replicate it, I'm sorry I cannot provide a better test case right away. I will say that upgrading from f32 to f64 in my code did not fix the issue.

I am doing a lot of difference operations, so the red multipolygon was not generated by hand, but is the result of several differences. I seem to be able to do almost identical operations tens of thousands of times with different multipolygons before this issue is encountered. You can imagine there would have been other polygons, sharing edges to the left and right of the blue polygon, which have already been used to take a difference, making it such that the right piece of the red multipolygon essentially shares its exact edges with the blue triangle. Perhaps some subtlety exists where no floating point error whatsoever occurred in my special case and the two edges being exactly co-linear causes the algorithm to fail.

michaelkirk commented 8 months ago

That error message doesn't appear in this crate, but it does appear in geo's implementation of booleanops.

It's possible you are experiencing https://github.com/georust/geo/issues/1103