tags:

views:

203

answers:

3

Let's say I have a (convex) polygon with vertices 0..n-1. I want to split this polygon in half, say, between verticies i and j. Vertices i and j should appear in both polygons.

As far as I can tell, there are only two cases. One where i < j, or when i > j. i is never equal to j (nor are they ever adjacent).

I'm storing my vertices like vector<Point> poly. You can assume Point is just a basic struct with two doubles x and y, with points indexed sequentially in CCW order.

If i < j, then I just need to copy the vertices from i to j (inclusive) into one vector, and then from j to n-1 plus 0 to i into another. Or vice versa for the other case, right?

Here's the code I'm using, but it doesn't seem to work right (let j == closestIndex):

if (i < closestIndex) {
 lowerPoly.insert(lowerPoly.end(), poly.begin() + i, poly.begin() + closestIndex + 1);
 upperPoly.insert(upperPoly.end(), poly.begin() + closestIndex, poly.end());
 upperPoly.insert(upperPoly.end(), poly.begin(), poly.begin() + i + 1);
} else {
 lowerPoly.insert(lowerPoly.end(), poly.begin() + i, poly.end());
 lowerPoly.insert(lowerPoly.end(), poly.begin(), poly.begin() + closestIndex + 1);
 upperPoly.insert(upperPoly.end(), poly.begin() + closestIndex, poly.begin() + i + 1);
}
+3  A: 

I think there's another restriction you need to include, in addition to i never equal to j.

You also need to ensure that if i is the starting point that you aren't splitting at either i-1 or i+1. If the sides are linear, splitting at consecutive points means that the dividing line is simply an edge, so you get back the original polygon and an edge line, which doesn't seem very interesting.

Instead of two arrays x and y, I'd recommend a single array of 2D points, with verticies numbered consecutively in a counterclockwise direction around the polygon.

So the two polygons will be:

Polygon 1 : start with i, iterate to the ending point j, and finish with the edge from j back to i;

Polygon 2: start with i, to the ending point j, and then over j+1, j+2, back to i.

duffymo
I should have mentioned that they are never adjacent either. And I'm not using two arrays with x and y... its a vector of 2D points (I wrote that, didn't I?). They are indeed numbered sequentially in CCW order too. Polygon 1 makes sense, but I don't know what you mean by j+1, j+2 in the second case.
Mark
Sorry, now that re-read your post you did indeed say that. Easiest case is a rectangle numbered 1, 2, 3, 4. You can split it into two triangles: (1, 2, 3, 1), and (1, 3, 4, 1).
duffymo
Ah..okay. I don't need the redundant starting point, but I see what you're saying now. The logic behind it is fine, but there's something wrong with my implementation. The cases around 0 seem to be messing me up.
Mark
Hang on a second, there might actually just be an issue with how I am displaying the results, this code *could* be fine.
Mark
A: 

My bad. The code above is fine, there was a problem with my display routine. I was pushing too many polygons onto the stack, so it only looked incorrect. Should have been obvious, but I didn't spot it. Thanks for the help duffymo.

Mark
+2  A: 

As a side note:

You don't really have 2 cases. If i > j then just swap i and j. Then you are always in the case where i < j, assuming i != j.

I would probably code it like follows:

if (i > closestIndex) 
    std::swap (i, closestIndex);
assert(closestIndex - i > 1); 
// make sure i != closestIndex and i is not adjacent to closestIndex

lowerPoly.insert(lowerPoly.end(), poly.begin() + i, poly.begin() + closestIndex + 1);
upperPoly.insert(upperPoly.end(), poly.begin() + closestIndex, poly.end());
upperPoly.insert(upperPoly.end(), poly.begin(), poly.begin() + i + 1);
rlbond
Wow. I feel really stupid today. Didn't think of that either. Thanks!!
Mark