算法原理:
参考连接:http://alienryderflex.com/polygon/,这里介绍得很详细,但是参考其中代码,实现下来,发现其中有一个bug,不知道是不是我自己的问题。
多边形绘制在原始图上:
为了高效,先确定多边形的坐标范围:
typedef struct boundary_t
{
int left;
int right;
int top;
int bottom;
}bound;
typedef struct loc_t
{
int x;
int y;
}loc;
void get_polygon_boundary(loc* poly, int count, bound* b)
{
if (!b)return;
int left, top, right, bottom;
left = top = INT_MAX;
right = bottom = INT_MIN;
int i;
loc pos;
for (i = 0; i < count; i++)
{
pos = poly[i];
if (pos.x < left)left = pos.x;
if (pos.y < top)top = pos.y;
if (pos.x > right)right = pos.x;
if (pos.y > bottom)bottom = pos.y;
}
b->left = left;
b->right = right;
b->top = top;
b->bottom = bottom;
}
这里所使用的多边形顶点,全部归一化到(0,1):
#define POLYGON_NODE_NUM 6
//多边形顶点
float polygon[POLYGON_NODE_NUM][2] =
{
{
0.15000000596046448,
0.28727272152900696
},
{
0.22857142984867096,
0.7236363887786865
},
{
0.22857142984867096,
0.7236363887786865
},
{
0.6471428275108337,
0.8054545521736145
},
{
0.6471428275108337,
0.8054545521736145
},
{
0.7814285755157471,
0.0672727301716804
}
};
上面链接中判断点是否在多边形内的方法:
bool point_in_polygon(loc* poly, int count, loc pos)
{
int i, j = count - 1;
bool oddNodes = false;
int x, y;
x = pos.x, y = pos.y;
for (i = 0; i < count; i++)
{
if ((poly[i].y < y && poly[j].y >= y|| poly[j].y < y && poly[i].y >= y)
&& (poly[i].x <= x || poly[j].x <= x))
{
oddNodes ^= (poly[i].x + (y - poly[i].y) / (poly[j].y - poly[i].y)*(poly[j].x - poly[i].x) < x);
}
j = i;
}
return oddNodes;
}
截取的多边形:
,对比一下图一中的多边形框和此图,明显存在问题。
因此,又搜索了一把, 在其他地方找的判断方法:
int lineIntersect(float v1x1, float v1y1, float v1x2, float v1y2,float v2x1, float v2y1, float v2x2, float v2y2)
{
float d1, d2;
float a1, a2, b1, b2, c1, c2;
// Convert vector 1 to a line (line 1) of infinite length.
// We want the line in linear equation standard form: A*x + B*y + C = 0
// See: http://en.wikipedia.org/wiki/Linear_equation
a1 = v1y2 - v1y1;
b1 = v1x1 - v1x2;
c1 = (v1x2 * v1y1) - (v1x1 * v1y2);
// Every point (x,y), that solves the equation above, is on the line,
// every point that does not solve it, is not. The equation will have a
// positive result if it is on one side of the line and a negative one
// if is on the other side of it. We insert (x1,y1) and (x2,y2) of vector
// 2 into the equation above.
d1 = (a1 * v2x1) + (b1 * v2y1) + c1;
d2 = (a1 * v2x2) + (b1 * v2y2) + c1;
// If d1 and d2 both have the same sign, they are both on the same side
// of our line 1 and in that case no intersection is possible. Careful,
// 0 is a special case, that's why we don't test ">=" and "<=",
// but "<" and ">".
if (d1 > 0 && d2 > 0) return NO;
if (d1 < 0 && d2 < 0) return NO;
// The fact that vector 2 intersected the infinite line 1 above doesn't
// mean it also intersects the vector 1. Vector 1 is only a subset of that
// infinite line 1, so it may have intersected that line before the vector
// started or after it ended. To know for sure, we have to repeat the
// the same test the other way round. We start by calculating the
// infinite line 2 in linear equation standard form.
a2 = v2y2 - v2y1;
b2 = v2x1 - v2x2;
c2 = (v2x2 * v2y1) - (v2x1 * v2y2);
// Calculate d1 and d2 again, this time using points of vector 1.
d1 = (a2 * v1x1) + (b2 * v1y1) + c2;
d2 = (a2 * v1x2) + (b2 * v1y2) + c2;
// Again, if both have the same sign (and neither one is 0),
// no intersection is possible.
if (d1 > 0 && d2 > 0) return NO;
if (d1 < 0 && d2 < 0) return NO;
// If we get here, only two possibilities are left. Either the two
// vectors intersect in exactly one point or they are collinear, which
// means they intersect in any number of points from zero to infinite.
if ((a1 * b2) - (a2 * b1) == 0.0f) return COLLINEAR;
// If they are not collinear, they must intersect in exactly one point.
return YES;
}
bool point_in_polygon_with_bound(loc* poly, int count, loc pos, bound b)
{
int i, j = count - 1;
bool oddNodes = false;
int x0, y0;
int x1, y1;
x0 = pos.x, y0 = pos.y;
x1 = b.left - 1;
y1 = y0;
for (i = 0; i < count; i++)
{
if ((poly[i].y < y0 && poly[j].y >= y0 || poly[j].y < y0 && poly[i].y >= y0)
&& (poly[i].x <= x0 || poly[j].x <= x0))
{
if (areIntersecting(x0, y0, x1, y1, poly[i].x, poly[i].y, poly[j].x, poly[j].y) == YES)
{
oddNodes = !oddNodes;
}
}
j = i;
}
return oddNodes;
}
注意,共线的情况下是要去除的。如果扫描直线穿过多边形的顶点,相当于相交两条直线,不影响判断结果。
最终效果: