Given a mesh consisting of a list of vertices (2D coordinates) and edges (as vertex pairs), like so:
So the edges are defined like this:
a: 2,3
b: 3,4
c: 4,8
d: 5,8
e: 6,7
etc..
Edges are orientation-neutral, i.e. the order of any two vertices that define an edge is random (edges are not clockwise or counter clockwise).
Polygons may be convex or concave, but they never overlap or self-intersect (edges never cross eachother).
Question: how do I generate a list of all polygons?
More specifically, in the above example I would need 4 polygons, like so:
(a,b,c,d,i)
(d,g,h)
(f,i,j,k)
(e,h,k)
The polygons have no orientation either, clockwise or counterclockwise does not apply, and in fact the order of the edges that define a polygon may be random as well. For example (a,i,d,b,c) for the 5-sided one would be fine as well.
Instead of defining polygons as a list of edges, it could also be a list of connected vertices, like so:
(2,3,4,8,5)
(6,5,8)
(2,5,7,1)
(7,6,5)
In this case, the order of the vertices cannot be random (the list of vertices should be a circular sequence) but orientation (clockwise or counterclockwise) is still irrelevant. So the 4-sided polygon could also be (5,2,1,7) or (1,7,5,2) et cetera.
What is an efficient (fast) way to construct a list of polygons, defined in either edges or vertices?
For each edge vw, generate two half-edges v->w and w->v. Partition these by head (the head of x->y is y). Within each partition, sort by angle (if you use a comparison sort, then there's a way to avoid trig).
For your sample graph, the result is
7->1, 2->1
1->2, 5->2, 3->2
2->3, 4->3
8->4, 3->4
7->5, 6->5, 8->5, 2->5
8->6, 5->6, 7->6
6->7, 5->7, 1->7
5->8, 6->8, 4->8
. Now, define a permutation where v->w maps to the half-edge following w->v in the list containing w->v (wrapping around if necessary). The cycles of this permutation are the polygons.
For example, 5->8 maps to 2->5 (after 8->5) maps to 3->2 (after 5->2) maps to 4->3 (after 2->3) maps to 8->4 (after 3->4) maps to 5->8 (after 4->8).
Related
I have a roughly planar mesh that I would like to find the outline of. To find the outline, I loop through all the triangles of the mesh and count the number of occurrences of each edge (represented by an unordered pair of vertices).
After examining all the triangles, there are only two possible values for each edge.
edge count = 1 : the edge belongs to a single triangle and so it is an outer edge
edge count = 2 : the edge is shared between two
triangles and so it is an inner border
Edges belonging to a single triangle (edge count = 1) define the mesh outline.
This strategy works pretty well, if it weren't for a problem, which I will try to illustrate with an example. Suppose we want to find the outline of the following mesh.
If we apply the strategy described above to this mesh, it will find the seven edges that define the outline - i.e. (0,1), (1,4), (4,7), (6,7), (5,6), (2,5) and (0,2) - but it will also find three inner edges, i.e. (2,3), (3,4) and (2,4), which belong to only one triangle each, respectively (2,3,6), (3,4,7) and (0,2,4).
I have thought of the following solution to solve the problem. As far as I can think, the issue can only arise when there are three vertices that lie on the same line as in the example above. The two short edges that connect the three vertices can be replaced by a single longer edge that connects the two outer vertices. This new edge is added to the list of edges or if already present its counter will be increased by one, reaching value 2. Iterating the procedure (following the path defined by the edges), I should simplify the list of edges and finally only those on the mesh outline should have count 1.
What do you think of my approach? Thanks.
The 2-3-4 configuration is "pathological" as it breaks the graph structure. In fact, this can be seen as a triangular hole in the mesh.
A possible way to handle is to list all single edges, detect the ones that overlap, and ignore them.
Given a triangular mesh A in 3D space. Rotate and translate all its points to generate a new mesh B.
How to determine the equality of A and B, just by their vertices and faces?
Topology of the mesh is not important, I only care about the geometric equality, A and B should be equal even if their triangulation are changed. It is
something like the transform in-variance problem for triangular mesh, only translate and rotation is considered.
To complete #Spektre's answer, if the two meshes are not exactly the same, that is there is at least a pair of nodes or edges which does not perfectly overlap, You can use the Hausdorff distance to quantify the "difference" between the two meshes.
Assuming triangle faces only.
compare number of triangles
if not matching return false.
sort triangles by their size
if the sizes and order does not match between both meshes return false.
find distinct triangle in shapes
So either the biggest or smallest in area, edge length or whatever. If not present then you need other distinct feature like 2 most distant points etc ... If none present even that then you need the RANSAC for this.
Align both meshes so the matching triangles (or feature points) will have the same position in both meshes.
compare matching vertexes
so find the closest vertex form Mesh A to each vertex in mesh B and if the distance of any them cross some threshold return false
return true
In case meshes has no distinct features for 3 you need to either use brute force loop through all combinations of triangles form A and B until #4 returns true or all combinations tested or use RANSAC for this.
There are alternatives to #3 like find the centroid and closest and farthermost points to it and use them as basis vectors instead of triangle. that requires single vertex or close group of vertexes to be the min and max. if not present like in symmetrical meshes like cube icosahedron, sphere you're out of luck.
You can enhance this by using other features from the mesh if present like color, texture coordinate ...
[Edit1] just a crazy thinking on partial approach without the need of aligninig
compute average point C
compute biggest inscribed sphere centered at C
just distance from C to its closest point
compute smallest outscribed sphere centered at C
just distance from C to its farthest point
compare the radiuses between the shapes
if not equal shapes are not identical for sure. If equal then you have to check with approaches above.
The paper On 3D Shape Similarity (Heung-yeung Shum, Martial Hebert, Katsushi Ikeuchi) computes a similarity score between two triangular meshes by comparing semiregular sphere tessellations that have been deformed to approximate the original meshes.
In this case, the meshes are expected to be identical (up to some small error due to the transformation), so an algorithm inspired by the paper could be constructed as follows:
Group the vertices of each mesh A, B by the number of neighboring vertices they have.
Choose one vertex V_A from mesh A and vertex V_Bi from mesh B, both with same number of neighbors.
The vertex and its N neighbors V_n1...V_nN form a triangle fan of N triangles. Construct N transforms which take vertex V_Bi to V_A and each possible fan (starting from a different neighbor V_Bn1, V_Bn2, ..., V_BnN) to V_An1...V_AnN.
Find the minimum of the sums of distances from each vertex of B to the closest vertex to it in A, for each N transforms for each vertex V_Bi.
If a sum of near zero is found, the vertices of the transformed mesh B coincide with vertices of A, a mapping between them can be constructed, and you can do further topological, edge presence or direction checks, as needed.
Suppose you have a set of triangles, like the one shown in the image below, where black is a triangle edge, red is a triangle point, green is the polygon that needs to be found, and blue is the polygon's points.
The polygon described may or may not be concave. The triangles in it will always be adjacent (share all three points with the other triangles in the set).
What sort of algorithms exist to generate the polygon that such a set of triangles describes? The polygon should be in the form of a list of points in clockwise or counter-clockwise order.
How About Following A simple GrahamScan Algo... That's should Do the Trick.
Assume you have N distinct points Pi and M triangles. We define each triangle by 3 indices i, j and k to the points. Each triangle will have 3 edges defined as E(i,j), E(j,k) and E(i,k). The way to find the "polygon" is as follows:
1) Loop thru all triangles. For each triangle, add the 3 edges into a set. Edges with two identical point indices should be considered as the same edge. Namely, E(i,j) = E(j,i). Once encounter such case, remove both E(i,j) and E(j,i) from the set as these are the interior edges.
2) The remaining edges in the set should be the edges forming the polygon.
3) Sort the edges in the set by the point indices as follows:
(3a) Pick any edge from the set, say E(i,j).
(3b) Add indices i and j into a std::vector, then remove E(i,j) from the set.
(3c) Find the edge from the set that shares the last point index in the std::vector (which is j now). Denote this edge as E(j,k). Add index k into the std::vector and remove E(j,k) from the set.
(3d) Repeat step (3c) until the set contains no edges. The point indices in the std::vector will be the points order for the polygon.
If you only have M triangles and 3*M (x, y) values for the triangle vertices, then you will need to do some pre-processing to remove identical points and re-define the triangles in terms of the point indices as stated above.
the polygons image
All of the polygons are simply, there are no holes in them.
board polygon(P0 to P7)
Red polygon (R0 to R6)
Green polygon (G0 G1 P2 G3)
Yellow polygon(Y0 to Y3)
I want to got new four polygons marked as 1 to 4 , polygon 1's coordinates are(J7 J10 R5 R4).
When I use polygon clipping algorithm, I can got the results easy , board diff(red union green union yellow). But when I have more than 10,000 polygons, I need a long time to get my results. My polygons are simply and my result polygons are simply also, there are no holes in the result polygons also.
You know I can find out the four polygons form the image easy using eyes, but how to find them using algorithm.
Thanks.
If all vertices of your computed black polygons do not have more than 2 edges intersecting at the vertex, then there may be a faster way than a more general tool.
Since the number of polygons is on the order of 10000, first try computing the intersection points of all pairs of polygons, and hopefully the number of intersection points is small enough (like 10 million or less). Then, for each intersection point test to see if it is contained in the interior of another polygon (in case you have multiple polygons that jointly overlap). Testing to see if a point is contained in the interior of a polygon can be done quickly, you can read how online. Then, all intersection points that are not contained in another polygon, which note also contains all the original polygon vertices that are not contained in the interior of a polygon, these are the vertices for the "black" polygons you want to compute. These points should be stored with a secondary structure that for each polygon edge, it stores all the stored intersection points along that edge, in sorted order. Similarly, for each stored vertex and intersection point you should store the edges that intersect at that point, and the location of the intersection point in the previous structure. So then pick any stored intersection point that hasn't been used yet in a black polygon, and pick one edge that defines the intersection point. Then you move to the neighboring intersection point along the edge which has the property that the part of the edge between the two intersection points does not pass inside a polygon. Then continue by similarly moving along the other edge that defines the neighboring intersection point. Continue until you reach the vertex you started at; this defines one black polygon. Then you can pick a new unused stored intersection point and repeat. Since your polygons have no holes, this will find all black polygons.
In quickhull algo, there's need to build a cone upon set of edges.
An edge is thought as subsimplex with one vertex removed.
It is required, that adding a vertex to an edge will form a simplex, as if that vertex was just replaced.
For instance, when storing simplices as lists of vrtices, for triangle defined with vertexen {p0,p1,p2} edges are: {p1,p2},{p2,p0},{p0,p1} - in this index order.
Now, when adding new vertex p at the end of edge vertex list, new triangles are: {p1,p2,p},{p2,p0,p},{p0,p1,p} They have the same orientation as if original triangle was slanted.
For triangle, edge opposite to p1 has reversed order of remaining vertices.
For tetrahedron, it is for p0 and p2.
What is proper way of storing edges, or proper way to find out when to reverse vertices order?
Okay.
In general, storing vertex set is just not enough to represent a simplex, if its orientation matters. The same set can represent equivalent simplices with different sign of volume. A list can preserve orientation, but it's not trivial to derive it just from order. Thus, neither sets nor lists alone are not good solution (to represent both simplex and their edges).
It is probably best to use a list or tuple of vertices to represent a simplex; the question is how to decide the order of the vertices. (as I am not entirely certain of the exact requirements of an arbitrary-dimentional quickhull, I will speak generally below...)
If you are replacing each vertex v[i] in turn with a new point p, the simplest consistent thing to do is to substitute it for the point it replaces. Thus, for triangle {v0,v1,v2}, you will get new triangles {p,v1,v2}, {v0,p,v1}, and {v0,v1,p}.
If you want to reorder the vertices (e.g., so that p is at the end), then you should remember that swapping any two vertices will reverse the orientation of the simplex. So, to maintain the orientation, you must do an even number of swaps.
In the above example, swapping p with the final vertex will reverse the orientation, unless p is already the final vertex. You can fix this by swapping the first two vertices in that case. (note that this is a unique solution only for 3-vertex simplices -- it is not applicable for 2-simplices, and one of multiple solutions for N>3-simplices).
You could also look at this as a matter of rotating the vertex list of the original 3-simplex. Unfortunately, this only works for odd-vertex simplices. For a vertex list of size N, rotation involves N-1 swaps, so for a simplex with an even number of vertices, a rotation will change the orientation.
And edge of a simplex does not have an orientation by itself.
Only N-simplex in N-dimentions has defined orientation.
It is determined by cross-product of N vectors pi-p0 (signed volume).
For lower dimentional simlices in higher dimentional space such cross-product cannot be built.
For this patricular task (building new simplices with edges of another) an edge can be represented by an (ordered) list of vertices and an index where to add new point to make it on the same side as was removed vertex.
Considering cycling order of list (not sure it is universally valid), it could be rotated so that index is either 0 or 1.