Computing distance from a point to a triangulation in 3D with Matlab - matlab

I have a 3D point cloud that I've transformed into a Delaunay triangulation using Matlab's function DelaunayTri. Now I have a test point in 3D and want to compute, in Matlab, the smallest distance between this point and the triangulation.
So far, I've thought of using the nearestNeighbor(...) member function of the DelaunayTri class in Matlab to find the point in the triangulation closest to my test point and then computing the distance between them. That is something but it is not what I really want.
The closest point on the triangulation to my test point is, in general, not a vertex of the triangulation but somewhere on the face of a triangle. How can I find this point?
Thank you!!!

I've written codes for these things, but they are not on the File Exchange. I can be convinced to give them out by direct mail though.
It is relatively easy to find the distance to a convex hull, but not trivial. A delaunay tessellation is bounded by the convex hull anyway. So you can convert that tessellation into the convex hull easily enough, or just use the convex hull. Note that a convex hull is often a terribly poor approximation for many purposes, especially if you are using this for color mapping, which is perhaps the most common thing I see this used for. In that case, an alpha shape is a far better choice. Alpha shapes also will have a triangulated boundary surface, though in general it will not be convex.
So, to find the nearest point on a convex triangulation:
Convert to the convex boundary surface, i.e., the convex hull. This reduces to finding those triangles which are not shared between pairs of tetrahedra. Internal facets will always appear exactly twice in the list of all facets. This trick also works for non-convex tessellations of course, so for alpha shapes.
Compute a bounding circumcircle for each triangular surface facet. This allows you to know when to stop checking facets.
Get the distances to each point on the surface. Sort each facet by the distance to the nearest point in that facet. Start by looking at the nearest facet in that list.
Compute the distance to the apparently nearest facet found in step 3. A simple solution is found by least distance programming (LDP), which can be converted to a constrained linear least squares. Lawson & Hanson have an algorithm for this.
Repeat step 4 until the current best distance found is less than the distance, comparing it to any of the circumcircles from step 2. This loop will be quite short really, at least for a convex hull. For a more general non-convex hull from an alpha shape, it may take more time.
You can also reduce the search space a bit by excluding the facets from your search that point AWAY from the point in question. Use those facet normals for this test.

I wrote the tool point2trimesh for this problem. It's kind of a "brute force" solution which works also for non-convex surfaces.

Related

Why do we need to triangulate a convex polygon in order to sample uniformly from it?

