martinez icon indicating copy to clipboard operation
martinez copied to clipboard

Wrong result for two simple polygons

Open abelramos opened this issue 5 years ago • 14 comments

These are my two simple polygons:

Two simple polygons

with coordinates:

[[115,96], [140,206], [120,210], [125,250], [80,300]]
[[111,228], [129,192], [309,282]]

And this is the resulting union:

Wrong resulting union

There are no vertical edges, in fact, no two points share the same x-coordinate. I believe the issue here is with the otherInOut property not being correctly computed as these are the sweep events with otherInOut set to true after the subdivision step:

Sweep events with otherInOut set to true

I also tried with the C++ code available online from the original paper, and the resulting union is the same.

abelramos avatar Dec 28 '19 07:12 abelramos

Thanks for the detailed example and the C++ reference, I will try and figure it out

w8r avatar Dec 30 '19 17:12 w8r

@abelramos Until this gets fixed, I have found that adding very small (like 0.0005), pseudorandom values to the coordinates will prevent this. The problem occurs when a point falls exactly on another line. Our app has grid snapping, I can confirm that this happens all the time.

jakeNiemiec avatar Dec 30 '19 18:12 jakeNiemiec

I have tested this case with polybooljs (another implementation of the Martinez algorithm) and there it seems to work:

Input: bug_110_input

Output: bug_110_output

So maybe it helps to have a look where the implementations differ.

bluenote10 avatar Jan 06 '20 09:01 bluenote10

It's not exactly the same algorithm, but thanks for the reference!

w8r avatar Jan 06 '20 09:01 w8r

I also tried with the C++ code available online from the original paper...

It's not exactly the same algorithm

Ah interesting, I was wondering about that already. What is this implementation here actually based on? I've found three "original" versions of the Martinez algorithm:

bluenote10 avatar Jan 06 '20 09:01 bluenote10

it's the last one

w8r avatar Jan 06 '20 09:01 w8r

@abelramos Until this gets fixed, I have found that adding very small (like 0.0005), pseudorandom values to the coordinates will prevent this. The problem occurs when a point falls exactly on another line. Our app has grid snapping, I can confirm that this happens all the time.

Exactly. I can also confirm it is not related to floating-point arithmetic and/or epsilon values, I tested the implementation with a type for rational numbers, and the issue remains.

abelramos avatar Jan 06 '20 18:01 abelramos

I have tested this case with polybooljs

Yes, I tried with that one too. It works. However, I believe this implementation is faster than the other one, that's why I'm interested in a fix for this one.

abelramos avatar Jan 06 '20 18:01 abelramos

afair the other one uses only linked lists (instead of a tree), plus solid improvements don't seem to get merged for... reasons

daef avatar Jan 07 '20 09:01 daef

I would love to get some help here, I didn't have time to look at it recently

w8r avatar Jan 07 '20 09:01 w8r

afair the other one uses only linked lists (instead of a tree)

Exactly, I came to the same conclusion here after reading the code a bit.

I would love to get some help here, I didn't have time to look at it recently

I'd like to have a look, but I don't have access to the paper :(.

bluenote10 avatar Jan 07 '20 19:01 bluenote10

@bluenote10 if you send me an email me at rowanwinsemius dot id dot au , then I can supply the paper

rowanwins avatar Jan 07 '20 21:01 rowanwins

I'm working on my own implementation of the Martinez paper, and I started there from the original implementation in C++ that they published (I need integer coordinates). Since I was having the same issue: here's what I tracked what was going wrong:

When the status line reaches point (120, 210), the line segments starting at (120,210) are incorrectly inserted between segment (111,228)-(129,192) and (80,300)-(115,96). This causes the segments to have the wrong neighbors.

So what likely needs work, is the segment comparer. I noticed that you're using a comparer somewhat similar to the C++ version so I'm guessing that's also going to apply here. When I made sure the segment comparer ordered them correctly for this one use case, the correct result was being computed.

svenboulanger avatar May 19 '23 20:05 svenboulanger

Thank you so much ! I will try that

On Fri, 19 May 2023 at 22:25, Sven @.***> wrote:

I'm working on my own implementation of the Martinez paper, and I started there from the original implementation in C++ that they published (I need integer coordinates). Since I was having the same issue: here's what I tracked what was going wrong:

When the status line reaches point (120, 210), the line segments starting at (120,210) are incorrectly inserted between segment (111,228)-(129,192) and (80,300)-(115,96). This causes the segments to have the wrong neighbors.

So what likely needs work, is the segment comparer. I noticed that you're using a comparer somewhat similar to the C++ version so I'm guessing that's also going to apply here. When I made sure the segment comparer ordered them correctly for this one use case, the correct result was being computed.

— Reply to this email directly, view it on GitHub https://github.com/w8r/martinez/issues/110#issuecomment-1555198208, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAGSBFCZSHJ4FRJTFJKU2DXG7JKXANCNFSM4KAIIFEQ . You are receiving this because you were assigned.Message ID: @.***>

w8r avatar May 19 '23 23:05 w8r