Getting 3D Voronoi Cells from Qhull output - computational-geometry

My goal is to get the individual 3D Voronoi cells (both vertices and edges) from the output of Qhull's qvoronoi subroutine. However, I'm having trouble understanding the voronoi ridges (output 'Fv'). A sample line from the output is:
7 0 1 1 0 4 5 3
The first number is the number of vertices in the line, the next two are the indices of the vertices separated by the ridge, and the rest of the numbers are the vertex indices on the ridge. I naively tried connecting adjacent vertices (i.e. 4->5, 5->3, 3->1, etc.), and it seemed to work, though I wasn't sure if that was correct. How do the points connect to each other?
Additionally, from the qvoronoi output (option 'FN'), I can get the vertices of each region, but there is no information about the connectivity between the vertices. I am wondering where this information is. Is it in the ridges output, or in a different qvoronoi output option?

The indices of the ridge do not seem to be in cyclic order. So, reconstructing back the polygon face might not be possible.
An alternate is to pass the output of gvoronoi of each cell to qconvex to construct the convex hull. This does not scale well, but might be okay if you have few cells you want to visualize or analyse.
For example, to get Voronoi cell of input site 5 of 30 input sites:
$ rbox 30 D3 | qvoronoi QV5 p | qconvex G

Try convex hull
Because Voronoi guarantees only convex polyhedra, there's a hacky way of finding this by finding a convex hull (in my case, scipy.spatial.ConvexHull()). The minimal convex hull surrounding your Voronoi region will be equivalent to what you want, and scipy.spatial even gives you further stuff for free
hull=scipy.spatial.ConvexHull(vertices)
volume=hull.volume
triangle_mesh_hull=vertices[hull.simplices] # shape is (n,3,3)
credit for the very short, elegant lines above goes to Jaime. If you want to do something to each triangular section of the mesh after this, you can access it like:
for triangle in triangle_mesh_hull:
do_stuff_to(triangle)
...
...
...
do_more_stuff_with(triangle)
...
...
...

Related

Detect hole in geometry

I am working with a serialization pipeline. I am taking a model and exporting it. I do not wish to export any model with a hole in a face. How would I detect a hole and report a error?
I have access to all vertexes, edges, faces etc.
Here is a picture of what I mean.
As you can see there is a hole in the face. I am fairly new to geometry so please try to explain in layman terms.
If a 3D object is "simple", meaning that it doesn't have holes, it satisfies Euler's Formula for Polyhedra, V - E + F = 2 where V is the number of vertices in the figure, E is the number of edges, and F is the number of faces. If you can easily obtain those three numbers, you can calculate the formula V - E + F. If the result is not 2, the object has a hole (or some other pathology like a pinch). In fact, you can tell how many holes the object has by V - E + F: if the number is 0, it has one hole; if the number is -2, it has two holes; etc.
Calculating V, E, and F can be a little tricky because vertices are generally shared by two or more edges, and edges are generally shared by two faces. You don't want to overcount; if three edges meet in a single vertex, you only want to count the vertex once, not three times.
Not only that, but it's easy to make a mistake counting when the shapes have holes (which is exactly the case you're interested in). The easiest way to avoid making a mistake is to break the figure up into convex parts with e.g., triangulation.
The formula doesn't tell you which face has the hole, but if you know that the figure has a hole you can apply Euler's formula to each face individually, again with triangulation. In that case, faces without holes will have V - E + F = 1 where V,E,F are now restricted to the face in question. (the discrepancy with the previous formula is resolved if you count the region outside the face as another (infinite) face). Faces with holes will have V - E + F < 1.
For example, a triangle on the plane has V=3, E=3, and F=1 (the "face" of the triangle represented by its interior) giving V-E+F=1. On the other hand, a triangle with a similarly shaped triangular hole inside, in which corresponding vertices of inner and outer triangles are connected, will have V=6, E=9, and F=3 for V-E+F=0. I have broken the figure into three convex quadrilaterals in this case.
Most books on computer graphics have a discussion of this topic.
If I understand correctly, you want to detect polygons with holes. Now how polygons with holes are represented can vary with each software (some store separate internal contour lists). However, a common representation in 3D packages (including formats like OBJ) use a flat face vertices representation which tends to look like this:
... where 2,6 and 1,7 would be the same vertex index stored twice in the same polygon (the numbers in the picture indicate face point indices). Note that this edge from 1,7 to 2,6 could be hidden in some software, but it's there even if it's not visible if the software stores polygon vertices in a flat list of indices/pointers.
So a quick way to tell if a polygon has a hole with such representations given only face data (ex: from an OBJ file) is to see if it has duplicate entries for the vertex indices. If the same vertex index is repeated more than one time in a polygon, then it has a hole.
Now there is a case where you can find duplicated vertices for an empty inner contour, like so:
... where 2,4 are welded (same vertex). If you want to distinguish these cases, you can detect them when the edge connecting exterior contour to interior contour only has one vertex duplicated instead of two. In that case, the interior contour is empty and this polygon is just a funky one (perhaps created through a CSG/plane slicing operation).
If you want a really robust solution, it's worth writing a routine that "unflattens" these flat contour lists into multiple interior/exterior groups by splitting the list apart where the duplicate edges connecting one contour to another are found. If the interior groups have fewer than 3 vertices, then they're probably just funky polygons without a visually noticeable hole. If they have 3 or more, then they meet the criteria required to show a hole which you can see visually. In cases where the interior contours don't form a full-fledged hole, you can just toss the interior contour and keep the exterior contour (in which case it's like just keeping the 3-point triangle exterior in the above pic while tossing out those redundant vertices, kind of cleaning up the geometry in the process and giving you the triangle formed from {1, 2/4, 5}).
A simple solution you can apply if you don't mind exporting unwelded geometry as long as it isn't funky (no holes or interior contours) is to simply clone (make unique) vertices that are duplicates in a polygon, basically unwelding it, like so:
That's a little easier than a full-blown tessellation kind of solution, and it still ends up giving you polygons without any holes or separate interiors. I visually moved 2 and 4 apart for the sake of demonstration to emphasize that they're now separate vertices, but you don't have to do that (they can be coincident).
This kind of unwelding technique is also useful if you have a tessellator that doesn't support holes. You can apply this technique to unweld the polygon, tessellate it, then weld/merge back coincident vertices to give you the final result.

