Vertices with normals to simple mesh with faces - python

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

Related

Python algorithm to project 3D point to triangle mesh along normal

Intro
Say I have a 3D point, a normal and a triangle mesh of a tetraeder:
pt = np.array([0,0,0.5])
normal = np.array([1,1,0])
vertices_tetr = np.array([0,0,0],[0,1,1],[1,0,1],[1,1,0])
faces_tetr = np.array([0,1,2],[0,2,3],[0,1,3],[1,2,3])
Link to .ply file of tetraeder can be found here.
Question
What would be a good method to project the 3D point to the mesh along the given normal?
Additional info
Efficiency is appreciated if the solution is not too complicated. If there's a good library for this then that's also an option.
Extra clarification: I am not looking for the closest point of the mesh, but really the projection of the 3D point on one of the faces of the mesh along the given normal.Thus as shown in the picture below with p, the original point, n the normal and p', the projected point.

How to generate equidistributed points (evenly distributed) on the surface of a sphere, specifying the distance between neighbouring points

In a nutshell:
I need an algorithm that can generate points on the surface of a sphere, and the euclidean distance between each point and its neighbors must be the same.
Here is a quick explanation about what I mean about that:
If the sphere was represented as a "geodesic polyhedron" ("geodesic sphere"), each side of all the triangles would have the same length. Note that it doesn't have to be a Geodesic grid or a geodesic polyhedron, it could be something else. I'm open to all suggestions.
The difficulty is that we must be able to specify the distance between the neighbouring points.
If it was a graph I would say that the edges should be the same length, and that the distance between the adjacent nodes / vertices should the same.
What I'm looking for:
an existing libray / function or algorithm that already solves this problem (but I doubt that it would be the case because I did a lot of research)
an implementation
Constraints of the algorithm:
Output:
an array of 3D (x,y,z) coordinates.
Input parameters:
3D (x,y,z) coordinates of the sphere center
radius of the sphere
distance between neighbouring points (adjacent nodes)
What I've done:
I did a lot of research about the subject
I've read a lot of papers an articles
I implemented some algorithms I found
I found a lot of good papers and resources about related problems, but nothing for this specific case. So after days of research, I ask people that have specialised knowledge of this area some help.
The closest solution I've found is the Deserno algorithm (see link below), but the problem is that its input parameters are the radius and a number of points to generate (we can't sepcify the coordinates of the sphere center an the distance between neighbouring points).
If it helps, here are some related questions and useful resources:
Evenly distributing n points on a sphere
Plotting points on the surface of a sphere in Python's matplotlib
https://en.wikipedia.org/wiki/Geodesic_grid
https://en.wikipedia.org/wiki/Geodesic_polyhedron
https://en.wikipedia.org/wiki/Spherical_polyhedron
Deserno algorithm: https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf
Some representations to give an idea:
Evenly distributed points:
Geodesic grid / geodesic polyhedron:
Geodesic polyhedron zoom:
Here, each point is at 10 centimeters of distance from its neighbors.

Is there a simple way to calculate the contour of a non simple self-intersecting curve?

I am looking for a way to triangulate and fill the interior of the contour of a non simple (possibly self intersecting) polygon. I found some very good algorithms online to triangulate simple curves or find the convex hull of a set of points, but my need is to find the contour of a list of points that I cannot rely on it being a Jordan curve (without punching holes for every self intersection like, say, mapbox/earcut, does)
I tried a python port of mapbox's earcut (https://github.com/joshuaskelly/earcut-python) which is great but punches holes for self intersections
I couldn't try scipy.spacial since it does not support non simple curves at all.
I'm performing my research in Python and plan to port it to JavaScript eventually but for now I am language agnostic and any algorithm would do.
import earcut
from shapely.ops import cascaded_union
from shapely.geometry import Polygon
points = [[(0,0), (100,0), (100,50), (200,100), (0,100), (20,20), (80,20), (80,80), (20,80)],[]]
data = earcut.flatten(points)
flattrangles = earcut.earcut(data['vertices'])
alltriangles = [[points[0][j] for j in tr] for tr in triangles.T.tolist()]
cascaded_union([Polygon(tr) for tr in alltriangles])
Expected one large polygon with no holes
Got a polygon with two triangular holes where the self intersections are

Plotting a 3d triangular mesh from 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

Generating a Voronoi Diagram around 2D Polygons

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.

Categories

Resources