I'm trying to create a Voronoi diagram around 2D holes (preferably in PyGame or scipy, but not necessary) and save the edges. It should look something like this:
I have been able to use scipy's Voronoi to generate a diagram around points, but I'm not sure how to proceed with 2D obstacles.
My code for working with points is:
self.vor = Voronoi(POINTS)
# iterate over voronoi graph and save edges
for vpair in self.vor.ridge_vertices:
if vpair[0] >= 0 and vpair[1] >= 0:
# vertices
v0 = self.vor.vertices[vpair[0]]
v1 = self.vor.vertices[vpair[1]]
# edge endpoints
start_point = (v0[0], v0[1]) # start point
end_point = (v1[0], v1[1])
Basically, I want to input 2D obstacles (which could also be adjacent/touching so as to form a larger obstacle) and generate a set of lines which are equidistant from those obstacles.
The construction you need is a medial axis. One way of constructing an approximate medial axis is to generate a constrained Delaunay triangulation of the space between the holes. Edges of the medial axis are then formed by connecting the circumcentres of adjacent triangles. There's quite a good matlab tutorial here. Example 8 is the relevant bit.
Unfortunately, scipy doesn't have an implementation of constrained Delaunay triangulation. It just has unconstrained Delaunay triangulations and Vornoi diagrams, which are dual to each other. You will need something else. Triangle is commonly used, and appears to have python bindings.
I posted a mini python package to make it - voronoi-diagram-for-polygons. You can find an example output from here. It should be pointed out in advance that this package depends on v1.8.dev0 of shapely which is still in development. In other words, it cannot be installed by pip automatically. You have to install it by the following:
pip install git+https://github.com/Toblerity/Shapely.
Related
Similar to this question: Using just vertices to generate faces in PyMeshLab
I am looking for a function in either PyVista or PyMeshLab which constructs a mesh surface given vertices. However, my vertices already have normals. They were obtained with a laser scanner, so I used the estimate normals function in CloudCompare knowing the sensor locations that the points were obtained from. Therefore, all my point cloud normals are true surface normals. I want to preserve this information.
All I really need is to march through the cloud and connect the vertices with faces of their nearest neighbors. That is, I would like my point cloud to be the mesh vertices. No Delaunay triangulations or anything like that. No ball pivoting algorithm or Poisson reconstruction that skips over some points. My points are already subsampled and sparse.
Are there any functions that can do this? Maybe it is even easy to do manually.
Thank you.
For example, in this code, nbr_sz dictates the neighborhood of points to look around for estimating surface normals.
import pyvista as pv
bunny = pv.read("Stanford_Bunny.ply")
points = pv.wrap(bunny.points)
surf = points.reconstruct_surface(nbr_sz=10)
pl = pv.Plotter(shape=(1, 2))
pl.add_mesh(points)
pl.add_title("Point Cloud of 3D Surface")
pl.subplot(0, 1)
pl.add_mesh(surf, color=True, show_edges=True)
pl.add_title("Reconstructed Surface")
pl.show()
See https://docs.pyvista.org/api/core/_autosummary/pyvista.PolyDataFilters.reconstruct_surface.html#pyvista.PolyDataFilters.reconstruct_surface
I have verts and faces generated by skimage.measure.marching_cubes. How to find all points where a mesh intersects a plane? I would like to get something like this but
on python and scikit-image
As stated in the answer you referred, your starting point should be similar and the steps will be the same, regardless of python or javascript.
Without example code it will be difficult to determine what part of it gives you problems.
By looping over the faces (consisting of 3 points if triangles) of the mesh and checking if and where each edge (v1, v2) intersects with the plane, you will get good result, depending on your use case. See here for an implementation of that intersection:
3D Line-Plane Intersection
I can supply specific implementation details if you give a minimal reproducible code example with a mesh and a plane.
Why are some Voronoi regions empty?
I have a point cloud of the surface of a human that I'm trying to find the Voronoi diagram of. So I found scipy.spatial.Voronoi(), including some pretty good documentation. But sometimes vor.regions includes empty regions, and the documentation doesn't quite explain why they're there. At best it explains the relation to its Delaunay calculation "Note here that due to similar numerical precision issues as in Delaunay triangulation above, there may be fewer Voronoi regions than input points." But if so, it's only because qhull calculates Voronoi using a similar (or the exact same) algorithm as it uses for Delaunay Triangulation that this happens. Mathematically, the only reason a Voronoi region should be empty is if its points are duplicated
Specific goals:
I'm looking to replicate the results from this paper that use the Voronoi diagrams to calculate normal vectors at each input point. So I could do a workaround where I use a similar normal to a nearby point's properly calculated normal, or I could ignore any point that gives a zero Voronoi region. But I'd really like to know how to solve these empty regions so I can use as much of the input data as possible.
Background and other research
This answer suggests Voronoi(points, qhull_options='Qbb Qc Qx') and in the docs scipy suggests qhull_options="QJ Pp"
input data: http://columbia.edu/~nxb2101/minimal_stickfig_.npy
Code:
import numpy as np; np.set_err(all='raise')
import scipy.spatial
pt_cloud=np.load('minimal_stickfig_.npy')
vor=scipy.spatial.Voronoi(pt_cloud)
for idx in range(len(vor.regions)):
region=vor.regions[idx]
vertices = vor.vertices[region]
hull=scipy.spatial.ConvexHull(vertices)
volume=hull.volume
triangle_mesh_hull=vertices[hull.simplices] # (n,3,3)
# triang mesh calculation taken from
# https://stackoverflow.com/questions/26434726/return-surface-triangle-of-3d-scipy-spatial-delaunay/26516915
inner_pt = np.mean(vertices[:2],axis=0).reshape((1,3))
CoM=np.zeros((3,))
pif("inner_pt is {0}".format(inner_pt))
for triangle in triangle_mesh_hull:
pif("triangle is: \n{0}".format(triangle))
tetra=np.concatenate((inner_pt,triangle),axis=0)
CoM_tetra=np.mean(tetra,axis=0)
vol_tetra=volume_tetra(tetra)
CoM+=(CoM_tetra*vol_tetra)
CoM /= volume
# do more with CoM, and volume
Any kind of help is appreciated; if you're not sure why qhull does this or how to get around it, please let me know what you did to make a high-quality mesh from a point cloud
I have this object/point cloud,rendered with pyopengl and pygame.
My object is a numpy array of the co-ordinates of the point. I wish to generate a 3d triangular mesh of this object, also it would be nice if you could decrease the number of triangles.
I have tried scipy.spatial.Delaunay and it doesnt generate triangles for 3d objects.
Dual Contouring would probably work well here, it's an algorithm that takes voxelized data and turns it into a mesh. I don't understand it trivially enough to outline it here, but basically you'd take your array of points and place them into a 3D grid array where if that grid cell contains a point it's set to equal 1 (full), and if it doesn't it is set to 0 (empty), you would then run the DC algorithm on this grid and it would output a mesh. The nice thing about this algorithm is it supports internal cavities and concave shapes.
Here's some links I found that may help you if you decide to use DC:
Basic Dual Contouring Theory
http://ngildea.blogspot.com/2014/11/implementing-dual-contouring.html
This is the github repo to the source I used when I implemented this algorithm in Unity3D:
https://github.com/nickgildea/DualContouringSample
I have a function whose range is a non-convex, simply connected region in R3. When I sample the function I know if the resulting point is on the surface of the region or not. I'd like to triangulate those samples subject to the surface constrains, i.e., the resulting tetrahedra should not
"hide" surface points. The hull would not be convex, of course.
I searched around for a library. So far I found Triangle, but it only works in R2. I also found TetGen, which works in R3, but it requires to provide
the surface triangulation (which I don't have). Also, as far as I can see, these C/C++ libraries do not have Python bindings.
Any suggestions? Thanks!
You may take a look at CGAL it has python-bindings.
One side note: If you need the surface triangulation (which seems to be a 2D problem), you may take each face, project it to 2D, triangulate it, and back to your 3D face.
EDIT due to comment: CGAL does "only" 3D triangulation. 3D constrained triangulation requires Steiner points. Since not every input can be triangulated in 3D (Schönhardt polyhedron as the classical counter-example).
Maybe you can take a look at MeshPy it looks like it has what you are looking for: "MeshPy provides Python interfaces to three well-regarded mesh generators, Triangle by J. Shewchuk, TetGen by Hang Si, and gmsh by Christophe Geuzaine and Jean-Francois Remacle."