Convex segmentation in 3D from just points? - algorithm

I have a set of 3D points. The coordinates are all integers with no decimals to worry about.
I have to convert these points to a collection of convex hulls (point collections only - the triangulation code is already done and working).
The goal is to create pseudo-concave meshes from points via convex segmentation. Overlapping meshes as well as incorrect normals are not concerns in this case.
The points have no index nor connectivity structure amongst themselves. Rather, connectivity in my program is assumed by:
-All neighbors are considered. (Like 8-way searching in 2D).
-A neighbor in my program is exactly the same as in image processing - distances greater than 1 unit assume the points are not neighbors.
The question is, does an algorithm exist for this?
Here's an image to help describe the desired effect:
(Note that I don't have the 10 reputation points to post it directly. It's just a link.)
https://i.imgur.com/ii3hU1p.jpg

Related

3D mesh direction detection

I have a 3D mesh consisting of triangle polygons. My mesh can be either oriented left or right:
I'm looking for a method to detect mesh direction: right vs left.
So far I tried to use mesh centroid:
Compare centroid to bounding-box (b-box) center
See if centroid is located left of b-box center
See if centroid is located right of b-box center
But the problem is that the centroid and b-box center don't have a reliable difference in most cases.
I wonder what is a quick algorithm to detect my mesh direction.
Update
An idea proposed by #collapsar is ordering Convex Hull points in clockwise order and investigating the longest edge:
UPDATE
Another approach as suggested by #YvesDaoust is to investigate two specific regions of the mesh:
Count the vertices in two predefined regions of the bounding box. This is a fairly simple O(N) procedure.
Unless your dataset is sorted in some way, you can't be faster than O(N). But if the point density allows it, you can subsample by taking, say, every tenth point while applying the procedure.
You can as well keep your idea of the centroid, but applying it also in a subpart.
The efficiency of an algorithm to solve your problem will depend on the data structures that represent your mesh. You might need to be more specific about them in order to obtain a sufficiently performant procedure.
The algorithms are presented in an informal way. For a more rigorous analysis, math.stackexchange might be a more suitable place to ask (or another contributor is more adept to answer ...).
The algorithms are heuristic by nature. Proposals 1 and 3 will work fine for meshes whose local boundary's curvature is mostly convex locally (skipping a rigorous mathematical definition here). Proposal 2 should be less dependent on the mesh shape (and can be easily tuned to cater for ill-behaved shapes).
Proposal 1 (Convex Hull, 2D)
Let M be the set of mesh points, projected onto a 'suitable' plane as suggested by the graphics you supplied.
Compute the convex hull CH(M) of M.
Order the n points of CH(M) in clockwise order relative to any point inside CH(M) to obtain a point sequence seq(P) = (p_0, ..., p_(n-1)), with p_0 being an arbitrary element of CH(M). Note that this is usually a by-product of the convex hull computation.
Find the longest edge of the convex polygon implied by CH(M).
Specifically, find k, such that the distance d(p_k, p_((k+1) mod n)) is maximal among all d(p_i, p_((i+1) mod n)); 0 <= i < n;
Consider the vector (p_k, p_((k+1) mod n)).
If the y coordinate of its head is greater than that of its tail (ie. its projection onto the line ((0,0), (0,1)) is oriented upwards) then your mesh opens to the left, otherwise to the right.
Step 3 exploits the condition that the mesh boundary be mostly locally convex. Thus the convex hull polygon sides are basically short, with the exception of the side that spans the opening of the mesh.
Proposal 2 (bisector sampling, 2D)
Order the mesh points by their x coordinates int a sequence seq(M).
split seq(M) into 2 halves, let seq_left(M), seq_right(M) denote the partition elements.
Repeat the following steps for both point sets.
3.1. Select randomly 2 points p_0, p_1 from the point set.
3.2. Find the bisector p_01 of the line segment (p_0, p_1).
3.3. Test whether p_01 lies within the mesh.
3.4. Keep a count on failed tests.
Statistically, the mesh point subset that 'contains' the opening will produce more failures for the same given number of tests run on each partition. Alternative test criteria will work as well, eg. recording the average distance d(p_0, p_1) or the average length of (p_0, p_1) portions outside the mesh (both higher on the mesh point subset with the opening). Cut off repetition of step 3 if the difference of test results between both halves is 'sufficiently pronounced'. For ill-behaved shapes, increase the number of repetitions.
Proposal 3 (Convex Hull, 3D)
For the sake of completeness only, as your problem description suggests that the analysis effectively takes place in 2D.
Similar to Proposal 1, the computations can be performed in 3D. The convex hull of the mesh points then implies a convex polyhedron whose faces should be ordered by area. Select the face with the maximum area and compute its outward-pointing normal which indicates the direction of the opening from the perspective of the b-box center.
The computation gets more complicated if there is much variation in the side lengths of minimal bounding box of the mesh points, ie. if there is a plane in which most of the variation of mesh point coordinates occurs. In the graphics you've supplied that would be the plane in which the mesh points are rendered assuming that their coordinates do not vary much along the axis perpendicular to the plane.
The solution is to identify such a plane and project the mesh points onto it, then resort to proposal 1.