Cut the Cake, or polygon decomposition

I'm facing the following problem: I'm given a set of coordinates on an integer grid that define the vertices of a polygon. The polygon is guaranteed to be convex. It's proven that such a polygon can always be cut into 4 equal area parts by 2 orthogonal lines. Let's call the point of these lines' intersection P.
Given that set, I should calculate the coordinates of P within the polygon and the angle the lines need to be turned on so that the lines cut the polygon into 4 equal parts.
I realise that, put generally, the cake cutting problem has no "good" solution. But this particular case of it should.
I've searched for an algorithm to solve that problem, but found nothing useful.
Where should I look?
My approach would be to calculate the coordinates of the centre of the polygon (that can be done more or less easily), place Pthere and then "wiggle" the lines until the areas of the parts match. But that sounds too inelegant.
UPD: that's the problem I'm dealing with. Perhaps this question should be suspended until I come up with actual code questions.
Here is a partial sketch of the solution:
Choose an arbitrary direction and find the line parallel to that direction that splits the polygon in two. To achieve this, draw a line by every vertex to decompose the polygon in slabs. The respective areas of the slabs will tell you what slab the desired line intersects. Simple linear interpolation will give the exact location of the line.
Now your polygon is split in two convex polygons. For each halve, repeat the above procedure using the perpendicular direction. In general, you will get two distinct splitters, and what remains to be done is to find the direction such that they do coincide.
In the given direction, the splitters intersect four specific edges of the polygon. If you slightly rotate, they still intersect the same four edges. You can decompose a full turn in angular ranges such that the four intersected edges remain the same.
Knowing the four intersected edges, you can establish the relation that tells you the distance between the two perpendicular splitters as a function of the angle. Then you can compute the angle at which the two splitters coincide, and check if this angle belongs to the range defined for these edges.
By trying all ranges in turn, you will find the solution.
Note: the limits of the angular ranges correspond to directions parallel or perpendicular to the lines joining two vertexes.

Find all polygons in points using MATLAB