Suppose I want to uniformly sample points inside a convex polygon.
One of the most common approaches described here and on the internet in general consists in triangulation of the polygon and generate uniformly random points inside each triangles using different schemes.
The one I find most practical is to generate exponential distributions from uniform ones taking -log(U) for instance and normalizing the sum to one.
Within Matlab, we would have this code to sample uniformly inside a triangle:
vertex=[0 0;1 0;0.5 0.5]; %vertex coordinates in the 2D plane
mix_coeff=rand(10000,size(vertex,1)); %uniform generation of random coefficients
x=-log(x); %make the uniform distribution exponential
x=bsxfun(#rdivide,x,sum(x,2)); %normalize such that sum is equal to one
unif_samples=x*vertex; %calculate the 2D coordinates of each sample inside the triangle
And this works just fine:
However, using the exact same scheme for anything other than a triangle just fails. For instance for a quadrilateral, we get the following result:
Clearly, sampling is not uniform anymore and the more vertices you add, the more difficult it is to "reach" the corners.
If I triangulate the polygon first then uniform sampling in each triangle is easy and obviously gets the job done.
But why? Why is it necessary to triangulate first?
Which specific property have triangle (and simplexes in general since this behaviour seems to extend to n-dimensional constructions) that makes it work for them and not for the other polygons?
I would be grateful if someone could give me an intuitive explanation of the phenomena or just point to some reference that could help me understand what is going on.
I should point out that it's not strictly necessary to triangulate a polygon in order to sample uniformly from it. Another way to sample a shape is rejection sampling and proceeds as follows.
Determine a bounding box that covers the entire shape. For a polygon, this is as simple as finding the highest and lowest x and y coordinates of the polygon.
Choose a point uniformly at random in the bounding box.
If the point lies inside the shape, return that point. (For a polygon, algorithms that determine this are collectively called point-in-polygon predicates.) Otherwise, go to step 2.
However, there are two things that affect the running time of this algorithm:
The time complexity depends greatly on the shape in question. In general, the acceptance rate of this algorithm is the volume of the shape divided by the volume of the bounding box. (In particular, the acceptance rate is typically very low for high-dimensional shapes, in part because of the curse of dimensionality: typical shapes cover a much smaller volume than their bounding boxes.)
Also, the algorithm's efficiency depends on how fast it is to determine whether a point lies in the shape in question. Because of this, it's often the case that complex shapes are made up of simpler shapes, such as triangles, circles, and rectangles, for which it's easy to determine whether a point lies in the complex shape or to determine that shape's bounding box.
Note that rejection sampling can be applied, in principle, to sample any shape of any dimension, not just convex 2-dimensional polygons. It thus works for circles, ellipses, and curved shapes, among others.
And indeed, a polygon could, in principle, be decomposed into a myriad of shapes other than triangles, one of those shapes sampled in proportion to its area, and a point in that shape sampled at random via rejection sampling.
Now, to explain a little about the phenomenon you give in your second image:
What you have there is not a 4-sided (2-dimensional) polygon, but rather a 3-dimensional simplex (namely a tetrahedron) that was projected to 2-dimensional space. (See also the previous answer.) This projection explains why points inside the "polygon" appear denser in the interior than in the corners. You can see why if you picture the "polygon" as a tetrahedron with its four corners at different depths. With higher dimensions of simplex, this phenomenon becomes more and more acute, again due partly to the curse of dimensionality.
Well, there are less expensive methods to sample uniform in the triangle. You're sampling Dirichlet distribution in the simplex d+1 and taking projection, computing exponents and such. I would refer you to the code sample and paper reference here, only square roots, a lot simpler algorithm.
Concerning uniform sampling in complex areas (quadrilateral in your case) general approach is quite simple:
Triangulate. You'll get two triangles with vertices (a,b,c)0 and (a,b,c)1
Compute triangle areas A0 and A1 using, f.e. Heron's formula
First step, randomly select one of the triangles based on area.
if (random() < A0/(A0+A1)) select triangle 0 else select triangle 1. random() shall return float in the range [0...1]
Sample point in selected triangle using method mentioned above.
This approach could be easily extended to sample for any complex area with uniform density: N triangles, Categorical distribution sampling with probabilities proportional to areas will get you selected triangle, then sample point in the triangle.
UPDATE
We have to triangulate because we know good (fast, reliable, only 2 RNG calls, ...) algorithm to sample with uniform density in triangle. Then we could build on it, good software is all about reusability, and pick one triangle (at the cost of another rng call) and then back to sample from it, total three RNG calls to get uniform density sampling from ANY area, convex and concave alike. Pretty universal method, I would say. And triangulation is a solved problem, and
basically you do it once (triangulate and build weights array Ai/Atotal) and sample till infinity.
Another part of the answer is that we (me, to be precise, but I've worked with random sampling ~20years) don't know good algorithm to sample precisely with uniform density from arbitrary convex more-than-three-vertices closed polygon. You proposed some algorithm based on hunch and it didn't work out. And it shouldn't work, because what you use is Dirichlet distribution in d+1 simplex and project it back to d hyperplane. It is not extendable even to quadrilateral, not talking to some arbitrary convex polygon. And I would state conjecture, that even such algorithm exist, n-vertices polygon would require n-1 calls to RNG, which means there is no triangulation setup, but each call to get a point would be rather expensive.
Few words on complexity of the sampling. Assuming you did triangulation, then with 3 calls to RNG you'll get one point sampled uniformly inside your polygon.
But complexity of sampling wrt number of triangles N would be O(log(N)) at best. YOu basically would do binary search over partial sums of Ai/Atotal.
You could do a bit better, there is O(1) (constant time) sampling using Alias sampling of the triangle. The cost would be a bit more setup time, but it could be fused with triangulation. Also, it would require one more RNG calls. So for four RNG calls you would have constant point sampling time independent of complexity of your polygon, works for any shape

How to check if given 3d point is outside convex hull

I'm working on a science project. I have a list of xyz-coordinates of voronoi diagram vertices, and a list of points that create my protein's convex-hull (from triangulation). Now some of the vertices lie quite far from the hull and I'd like to filter them out. How can I do it in c++ ? For now it doesn't have to be super optimised, I'm only focused on removing those points.
visualization
I was also thinking to check if a line from voronoi vertex(red crosses) to center of protein(pink sphere) is intersecting with hull face at any point, but I'm not sure how to achive that.
I've read that you can check if a point is inside a polygon by counting the times an infinite line from the point is crossing the hull, but that was for two dimensions. Can similar approach be implemented to suit my needs ?
https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/
Let's start with the two-dimensional case. You can find the solution to that on CS.SX:
Determine whether a point lies in a convex hull of points in O(logn)
The idea is that each two consecutive points on the convex hull define a triangular slice of the plane (to some internal point of the hull); you can find the slice in which your point is located, and check whether it's closer to the internal point than the line segment bounding the slide.
For the three-dimensional case, I'm guessing you should be able to do something similar, but the search for the 3 points forming the relevant triangle might be a little tricky. In particular, it would also depend on how the convex hull is represented - as in the 2-d case the convex hull is just a sequence of consecutive points on a cycle.
I know this doesn't quite solve your problem but it's the best I've got given what you've written...

Convex Hull with a predefined number of vertices

I am working on image segmentation and I thought the convex hull can provide me with a simple solution to my problem. Currently I have polygons with for sides (see image below). Due to image processing issues, the shape does not have clean straight sides and hence when I use the standard convex hull (in Matlab) I may get more than the four main corners to define it.
My goal is to force the convex hull algorithm to find the best 4 vertices that will enclose my polygons (i.e. 4 best enclosing vertices per polygon). Is this possible? An example code will be appreciated.
Thanks
The problem of the minimum area bounding polygon is briefly mentioned in "Geometric applications of a matrix-searching algorithm" (see Applications section). It is not simple and is probably not the way for you.
For an easier (but approximate) answer to your question, you can consider the four cardinal directions and find the farthest points in these, which define a quadrilateral. (Also consider the four intermediate directions, which are more appropriate for an axis-aligned rectangle.)
If you insist having an enclosing quadrilateral, you can translate the four edges to the farthest points in the respective perpendicular directions, and find the pairwise intersections.
If you insist having a rectangle, compute the convex hull and find the minimum area or minimum perimeter bounding rectangle by the Rotating Calipers method. https://geidav.wordpress.com/tag/rotating-calipers/

How to move a triangulation in matlab

I have made a 3D delaunay triangulation in matlab with some defined points. Considering it a consistent triangulation (I mean with fixed edges and angles) I want to move this triangulatoin in the space and then compute the location of one point by giving other points' location.
I have searched a lot on the net but I couldn't find a proper solution for this problem. Actually there isn't any similar example.

I have a point set in image,how to find the External irregular shape circling all the points by Matlab

I got a point set after executing SIFT algorithm.Now I want to find the external irregular shape of those points.Is there anyone knowing the relevant functions in Matlab? Notice that I don't want the convex hall.Thank you!
If you want convex hull, (unclear based on your comment... you can edit questions btw), look up convhull.
If you don't want convex hull, a Delaunay triangulation will probably get you started since the result captures both the convex hull of the points, but also the internal structure such that you may be able to remove some edges from the outside of the returned triangulation.