Building a graph from a point cloud - point-cloud-library

I have a PCL Point Cloud. Basically, I need to write some code that does the following:
Example
Basically, I need to build a graph/edge map of the point cloud. Where each node represents a point, and those points have pointers/edges to neighbouring points. And preferably, it cannot form a corner edge as seen in the picture. (This could be enforced by saying a point cannot have a large change in l1 norm too (taxicab distance. add all axis), not just l2 norm).
I need to do this because, it's useful for all my other algorithms. Normal computation etc.
I'm currently at a loss of how to implement this. My point cloud is unorganized. I could sort it into a KD Tree but I'm not sure if that is related to this or how I might use this.

The graph/edge map is the same as a triangulation between the vertices.
In your case, as you only want to connect vertices which are close together, Delaunay Triangulation will work.
The edges are the connections between vertices in your graph.
PCL has ConcaveHull, which will triangulate the surface of your vertices, given an alpha value. This alpha value is the maximum radius for each triangle, in your case, half the known distance between diagonal vertices.

Related

How to use delaunay trianglation in 3d points?

I understand how to use delaunay triangulation in 2d points?
But how to use delaunay triangulation in 3d points?
I mean I want to generate surface triangle mesh not tetrahedron mesh, so how can I use delaunay triangulation to generate 3d surface mesh?
Please give me some hint.
To triangulate a 3D point cloud you need the BallPivoting algorithm: https://vgc.poly.edu/~csilva/papers/tvcg99.pdf
There are two meanings of a 3D triangulation. One is when the whole space is filled, likely with tetrahedra (hexahedra and others may be also used). The other is called 2.5D, typically for terrains where the z is a property as the color or whatever, which doesn't influence the resulting triangulation.
If you use Shewchuk's triangle you can get the result.
If you are curious enough, you'll be able to select those tetrahedra that have one face not shared with other tetrahedra. These are the same tetrahedra "joined" with infinite/enclosing points. Extract those faces and you have your 3D surface triangulation.
If you want "direct" surface reconstruction then you undoubtly need to know in advance which vertices among the total given are in the surface. If you don't know them, perhaps the "maxima method" allows to find them out.
One your points cloud consists only of surface vertices, the triangulation method can be any one you like, from (adapted) incremental Chew's, Ruppert, etc to "ball-pivoting" method and "marching cubes" method.
The Delaunay tetrahedrization doesn't fit for two reasons
it fills a volume with tetrahedra, instead of defining a surface,
it fills the convex hull of the points, which is probably not what you expect.
To address the second problem, you need to accept concavities, and this implies that you need to specify a reference scale that tells what level of detail you want. This leads to the concept of Alpha Shapes, which are obtained as a subset of the faces.
Lookup "Alpha Shape" in an image search engine.

How best to triangulate a 5-point star polygon?

I've implemented the "ear-splitting" triangulation method for simple polygons. In testing it out, I see it crashes on the test case of a symmetrical 5-point star.
I think I understand why this polygon is "tricky" -- because it contains edges that are collinear....an ear-shaving diagonal which the algorithm chooses based on starting with a convex vertex (one of the 5 points), then inspecting the diagonal for no "X" edge intersections, and for no vertices intruding into the ear triangle) will blindly assign a diagonal which is collinear with 2 existing edges. After removing the ear's external vertex, the remaining polygon will no longer be "simple" -- it will have vertices having a straight angle (180 deg.), a violation of the simple polygon contract.
I'm chagrined that I've proven that ear-splitting faces this failure case. I thought from the literature that it was a general-purpose method (applicable to all simple polygons). Are those "inductive proofs" you find repeated everywhere overstated?
Has anyone successfully modified an ear-splitting triangulation method to handle the 5-point star?
Random Perturbation of Collinear Edge Endpoints
The "ear-splitting" triangulation algo suffers from a breakdown in the case of polygons which have edges that are collinear. As you can see in the 5-point star, all the edges have this problem.
A simple "patch" can rescue the "ear-splitting" triangulation algo:
1) Before beginning the triangulation, inspect the polygon's edge list (as LineSegs) for any pair of edges that share the same 2D extended line. Apply a tiny random perturbation to both endpoints of any such edge, (e.g., in the range -0.001..+0.001.) Save the original locations of these vertices, so they can be restored after the triangulation.
2) Now you can run ear-split triangulation, having removed the ill-conditioned situation of collinear edges.
3) Undo the perturbations you applied to the vertices.
I've tested this approach, and it works fine. It might seem a bit of a hack, but it's by far the easiest way to rescue the ear-split triangulation from its most noticeable flaw. The random perturbations want to be tiny compared to location coordinates in your app, but huge compared to the finite math EPSILON you're using to compare real-numbers for equal.

