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.
Related
Consider the picture :
Given the black "irregular line" segments, I want to have the green boundary surrounding them.
My Attempt to solve :
Note, that I need to capture the concavity. Thus the convex hull algorithm will not work. I have used some interpolations, to draw the straight line segments indicated by overlayed red stripes. Then I attempted to run a sweep algorithm. These stripes are roughly parallel, if that helps.
That is, their headings lay within some small interval.
Heading H in { angle alpha - x , angle alpha +x } union { angle alpha - x + 180 , angle alpha +x+ 180 } for some small x
However, it needs to be guaranteed, that the green boundary should not intersect any red lines.
So, my naive attempt was :
Start at leftmost vertex of all lines.
Pick the line attached to the vertices. (if more vertices, then take the top most and bottom most)
Use this line to "partition" the plane. (or two lines or two "separatices", if 2 vertices)
Pick the next leftmost unvisited vertices.
See if the vertex lies above the top separatrix or below the bottom separatrix.
If above the top separatrix, add it to a set called "top chain", if below the bottom one, the add to bottom chain.
But this runs into problems.
The problem
To determine whether the newly picked point is at the top or at the bottom of a separatrix, I use the vector product method. But consider this :
Imagine you are at the green square. Your separatrix now is the black line, vector pointing to the left, as the arrow shows.
At this stage, you compare this with the green vector showing the next vertex to be picked on the blue line. The vector method, intended to measure angles between -Pi to Pi will consider this a negative value. Thus the point, although necessary, will not be picked up.
If you reverse the direction of the vector, then the Magenta line will not be picked up.
Question
How to efficiently solve this problem? I am using D, so bonus if there is a D library capable of this.
Filling concavities is a somewhat arbitrary operation. Have a look at Alpha-shapes, a generalization of the convex hulls.
https://en.wikipedia.org/wiki/Alpha_shape
The problem is relatively simple, determine if a polygon is completely inside, completely outside, or cut by another polygon, however, the polygons may share vertices or parts of edges.
First I thought just check for every vertex in polygon A if it lies inside/outside of polygon B, this fails as soon as B cuts A, see:
Left: A would be classified as outside of B
Right: A would be classified as in the inside of B
The next Idea was, check for intersections if there are any, it's classified as cut, if there are none, check for any point of A if it's inside B. This, however, fails in cases where this checked point falls on an edge of B, where it could be both, inside or outside.
So, just check the all points of A against B, until a point is found that doesn't lie on an edge of B, this, however, can also fail, if all points of A lie on edges of B, see:
Left: A should be classified as inside
Right: A should be classified as outside
So the question remains, how can you in this case without a doubt determine if polygon A lies inside or outside polygon B, if edges and vertices may be shared.
So all vertices of the green polygon lie on the boundary of the black polygon, and there are no "obvious" x-shaped edge intersections (you should have already already eliminated those; or you could insert an artificial vertex at each intersection point to reduce the problem to the below case).
First, for every vertex of either polygon that lies on the boundary of another polygon, insert an artificial vertex to the other polygon at that point (if there isn't one already there). You do that for all green vertices, and maybe some black vertices. This is needed so that all edge intersections are simple. Two edges have no common points, one common point (at their common vertex), or all common points (both vertices and everything in between; such edges are identical).
Once all intersections are simple, the problem is easy.
For all midpoints of green edges, determine if said midpoints are inside or outside of the black polygon. Discard those that are on the boundary.
If they are all inside, the green polygon is inside the black one. If all are outside, then it is NOT inside (could be outside, or the black one could be inside the green one; reverse the roles and do the procedure again to determine which is the case). If some are inside and some outside, then there's a funny intersection.
Don't have any midpoint that is not on the boundary? The two polygons are identical.
If you want an algorithm, you can find two O(nlog(n)) algorithm in this article (Two efficient algorithms for determining intersection points between simple polygons) for the intersection of two simple polygones. Then, if you find that the intersection of two simple polygons is the same as one of them (order vertices and check their equalities), you will find the solution.
Moreover, you can find an implementation in python shapely package.
What algorithm to use so that we can determine that if the red dot belongs to Area1 or Area2.
my original idea was to divide the polygons into triangles using consecutive points and then use a known algorithm to determine if a point belongs to one of these triangles however there is a problem shown in the figure.p4 p5 p6 are point in Area 1 but they make a triangle in area 2.
Continue inifite ray from red point to any direction. Count intesections of such ray with any polygon. Even count of intersections indicates that point lies outside of polygon
You can use the idea of the polygon filling algorithm for that. If you know the vertices of a polygon, you can lay a horizontal ray through the red point and count the vertices it intersects. If the count is even, it is outside, otherwise it is inside.
If you imagine coming from the far left along that ray, the first intersection is entering the polygon, the second is leaving it, the third is entering again... and so on. So if the number is odd (1,3,5,...) you are inside the polygon when you hit the point, otherwise you are outside.
Here is the idea -
Draw a horizontal line to the right of red point and extend it to infinity
Count the number of times the line intersects with polygon edges.
A point is inside the polygon if either count of intersections is odd or
point lies on an edge
See Check if a point lies inside or outside a polygon.
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:
Is there a computationally efficient way to determine the points of intersection of a straight line with all the edges of a given Voronoi tessellation in a rectangular plane area?
Thanks
Once you have your first intersection point, the rest is easy.
Prepare a database of edges: for each edge, list both polygons it belongs to, or say it is the outer edge (and so belongs to one polygon only). In your picture, the lower side of the rectangle would contain 4 edges of 4 different polygons.
Draw your line, find your first intersection point ([0, 0.25] in your picture, not circled). Say it's polygon A. Then the next intersection point (the lowest one circled in your picture) also belongs to A. You find the relevant edge with a binary search through the list of edges of A.
Now you have found the second edge of A, find out which other polygon it belongs to. Then use binary search to find which other edge of that other polygon the line intersects. And so on until you exit your rectangle.