drufat / triangle

Python bindings to the triangle library
GNU Lesser General Public License v3.0
224 stars 53 forks source link

holes in triangulation #23

Closed mikedh closed 6 years ago

mikedh commented 6 years ago

Hey, thanks for this package- I'm looking in to switching from meshpy to this. I noticed that holes don't appear to be making it to triangle. If the holes are passed to the plotting helper function it creates a marker for the hole, but is triangulated over:

hole_example

Code to reproduce:

import triangle
import triangle.plot
import matplotlib.pyplot as plt

import numpy as np

if __name__ == '__main__':
    ### generate a circle with a hole in it                         
    theta = np.linspace(0.0, np.pi * 2, 25)
    circle = np.column_stack((np.cos(theta),
                              np.sin(theta)))

    # exterior plus interior                                        
    vertices = np.vstack((circle, circle * .5))
    segments = np.column_stack((np.arange(0, len(circle) - 1),
                                np.arange(1, len(circle))))
    # add the interior                                              
    segments = np.vstack((segments,
                          segments + len(circle)))

    # the hole is in the middle. like a doughnut                    
    holes = np.array([[0,0]], dtype=np.float64)

    # args to pass to triangulate                                   
    args = {'segments': segments,
            'vertices': vertices,
            'holes':    holes}
    B = triangle.triangulate(args)

    triangle.plot.compare(plt, args, B)
    plt.show()
mdsumner commented 6 years ago

Triangle itself can accept a "seed point" for each hole, and it will cull them out from the inside - but otherwise get the centroids of the resulting triangles and classify them by in-polygon test with your inputs and cull from that.

The interface accepts these seed points, search for "hole" here: http://dzhelil.info/triangle/

mikedh commented 6 years ago

Thanks for looking- I am passing holes (an (n,2) array of seed points) in the example above. I think the data isn't making it where it needs to go in this wrapper, as the same logic works properly in the meshpy.triangle wrapper.

mdsumner commented 6 years ago

Ah, sorry about that - reacted too fast! It's great to have an example to follow - I'm keen to learn Python.

mikedh commented 6 years ago

Actually, this was the result of my segments not being closed, when that was fixed it worked fine:

import triangle
import triangle.plot
import matplotlib.pyplot as plt

import numpy as np

if __name__ == '__main__':
    ### generate a circle with a hole in it                         
    theta = np.linspace(0.0, np.pi * 2, 25)
    circle = np.column_stack((np.cos(theta),
                              np.sin(theta)))

    # exterior plus interior                                        
    vertices = np.vstack((circle, circle * .5))
    segments = np.column_stack((np.arange(0, len(circle) - 1),
                                np.arange(1, len(circle))))
    # make sure segments are closed
    segments %= len(circle) - 1

    # add the interior                                              
    segments = np.vstack((segments,
                          segments + len(circle) + 1))

    # the hole is in the middle. like a doughnut                    
    holes = np.array([[0,0]], dtype=np.float64)

    # args to pass to triangulate                                   
    args = {'segments': segments,
            'vertices': vertices,
            'holes':    holes}

    t = triangle.triangulate(args, 'pq0D')
    triangle.plot.plot(plt.axes(), **t)
    plt.show()

In testing, triangle.triangulate was pretty much exactly twice as fast as meshpy.triangle and has a nicer API. After testing, I changed the default in trimesh to use triangle.triangulate- thanks for the great package!