我一直试图用我的Sutherland-Hodgman Polygon Clipper算法来解决这个问题。填写多边形时,我会得到以下结果:
我似乎无法弄清楚导致错误的原因,这是我的代码:
// @param in the number of vertices in the polygon to be clipped
// @param inV the incoming vertex list
// @param outV the outgoing vertex list
// @param ll the lower-left corner of the clipping rectangle
// @param ur the upper-right corner of the clipping rectangle
//
// @return number of vertices in the polygon resulting after clipping
int Clipper::clipPolygon( int in, const Vertex inV[], Vertex outV[],
Vertex ll, Vertex ur )
{
int out = 0, out2 = 0, out3 = 0, out4 = 0;
Vertex *outV2, *outV3, *outV4;
// We clip entire figure by clipping on the 4 edges of the clipping window
// each step will be stored, in *out pointers.
SHPC(inV, outV, in, out, ll.x, ur.y, ll.x, ll.y); // left
outV2 = new Vertex[out];
SHPC(outV, outV2, out, out2, ll.x, ll.y, ur.x, ll.y); // bottom
outV3 = new Vertex[out2];
SHPC(outV2, outV3, out2, out3, ur.x, ll.y, ur.x, ur.y); // right
outV4 = new Vertex[out3];
SHPC(outV3, outV4, out3, out4, ur.x, ur.y, ll.x, ur.y); // top
// we want outx and outy to store the final clipped polygons, which
// means we need to get content of outx4 and outy4
for (int i = 0; i < out; i++) { outV[i].x = outV4[i].x; outV[i].y = outV4[i].y; }
// same principle for out value
out = out4;
delete[] outV2;
delete[] outV3;
delete[] outV4;
return out;
}
void Clipper::SHPC(const Vertex inV[],
Vertex outV[], int in, int &out,
float x0, float y0, float x1, float y1) {
float px = inV[in - 1].x, py = inV[in - 1].y; // last vertex is the initial “predecessor”
float _x = px, _y = py;
for (int j = 0; j < in; j++) {
if (inside(inV[j].x, inV[j].y, x0, y0, x1, y1)) { // Cases 1 & 4
if (inside(px, py, x0, y0, x1, y1)) { // Case 1
output(inV[j].x, inV[j].y, out, outV);
}
else { // Case 4
intersect(px, py, inV[j].x, inV[j].y, x0, y0, x1, y1, _x, _y);
output(_x, _y, out, outV);
output(inV[j].x, inV[j].y, out, outV);
}
}
else { // Cases 2 & 3
if (inside(px, py, x0, y0, x1, y1)) { // Case 2
intersect(px, py, inV[j].x, inV[j].y, x0, y0, x1, y1, _x, _y);
output(_x, _y, out, outV);
} // Case 3 has no output
}
px = inV[j].x;
py = inV[j].y;
} // for
}
// is point inside boundary?
bool Clipper::inside(float _x, float _y, float x0, float y0, float x1, float y1) {
if (y0 == y1) { // horizontal edge
if (x0 < x1) return _y >= y0;
if (x0 > x1) return _y <= y0;
} else { // vertical edge
if (y1 > y0) return _x <= x0;
if (y0 > y1) return _x >= x0;
}
return false;
}
// put point into vector, update length
void Clipper::output(float _x, float _y, int &out, Vertex outV[]) {
outV[out].x = _x;
outV[out++].y = _y;
}
// compute intersection point, put point into newpoint parameter
void Clipper::intersect(float sx, float sy, float ex, float ey, float x0, float y0, float x1, float y1, float &_x, float &_y) {
if (x0 == x1) { // if it's a vertical edge
_x = x0;
_y = sy + (x0 - sx) * (ey - sy) / (ex - sx);
}
else { // if it's a horizontal edge
_y = y0;
_x = sx + (y0 - sy) * (ex - sx) / (ey - sy);
}
}
如果我不得不猜测我会说这是我的内部功能的一个问题,但这就提出了一个问题,为什么它只是不适用于明星而不适用于其他形状?我尝试重写内部函数,但它通常只在不同的方向上导致相同类型的错误。如果有人能指出我正确的方向,我会很感激。