lycantropos / sect

Geometric partitioning (triangulation, trapezoidal decomposition)
https://sect.rtfd.io
MIT License
26 stars 4 forks source link

Holes in a contour #9

Closed thomaskilian closed 10 months ago

thomaskilian commented 10 months ago

Hi, I'm trying to figure out, how to pass holes with the contours. The constrained_delaunay seems to be able to deal with that but from the documentation I could not find out how.

lycantropos commented 10 months ago

Hi @thomaskilian, to pass a contour with holes (which themselves are also contours) -- just construct a Polygon, its constructor accepts border with holes. This is an example.

Hope this helps.

thomaskilian commented 10 months ago

Hi @lycantropos Thanks for the quick feedback. Unfortunately that will raise an error. I tried a small square inside a square: x = Triangulation.constrained_delaunay( Polygon(Contour([Point(0, 0), Point(4, 0), Point(4, 4), Point(0, 4), Point(0, 0)]), [Contour([Point(1, 1), Point(1, 2), Point(2, 2), Point(2, 1), Point(1, 1)])]), context=context ).triangles() and it croaks like

File "/Users/thomaskilian/Downloads/tri.py", line 8, in x = Triangulation.constrained_delaunay( File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/sect/core/delaunay/triangulation.py", line 116, in constrained_delaunay cut(result, holes) File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/sect/core/delaunay/triangulation.py", line 279, in cut for event in events_queue.sweep(): File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/sect/core/delaunay/events_queue.py", line 170, in sweep and self.detect_intersection(event, above_event)): File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/sect/core/delaunay/events_queue.py", line 94, in detect_intersection raise ValueError('Edges of the same polygon '

lycantropos commented 10 months ago

@thomaskilian : it's because your first vertex and the last vertex are equal, when they shouldn't (since it's redundant), try

x =  Triangulation.constrained_delaunay( Polygon(Contour([Point(0, 0), Point(4, 0), Point(4, 4), Point(0, 4)]), [Contour([Point(1, 1), Point(1, 2), Point(2, 2), Point(2, 1)])]), context=context ).triangles()

instead

thomaskilian commented 10 months ago

Well, that definitely looks better :-) The geo-libs usually provide ring objects witth first and last point the same (redundance I found strange) so I adopted that. Thanks again!

thomaskilian commented 10 months ago

Sorry to bother you once more. But how would I pass a figure like this:

Bildschirmfoto 2023-12-20 um 18 53 57

It does not see the dent top left and returns <img width="253" alt="Bildschirmfoto 2023-12-20 um 19 06 24" src="https://github.com/lycantropos/sect/assets/69296/a32b2dc7-8045-4380-966a-07785be00a39">

I assume that I have to specifx that area as hole, right? Or is there an easier way?

lycantropos commented 10 months ago

like that

from ground.base import get_context

context = get_context()
Polygon = context.polygon_cls
Point = context.point_cls
Contour = context.contour_cls
assert Triangulation.constrained_delaunay(
        Polygon(Contour([Point(0, 0), Point(3, 0), Point(3, 3), Point(1, 3),
                         Point(1, 2), Point(0, 2)]), []),
        context=context
).triangles() == [
           Contour([Point(1, 2), Point(3, 0), Point(3, 3)]),
           Contour([Point(0, 0), Point(3, 0), Point(1, 2)]),
           Contour([Point(1, 2), Point(3, 3), Point(1, 3)]),
           Contour([Point(0, 0), Point(1, 2), Point(0, 2)])
       ]

?

thomaskilian commented 10 months ago

WOW! You made someone very happy! :-)