Find the distance between two points on any 3d surface

I am making a game in Unity3d and I need a pathfinding algorithm that can guide enemy's towards the player on a 3d surface. The problem is that the 3d surface can take any shape, so it can be a 3d sphere, cube, torus and many more shapes.
I tried using A* but for that formula I need the distance between the two points, and since the object is curved I cannot get that so easily. I found that you can use the Haversine formula if its a sphere, but that won't work on a torus or a random 3d shape.
I want this kind of result except with every kind of object:
https://www.youtube.com/watch?v=hvunNq7yVcU
Is there a way/algorithm that I can use to get that result. I know there is something called nav mesh but I need to program it myself. Also I cannot find how nav mesh approaches this dilema. I am going to use the triangles of my object as nodes.
So my question boils down to:
Does anyone know a algorithm for pathfinding that works on any 3d surface?
Thanks in advance.
I think your problem is that you are not using a graph, I would suggest that you look into a tutorial on how to create a graph, for the language you are using if you can, (this may also help here they are using edges to connect their node which is needed if you have more then one weight). If you do make a graph you will need a node class. Each node must contain pointers to any nodes that it is connected to and an ID of some kind. In your case that is probably all you need but it is also possible to assign a weight to each move if you also have an edge class (connectors between nodes) which would be used to connect the nodes. If you do have an edge class your nodes will have pointers to edges instead of other nodes and each edge will have a weight and a pointer to 1 or 2 nodes (depending on if it is a directed path or not). You can also make a graph class to contain all of your nodes and edges.
Summary:
make a node class and determine if you need the edge class (if everything has a weight of 1 you can get away with out it). Use the node class to create a graph to represent your map with each tile being a node with pointers to connected tiles. Use A* or dijkstra's algorithm to search your graph to find the shortest path.
note: most examples you will find will be for 2d graphs, yours is no different except that there are no bounds on yours, you just need to connect the nodes to their adjacent tiles.

2d integration over non-uniform grid

I'm writing a data analysis program and part of it requires finding the volume of a shape. The shape information comes in the form of a lost of points, giving the radius and the angular coordinates of the point.
If the data points were uniformly distributed in coordinate space I would be able to perform the integral, but unfortunately the data points are basically randomly distributed.
My inefficient approach would be to find the nearest neighbours to each point and stitch the shape together like that, finding the volume of the stitched together parts.
Does anyone have a better approach to take?
Thanks.
IF those are surface points, one good way to do it would be to discretize the surface as triangles and convert the volume integral to a surface integral using Green's Theorem. Then you can use simple Gauss quadrature over the triangles.
Ok, here it is, along duffymo's lines I think.
First, triangulate the surface, and make sure you have consistent orientation of the triangles. Meaning that orientation of neighbouring triangle is such that the common edge is traversed in opposite directions.
Second, for each triangle ABC compute this expression: H*cross2D(B-A,C-A), where cross2D computes cross product using coordinates X and Y only, ignoring the Z coordinates, and H is the Z-coordinate of any convenient point in the triangle (although the barycentre would improve precision).
Third, sum up all the above expressions. The result would be the signed volume inside the surface (plus or minus depending on the choice of orientation).
Sounds like you want the convex hull of a point cloud. Fortunately, there are efficient ways of getting you there. Check out scipy.spatial.ConvexHull.

Point cloud:project city square to ground plane

I have a city square with people, cars, trees and buildings in pcl format. I need to automatically determine the ground plane and project this objects on that ground plane to get a 2D map with occupied places.
Any idea?
I think the best thing to do here would be to familiarise yourself with the following two PCL tutorials:
http://pointclouds.org/documentation/tutorials/planar_segmentation.php
http://pointclouds.org/documentation/tutorials/project_inliers.php
The first tutorial makes use of the RANSAC algorithm to find a dominant plane in a scene. I use it to find tables and floors in robotics scenarios. You would use it to find your dominant ground plane.
The second tutorial shows how to project points directly onto a plane. This is what you would use to make your 3D point cloud into a 2D one. Note that, despite the "inlier" keyword, you can pass your whole point cloud to be projected onto the plane.
Actually, if you are after "occupied" places, you might want to project all of the points that aren't in the ground plane (i.e. the outliers), and that are above it (you can use a PCL filter, such as PlaneClipper3D, for example, or just the complement of the outliers from the plane-segmentation operation.
If the plane that you end up with (containing all your projected points) is not in the coordinate frame you want, you may wish to rotate the whole lot, for example, to align with the coordinate axes so that all z-coordinates are zero. See pcl::transformPointCloud for this (the transform will be obtainable from the plane coefficients returned from the plane segmentation).
I hope this is helpful and not at too basic a level, though the question was rather general so I suppose it should be okay.

Resources