多边形电子围栏算法
在日常生活工作中,我们经常接触到电子围栏,大部分的电子围栏基本上都是圆形的,想要知道某一个点是否在圆形区域内,算法很简单,只需要知道这个圆形区域的圆心坐标和被测点的坐标的距离是否小于半径即可。两点的距离小于半径,说明被测点在圆形区域内,反之则在圆形区域外。那如果围栏的区域形状不是圆形,而是一个不规则的多边形呢,那我们怎么知道被测点是否在多边形区域内。其实很简单,整体思想如下:
从目标被测点引发一条竖直向上的射线,看这条射线和多边形所有线段的交点数目。如果有奇数个交点,则说明目标点在多边形内部,如果有偶数个交点,则说明目标点在多边形外部。此思路在特殊处理后适用于凸多边形,凹多边形,不规则多边形。但有几个特殊的情况需要处理。
1 当射线与线段的左边顶点相交时,我们认为射线与线段相交。当射线与线段的右边顶点相交时,我们认为射线与线段不相交。如下图所示:
2 当有竖直向上的线段时,我们认为该线段不与射线相交(包括射线和线段重叠的情况)。如:
示列代码如下:
#include <stdio.h>
#include <math.h>
struct Point_t{
double x_value;
double y_value;
};
//给定坐标围成多边形
struct Point_t p_tab[4]={
{10.0, 20.0}, //第0个点
{20.0, 30.0},
{30.0, 20.0},
{20.0, 10.0},
};
//被测点的坐标
struct Point_t testaaa = {
.x_value = 21.0,
.y_value = 19.0,
};
int equal(double a, double b)
{
if((fabs(a-b)) <= (1E-6)){
return 1;
}
return 0;
}
int Polygon_fence_check(struct Point_t Test, struct Point_t *refer, int point_num)
{
int i;
int next_i;
int crossings_count = 0;
double slope;
unsigned char cond;
if(refer = NULL){
return -1;
}
for(i = 0; i < point_num; i++){
if((i+1)>= point_num){
next_i = 0;
}else{
next_i = i+1;
}
//线段的横坐标一样,表示线段竖直。这种情况,我们认为被测点引发的竖直射线不会和此类线段相、交。包括射线和线段重叠。
if(equal(refer[i].x_value, refer[next_i].x_value) == 1){
printf("point %d and point %d x_value is same\r\n", i, next_i);
continue;
}
cond = 0;
//判断被测点的横坐标是否在某线段两顶点的横坐标区间内。注意:当线段左边顶点的横坐标与被测点的横坐标一样时,我们以为
//被测点的横坐标在线段两顶点的横坐标区间内;当线段右边顶点的横坐标与被测点的横坐标一样时,我们以为被测点的横
//坐标在线段两顶点的横坐标区间外。
if(((refer[i].x_value <= Test.x_value)&&(Test.x_value < refer[next_i].x_value))
||((refer[next_i].x_value <= Test.x_value)&&(Test.x_value < refer[i].x_value))){
cond = 0x01;
}
if(cond == 0x01){
//当被测点的横坐标在两顶点的横坐标区间内时,计算线段上对应被测点横坐标的纵坐标。当这个纵坐标大于被测点的纵坐标时,
//我们以为射线与线段相交。
slope = (refer[next_i].y_value - refer[i].y_value)/(refer[next_i].x_value - refer[i].x_value);
if(Test.y_value < (slope*(Test.x_value - refer[i].x_value)+refer[i].y_value)){
printf("crossing line num = %d\r\n", i);
crossings_count++;
}
}
}
printf("crossings count = %d\r\n",crossings_count);
return ((crossings_count%2) != 0);
}
int main(void)
{
int flag;
flag = Polygon_fence_check(testaaa, p_tab, 4);
printf("flag = %d\r\n", flag);
return 0;
}
原文地址:https://blog.csdn.net/langaopeng/article/details/143624850
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!