I have a set of points in the plane and I want to find all convex polygons without including a point inside them.
For example I want to find all triangles, all four sized polygons, all four five sized polygons and so on until is possible to find them without including a point inside them.
In the image, row a corresponds to convex polygons of size 3. While column 1 and 2 show correct examples of what I want, column 3 shows a triangle including two points inside of it, which I dont want.
Rows b and c show examples of polygons of size 4 and 5.
b3 shows an example of a non convex polygon
I wonder if there is a function in MATLAB or any other language or if someone knows about an algorithm that can do it.
The algorithm could receive, beside the points, the size of the polygons to search, it would return all possibly correct polygons or empty if does not contain any polygon of that size.
I appreciate the help.
Step 1: Perform a Delaunay-Triangulation of the points.
Step 2:
For polygons of size 3: resulting triangles are the result.
For polygons of size 4: pick any pair of triangles that share two corners
For polygons of size 5: pick any polygon of size 4 and pair it with a
triangle that shares exactly two corners
You can try the naive solution if it is feasible :-
select k points for k sided polygon
apply convex hull alogrithm on it
if convex hull size equal k then the set of points form desired k sided polygon.
Time Complexity:- O(2^N*N*logN)

Algorithm for the decomposition of polygons

Does anyone know a relatively fast algorithm for decomposing a set of polygons into their distinct overlapping and non-overlapping regions, i.e. Given a set of n polygons, find all the distinct regions among them?
For instance, the input would be 4 polygons representing circles as shown below
and the output will be all polygons representing the distinct regions shown in the different colours.
I can write my own implementation using polygon operations but the algorithm will probably be slow and time consuming. I'm wondering if there's any optimised algorithm out there for this sort of problem.
Your problem in called the map overlay problem. It can be solved in O(n*log(n)+k*log(k)) time, where n is the number of segments and k is the number of segment intersections.
First you need to represent your polygons as a doubly connected edge list, different faces corresponding to the interiors of different polygons.
Then use the Bentley–Ottmann algorithm to find all segment intersections and rebuild the edge list. See: Computing the Overlay of Two Subdivisions or Subdivision representation and map overlay.
Finally, walk around each cycle in the edge list and collect faces of that cycle's half-edges. Every set of the faces will represent a distinct overlapping region.
See also: Shapefile Overlay Using a Doubly-Connected Edge List.
I don't think it is SO difficult.
I have answered the similar question on the friendly site and it was checked by a smaller community:
https://cs.stackexchange.com/questions/20039/detect-closed-shapes-formed-by-points/20247#20247
Let's look for a more common question - let's take curves instead of polygons. And let's allow them to go out of the picture border, but we'll count only for simple polygons that wholly belong to the picture.
find all intersections by checking all pairs of segments, belonging to different curves. Of course, filter them before real check for intersection.
Number all curves 1..n. Set some order of segments in them.
For every point create a sequence of intersections SOI, so: if it starts from the border end, SOI[1] is null. If not, SOI[1]= (number of the first curve it is intersecting with, the sign of the left movement on the intersecting curve). Go on, writing down into SOI every intersection - number of curve if there is some, or 0 if it is the intersection with the border.
Obviously, you are looking only for simple bordered areas, that have no curves inside.
Pieces of curves between two adjacent non-null intersection points we'll call segments.
Having SOI for each curve:
for segment of the curve 1, starting from the first point of the segment, make 2 attempts to draw a polygon of segments. It is 2 because you can go to 2 sides along the first intersecting curve.
For the right attempt, make only left turns, for the left attempt, make only the right turns.
If you arrive at point with no segment in the correct direction, the attempt fails. If you return to the curve 1, it success. You have a closed area.
Remember all successful attempts
Repeat this for all segments of curve 1
Repeat this for all other curves, checking all found areas against the already found ones. Two same adjacent segments is enough to consider areas equal.
How to find the orientation of the intersection.
When segment p(p1,p2) crosses segment q(q1,q2), we can count the vector multiplication of vectors pXq. We are interested in only sign of its Z coordinate - that is out of our plane. If it is +, q crosses p from left to right. If it is -, the q crosses p from right to left.
The Z coordinate of the vector multiplication is counted here as a determinant of matrix:
0 0 1
p2x-p1x p2y-p1y 0
q2x-q1x q2y-q1y 0
(of course, it could be written more simply, but it is a good memorization trick)
Of course, if you'll change all rights for lefts, nothing really changes in the algorithm as a whole.

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