Build constrained alpha shape of polygons

I have a quite specific task.
I need to compute alpha shape of a set of points. (You can frolic with already implemented algorith there)
The point is that I have predefined subsets of points (let's call them details) and I do not want their structure to be changed. For example, suppose these polygons to be details:
Then, the following hulls are ok depending on alpha-radius:
And the following is not:
In brief, I want the structure of specified subsets of points to stay unchanged during reducing the radius.
So, how do you think:
May I use any of already implemented algorithm or should I figure out some specific one?
Is there implemented example of Alpha-Shape algorithm with open source code anywhere? (Alpha-Shape, not Concave hull. It must split contour into several parts when reducing the radius)
Well, Finally I solved this using constrained Delaunay triangulation.
The idea (that Yves Daoust shared in comment to the question) was to use not just Delaunay triangulation during building Alpha shape, but constrained Delaunay triangulation.
Algorithm: In brief, I:
Took convex hull of the promoted polygons
Computed its constrained triangulation. (Constraining segments are polygon's edges)
On this step I used Triangle .NET library for C#. I guess, every popular language has alternatives to it.
Built alpha shape: threw away all triangles where any edge is longer than predefined alpha
Results of my struggles:
Alpha = 1000, alpha shape is just a convex hull
Alpha = 400
Alpha = 30. Only very small concavities are smoothened
Feel free to write me for a deeper explanation, if you wish.

Optimizing Geodesic Distances on a Triangular Mesh

I have a convex triangulated mesh. I am able to numerically calculate geodesics between points on the surface; however, I am having trouble tackling the following problem:
Imagine a net being placed over the mesh. The outside boundary of the net coincides with the boundary of the mesh, but the nodes of the net corresponding to the interior of the net are allowed to move freely. I'm interested in finding the configuration that would have the least stress (I know the distances for the at rest state of the net).
Doing this on a smooth surface is simple enough as I could solve for the stresses in terms of the positions of the nodes of the net; however, I don't see a way of calculating the stresses in terms of the position of the net nodes because I don't know that a formula exists for geodesics on a convex triangulated surface.
I'm hoping there is an alternative method to solving this such as a fixed point argument.
Hint:
If I am right, as long as a node remains inside a face, the equations are linear (just as if the node was on a plane). Assuming some node/face correspondence, you can solve for the equilibrium, as if the nodes did belong to the respective planes of support, unconstrained by the face boundaries.
Then for the nodes which are found to lie outside the face, you can project them on the surface and obtain a better face assignment. Hopefully this process might converge to a stable solution.
The picture shows a solution after a first tentative node/face assignment, then a second one after projection/reassignment.
On second thoughts, the problem is even harder as the computation involves geodesic distances between the nodes, which depend on the faces that are traversed. So the domain in which linearity holds when moving a single node is even smaller than a face, it is also limited by "wedges" emanating from the lined nodes and containing no other vertex.
Then you may have to compute the domains where the geodesic distances to a linked neighbor is a linear function of the coordinates and project onto this partition of the surface. Looks like an endeavor.

Algorithm for determining whether a point is inside a 3D mesh

What is a fast algorithm for determining whether or not a point is inside a 3D mesh? For simplicity you can assume the mesh is all triangles and has no holes.
What I know so far is that one popular way of determining whether or not a ray has crossed a mesh is to count the number of ray/triangle intersections. It has to be fast because I am using it for a haptic medical simulation. So I cannot test all of the triangles for ray intersection. I need some kind of hashing or tree data structure to store the triangles in to help determine which triangle are relevant.
Also, I know that if I have any arbitrary 2D projection of the vertices, a simple point/triangle intersection test is all necessary. However, I'd still need to know which triangles are relevant and, in addition, which triangles lie in front of a the point and only test those triangles.
I solved my own problem. Basically, I take an arbitrary 2D projection (throw out one of the coordinates), and hash the AABBs (Axis Aligned Bounding Boxes) of the triangles to a 2D array. (A set of 3D cubes as mentioned by titus is overkill, as it only gives you a constant factor speedup.) Use the 2D array and the 2D projection of the point you are testing to get a small set of triangles, which you do a 3D ray/triangle intersection test on (see Intersections of Rays, Segments, Planes and Triangles in 3D) and count the number of triangles the ray intersection where the z-coordinate (the coordinate thrown out) is greater than the z-coordinate of the point. An even number of intersections means it is outside the mesh. An odd number of intersections means it is inside the mesh. This method is not only fast, but very easy to implement (which is exactly what I was looking for).
This is algorithm is efficient only if you have many queries to justify the time for constructing the data structure.
Divide the space into cubes of equal size (we'll figure out the size later). For each cube know which triangles has at least a point in it. Discard the cubes that don't contain anything. Do a ray casting algorithm as presented on wikipedia, but instead o testing if the line intersects each triangle, get all the cubes that intersect with the line, and then do ray casting only with the triangles in these cubes. Watch out not to test the same triangle more than one time because it is present in two cubes.
Finding the proper cube size is tricky, it shouldn't be neither to big or too small. It can only be found by trial and error.
Let's say number of cubes is c and number of triangles is t.
The mean number of triangles in a cube is t/c
k is mean number of cubes that intersect the ray
line-cube intersections + line-triangle intersection in those cubes has to be minimal
c+k*t/c=minimal => c=sqrt(t*k)
You'll have to test out values for the size of the cubes until c=sqrt(t*k) is true
A good starting guess for the size of the cube would be sqrt(mesh width)
To have some perspective, for 1M triangles you'll test on the order of 1k intersections
Ray Triangle Intersection appears to be a good algorithm when it comes to accuracy. The Wiki has some more algorithms. I am linking it here, but you might have seen this already.
Can you, perhaps improvise by, maintaining a matrix of relationship between the points and the plane to which they make the vertices? This subject appears to be a topic of investigation in the academia. Not sure how to access more discussions related to this.

area of intersection of two triangles, or a set of halfplanes, or area of a convex point set

I need to compute the area of the region of overlap between two triangles in the 2D plane. Oddly, I have written up code for the triangle-circle problem, and that works quite well and robustly, but I have trouble with the triangle-triangle problem.
I already first check to see if one entirely contains the other, or if the other contains the first, as well as obtain all the edge-wise intersection points. These intersection points (up to 6, as in the star of David), combined with the triangle vertices that are contained within the other triangle, are the vertices of the intersection region. These points must form a convex polygon.
The solution I seek is the answer to either of these questions:
Given a set of points known to all lie on the convex hull of the point set, compute the area of the convex hull. Note that they are in random order.
Given a set of half-planes, determine the intersecting area. This is equivalent to describing both triangles as the intersection of three half-planes, and computing the solution as the direct intersection of this description.
I have considered for question 1 simply adding up all areas of all possible triangles, and then dividing by the multiplicity in counting, but that seems dumb, and I'm not sure if it is correct. I feel like there is some kind of sweep-line algorithm that would do the trick. However, the solution must also be relatively numerically robust.
I simply have no idea how to solve question 2, but a general answer would be very useful, and providing code would make my day. This would allow for direct computation of intersection areas of convex polygons instead of having to perform a triangle decomposition on them.
Edit: I am aware of this article which describes the general case for finding the intersection polygon of two convex polygons. It seems rather involved for just triangles, and furthermore, I don't really need the resulting polygon itself. So maybe this question is just asked in laziness at this point.
Question 1: why are the points in a random order? If they are, you have to order them so that connecting consecutive points with straight lines yields a convex polygon. How to order them -- for example, by running a convex hull algorithm (though there are probably also simpler methods). Once you have ordered them, compute the area as described here.
--
Question 2 is simpler. Half-plane is defined by a single line having an implicit equation a*x+b*y+c=0 ; all points (x, y) for which a*x+b*y+c <= 0 (note the inequality) are "behind" the half-plane. Now, you need at least three planes so that the intersection of their negative half-spaces is closed (this is necessary, but not sufficient condition). If the intersection is closed, it will be a convex polygon.
I suggest that you maintain a linked list of vertices. The algorithm is initialized with THREE lines. Compute the three points (in general case) where the lines intersect; these are the starting vertices of your region (triangle). You must also check that each vertex is "behind" the half-plane defined by the line going through the other two vertices; this guarantees that the intersection actually IS a closed region.
These three vertices define also the the three edges of a triangle. When you intersect by a new half-plane, simply check for the intersection between the line defining the half-plane and each of the edges of the current region; in general you will get two intersection points, but you must watch out for degenerate cases where the line goes through a vertex of the region. (You can also end up with an empty set!)
The new intersection vertices define a line that splits the current region in TWO regions. Again, use orientation of the new half-plane to decide which of the two new regions to assign to the new "current region", and which one to discard.
The points in the list defining the edges of the current region will be correctly ordered so you can apply the formula in the above link to compute its area.
If this description is not detailed/understandable, the next-best advice I can give you is that you invest in a book on computational geometry and linear algebra.

Resources