I am trying to implement a mesh simplification algorithm by doing a series of edge collapses. Currently, I am going through each triangle and then collapsing the shortest edge and the algorithm is stable(doesn't go out of bounds). But beyond a point, it starts to create broken(holes) artifacts. What is the correct way to determine whether an edge is collapsible or not so that it doesn't lead to non-manifold artifacts(or mesh)?
NOTE: I use a half-edge data structure. Also, I do not want to use any external libraries like OpenMesh or CGAL. I have my reasons for not using them.
There are two main conditions for an edge collapse:
Connectivity
On each side of the collapsed edge, only one pair of edges must be merged. This can be checked by counting the joint neighbour vertices of the two merging vertices (there must be exactly two).
Consider the following example where the red edge is being collapsed:
The triangle between the orange and cyan edge is not manifold anymore.
Geometry
Triangles must not flip during the edge collapse. This can be checked by calculating the angle between the triangle normal before the flip and after the flip for triangles that are kept.
Here is an example where the normal of the green triangle is flipped during the collapse:
Related
I am trying to implement a half edge structure. It looks like this:
vertex:
edge
position
edge:
vertex
face
previouse edge
next edge
twin edge
face:
edge
now i noticed a problem when the mesh has two disconnected faces that share one vertex. For example in the case that all edge twins are null. I this case i can't find all edges from a vertex anymore.
image of a problem case.
In the image the vertex in the middle has only a reference to an edge of the white face. The black face is not reachable. How can i make this possible with the half edge structure?
Half-edge data structure allows only to represent manifold surfaces, thus this configuration is not allowed....
... but, if you add an unbounded face, the surface becomes manifold and you can describe this configuration. This is usually the solution used in the main library that implement HDS data structures.
With this unbounded face, each edge has two half-edges (there is no more null twin), and you need a way to differentiate half-edges that belong to the unbounded face and other half-edges (sometimes the unbounded half-edges have a null face).
Last remark, if you have several connected component, you will have several unbounded faces.
I am working with several convex polygons that overlap each other and I need to combine them back together to form one single polygon that may be convex or concave.
The problem is always as follows:
1) The polygons that I need to merge together are always convex.
2) The vertices of each polygon are defined in clockwise order.
3) The polygons are never in any specific order.
4) The final polygon can only be simple convex or concave polygon, i.e. no self-intersection, no duplicate vertices or holes in the shape.
Here is an example of the kind of polygons that I am working with.
![overlapping convex polygons]"image removed")
My current approach is to start from the first polygon and vertex by vertex I loop through all vertices of all of the polygons to find overlap. If there is no overlap, I store the vertex for the final outline and continue.
Upon finding overlapping vertices, I determine which polygon to continue to by measuring the angles of the possible paths and by choosing the one that leads towards the outside of the shape.
This method works until I encounter polygons that do not have vertices overlapping each other, but instead one polygon's vertex is overlapping another polygon's side, as is the case with the rectangle in the image.
I am currently planning on solving these situations by running line intersect checks for all shapes that I have not yet processed, but I am convinced that this cannot be the easiest or the best method in terms of performance.
Does someone know how I should approach this problem in a more efficient manner and/or universal manner?
I solved this issue and I'm posting the answer here in case someone else runs into this issue as well.
My first step was to implement a pre-processing loop based on trincot's suggestions.
I calculated the minimum and maximum x and y bounds for each individual shape.
I used these values to determine all overlapping shapes and I stored a simple array for each shape that I could later use to only look at shapes that can overlap each other.
Then, for the actual loop that determines the outline of the final polygon:
I start from the first shape and simply compare its vertices to those of the nearby shapes. If there is at least one vertex that isn't shared by another vertex, it must be on the outer edge and the loop starts from there. If there are only overlapping vertices, then I add the first shape to a table for all checked shapes and repeat this process with another shape until I find a vertex that is on the outer edge.
Once the starting vertex is found, the main loop will check the vertices of the starting shape one by one and measure how far from the given vertex is from every nearby shapes' edges. If the distance is zero, then the vertex either overlaps with another shape's vertex or the vertex lies on the side of another shape.
Upon finding the aforementioned type of vertex, I add the previous shape's number to the table of checked shapes so that it isn't checked again. Then, I check if there are other shapes that share this particular vertex. If there are, then I determine the outermost shape and continue from there, starting back from step 2.
Once all shapes have been checked, I check that all non-overlapping vertices from the starting shape were indeed added to the outline. If they weren't, I add them at the end.
There may be computationally faster methods, but I found this one to be simple to write, that it meets all of my requirements and it is fast enough for my needs.
Given a vertex, you could speed up the search of an "overlapping" vertex or edge as follows:
Finding vertices
Assuming that the coordinates are exact, in the sense that if two vertices overlap, they have exactly the same x and y coordinates, without any "error" of imprecision, then it would be good to first create a hash by x-coordinate, and then for each x-entry you would have a hash by y-coordinate. The value of that inner hash would be a list of polygons that have that vertex.
That structure can be built in O(n) time, and will allow you to find a matching vertex in constant time.
Only if that gives no match, you would go to the next algorithm:
Finding edges
In a pre-processing step (only once), create a segment tree for these polygons where a "segment" corresponds to a min/max x-coordinate range for a particular polygon.
Given a vertex, use the segment tree to find the polygons that are in the right x-coordinate range, i.e. where the x-coordinate of the vertex is within the min/max range of x-coordinates of the polygon.
Iterate those polygons, and eliminate those that do not have an y-coordinate range that has the y-coordinate of the vertex.
If no polygons remain, the vertex does not participate in any edge of another polygon.
You cannot get more than one polygon here, since that would mean another polygon shares the vertex, which is a case already covered by the hash-based algorithm.
If you get just one polygon, then continue your search by going through the edges of that polygon to find a match -- which is what you already planned on doing (line intersect check), but now you would only need to do it for one polygon.
You could speed that line intersect check up a little bit by first filtering the edges to those that have the right x-range. For convex polygons you would end up with at most two edges. At most one of those two will have the right y-range. If you get such an edge, check whether the vertex is really on that edge.
In my program I have created a Geometry from the vertices of an intersection between a plane and a mesh. I use this Geometry to create a LineSegments object and it works perfectly. I would like to use the vertices in a couple of other ways as well, but the array of vertices in the Geometry is not in the correct order (the order that LineSegments draws them). I am unable to find where the information is stored that allows LineSegments to draw lines between the vertices in the correct order. The link below shows the problem:
https://gamedev.stackexchange.com/questions/99353/vertex-ordering-with-threejss-exporter
There is only one answer that suggests that you check the faces for more information, but from what I can see there is no information about the faces in my Geometry, it only contains the vertices that I put in there.
Any help would be much appreciated!
In a watertight and topologically correct mesh, every edge is shared by exactly two faces. When you cut by a plane, the two faces generate two edges that meet at a vertex, where the common edge pierces the plane.
So if you have a model such that you can reliably pair the edges of the faces (or if the edges are listed uniquely), you can obtain a list of section edges where the vertices are shared by two edges, and describe a closed polygon (unless the surface itself is open).
You can reconstruct this polygon by going from edge to edge, through the common vertices.
For instance, consider the cube below and assume that its faces are labeled left, right, front, back, top, bottom.
The section is made of five edges that can be labeled lt-rt, rt-rf, rf-bf, bf-lb, lb-lt.
The problem is to redraw a self-intersecting 2D polygon, whose border is always a separation line between its interior and its exterior and completely crosses itself in some points (that is, in those points, the polygon interior switches the side of the border, from left to right or vice versa).
What is the simplest algorithm that can do that?
The initial polygon (left) and the redrawn one (right):
.
I added another, a little more complicated example of an initial polygon, that is still very simple (it has only one self-intersection vertex) in this third picture where the polygon interior is filled (points A,B,C,D,E appear in alphabetic order initially when drawing the polygon border).
What you are asking isn't that simple.
You can use a sweepline procedure. The general principle is as follows.
When you draw an horizontal line across the polygon, it meets an even number of edges. Sorting the intersections from left to right, and linking them in pairs, you obtain interior segments.
If you do this for all positions of the horizontal, you will decompose the polygon in a number of monotone chains, i.e. polylines always going down.
When the polygon is simple, the chains appear in pairs at a vertex, disappear in pairs at another, and live their own lifes. But when the polygon is crossed, the chains can cross each other. This can be detected by the fact that from one position of the horizontal to the next, the ordering of intersections change.
Now you have to fix that by "uncrossing" the chains, which is done by splitting the edges at the intersection point.
I can't develop more here, try and lookup "sweepline algorithm".
I have a map of polygons, for example:
alt text http://img13.imageshack.us/img13/2808/output.png
(sorry the image isn't so great, I'll try and get better one later)
The green lines are the shortest path from between the connected shapes. What I need to do is find the green lines that form the outer edge and which direction I need to traverse them in to circle CCW.
The polygons will always be convex and the lines will never cross. The lines are defined in terms of there X,Y endpoints. I have an index from polygons to related lines and it is tagged with which end is attached.
The reason I need this is because I need to find the edges forming each of the interior section and my wall following solution fails/crashes for the exterior section.
0. Clarification: I am not sure whether the green connections between the convex polygons are provided as part of the input or whether the program has to determine the appropriate green connections as shortest paths between polygons itself. I just noticed that your image is missing a green edge at the top right corner (that would be part of outer border if allowed).
1. Solution: Always choose the next edge. If your input specifies which green lines are allowed and which not, then you simply traverse the boundary of the outside component by finding one start point (e.g. by taking the polygon corner with lowest x-coordinate), ordering the green edges that depart from the polygon of this current point in counter-clock-wise order and choosing the edge immediately following the current point in CCW order. Now, take the other end of that edge as "current point" and repeat the same method to find the next edge... until you return to the first polygon.
2. Solution: Start with the convex hull. If you allow all possible green lines, you don't need them as input. The convex hull of all polygon edges is a first approximation to your solution (details of finding --- see further below): The convex hull contains real polygon edges (let's think of them as "black": They are part of your final solution, already in correct order) and edges that connect polygons (Let's think of them as red: They need to be replaced by green edges and possibly parts of other polygons).
Completing the 2nd solution: divide and conquer: Now, we need to replace each red edge by a combination of green and black edges. We just focus on one red line at a time (and apply the same method for each red line that we may have).
So we have one red line that contains two polygons that have one green line (the shortest connection between them) --- the four edges of these two lines define a quadrangle. If none of the other polygon corners are in this quadrangle, you are done: replace the red edge by the green edge and any black edges on the polygons to get to the connecting points.
But if you find polygon in the quadrangle, select from them the closest to the red edge. Move the red edge towards that point --- so that the new point cuts the red edge into two red edges. These two new red edges replace the one old red edge: apply this method recursively to both of them. Their corresponding quadrangles are much smaller and contain less polygon edges.
As you keep applying this divide and conquer method you will eventually end up with no remaining red edges (because you loose one red edge each time you find an empty quadrangle).
Convex hull: This is a difficult problem in n dimensions but easy in two dimensions: If you search the net or browse SO, you surely find a better solution than I can think of right now, but here is one that comes to mind (again: divide and conquer): Find one point A with maximal x-coordinate and one point B with minimal x-coordinate, connect them by two directed "blue" edges: A->B and B->A. Divide your points into two sets: those at the right hand side of the edge A->B and those on the left hand side (which really is the right hand side of B->A). We repeatedly replace each blue edge until we find the convex hull:
Take one blue edge A->B and look at the points its right hand side. If there are none, then this blue edge is really black (part of your solution). Otherwise, take the point C furthest to the right of the blue edge and replace the edge A->B by two blue edges A->C and C->B. Divide the points that were at the right hand side of A->B into those that are at the right hand side of A->C, those that are at the right hand side of C->B and those that are neither (they are ignored). Repeat until all blue edges are replaced.