zoukankan      html  css  js  c++  java
  • C实现一个检查点在多边形内部

    2011-5-2

    最近又写了一个检查点在多边形内部的程序,主要还是为了XX公司那边的一个项目做点小事情。好了,下面开始讲解原理。

    射线法检测,其实就是在已知点内,固定好该点的X或者Y坐标,然后对任意X或者Y轴做垂线(固定XY轴做垂线,固定YX轴做垂线)。垂线和线段如果相交的次数是奇数,证明点在多边形内部,如果是偶次,说明点在多边形外部。

     

    但是,要讨论的是凸多边形会有特殊情况。

    C实现一个检查点在多边形内部

    上图,P1的时候做射线,交了3点,但是在多边形外,P2交了2点,但是在多边形内部。

    还有的情况就是

    C实现一个检查点在多边形内部

    和上边的类似,只是在程序处理上,坐标y一个是从高到低,一个低到高

    遇到这两种情况,只能当做相交了一次,在那个拐弯点。

    用程序处理如下:

           if((*this.Point_Is_On_Line)(FixedLinePoints[i], *MovePoint, this.RadialLineEndP))//从这里往下主要是判断凸多边形2种的特殊情况

                  {

                         if(FixedLinePoints[i].y > FixedLinePoints[j].y )

                         {

                                this.CrossCount++;

     

                         }

                  }

                  else if((*this.Point_Is_On_Line)(FixedLinePoints[j], *MovePoint, this.RadialLineEndP))

                  {

                         if(FixedLinePoints[j].y > FixedLinePoints[i].y)

                         {

                                this.CrossCount++;

                         }

                  }

                  else if((*this.Check_Two_Lines_Intersect)(FixedLinePoints + i, FixedLinePoints + j, MovePoint, &this.RadialLineEndP))//判断射线与线段是否相交

                  {

                         this.CrossCount++;

                  }

     

    有优先级别的判断,先是第一种情况,后是第二种情况,最后是普通情况的判断。就可以了。

     

    测试条件:

           struct Vertex_PointXY testtab[4] = {

                         {0,0},{0,8},{2,2},{4,0},

           };

     

           struct Vertex_PointXY a = {-1, 2};

           struct Vertex_PointXY b = {100, 100};

           struct Vertex_PointXY c = {0 , 0};

           struct Vertex_PointXY d = {1,2};

     

    实验结果如下:

    2

    Point is outside the polygon!

    2

    Point is outside the polygon!

    1

    Point is on the polygon!

    0

    Point is in the polygon!

     

     

     

    下面是实现代码:

     

     

    #ifndef CHECK_POINT_IN_POLYGON_H_

    #define CHECK_POINT_IN_POLYGON_H_

     

     

    #include <stdio.h>

    #include <stdlib.h>

    #include <math.h>

    #include <stdint.h>

    #include <string.h>

     

    #ifndef INFINITY

    #define INFINITY  1e10

    #endif

     

    #ifndef ESP

    #define ESP  1e-5

    #endif

     

    #ifndef MAX_N

    #define MAX_N  1000

    #endif

     

    struct Vertex_PointXY

    {

           double x;

           double y;

    };

     

    struct Vertex_List

    {

           uint32_t vertex_num;

           struct Vertex_PointXY *vertex_point;

    };

     

    struct Bounded_Rectangle

    {

           double min_x;

           double min_y;

           double max_x;

           double max_y;

    };

     

     

    struct Check_Two_Points_Same_Side_Of_Beeline_Private

    {

           double CTPSSB_dx;

           double CTPSSB_dy;

           double CTPSSB_dx1;

           double CTPSSB_dy1;

           double CTPSSB_dx2;

           double CTPSSB_dy2;

    };

     

     

     

    struct Check_Two_Lines_Intersect_Private

    {

           int return_value;

           int temp[2];

    };

     

    struct Point_Is_On_Line_Private

    {

           double *temp;

           int return_value;

    };

     

    struct Check_Point_In_Polygon_Private

    {

           struct Bounded_Rectangle BoundedRectangle;

           void (*Get_Vertices_Bound) (struct Vertex_PointXY *Vertex_P, uint32_t Vertex_Num, struct Bounded_Rectangle *BoundedResult);

           int32_t (*Check_Two_Lines_Intersect) (\

                                                                                        struct Vertex_PointXY *line1_start_p,\

                                                                                        struct Vertex_PointXY *line1_end_p,\

                                                                                        struct Vertex_PointXY *line2_start_p,\

                                                                                        struct Vertex_PointXY *line2_end_p\

                                                                                        );

           int (*Point_Is_On_Line) (struct Vertex_PointXY point, struct Vertex_PointXY fixed_line_p1, struct Vertex_PointXY fixed_line_p2);

           struct Vertex_PointXY RadialLineEndP;

           int CrossCount;

           int return_value;

    };

     

    //该函数完成Check_Point_In_Polygon的私有成员变量和函数的初始化工作

    #define REGISTER_CHECK_POINT_IN_POLYGON_PRIVATE_VALUE(NAME) \

                                                                                 struct Check_Point_In_Polygon_Private NAME;\

                                                                                 NAME.Get_Vertices_Bound = Get_Vertices_Bound;\

                                                                                 NAME.Check_Two_Lines_Intersect = Check_Two_Lines_Intersect;\

                                                                                 NAME.Point_Is_On_Line = Point_Is_On_Line; \

     

     

     

     

    struct Check_Point_In_Polygon_Public

    {

           struct Vertex_PointXY *FixedLinePoints;

           uint32_t LinePointsNum;

           struct Vertex_PointXY *MovePoint;

           int (*Check_Point_In_Polygon)( \

                                                                          struct Vertex_PointXY *FixedLinePoints,\

                                                                    uint32_t LinePointsNum,\

                                                                    struct Vertex_PointXY *MovePoint\

                                                                   );

     

    };

     

     

     

    //提供给外部函数的接口

    #define CHECK_POINT_IN_POLYGON_INTAFACE(FIXEDPOINTS, NUM, MOVEPOINT)    Check_Point_In_Polygon(FIXEDPOINTS, NUM, &MOVEPOINT)

     

     

     

    extern int Check_Point_In_Polygon( \

                                                                   struct Vertex_PointXY *FixedLinePoints,\

                                                             uint32_t LinePointsNum,\

                                                             struct Vertex_PointXY *MovePoint\

                                                            );

     

     

     

     

     

     

     

    #endif

     

     

     

     

    #include "check_point_in_polygon.h"

     

     

     

    //私有函数声明区

    static int32_t Check_Two_Points_Same_Side_Of_Beeline(  \

                                                                                        struct Vertex_PointXY *fixed_line_PS,\

                                                                                        struct Vertex_PointXY *fixed_line_PE,\

                                                                                        struct Vertex_PointXY *moved_1_PM,\

                                                                                        struct Vertex_PointXY *moved_2_PM\

                                                                                        );

    static int32_t Check_Two_Lines_Intersect(\

                                                                                 struct Vertex_PointXY *line1_start_p,\

                                                                                 struct Vertex_PointXY *line1_end_p,\

                                                                                 struct Vertex_PointXY *line2_start_p,\

                                                                                 struct Vertex_PointXY *line2_end_p\

                                                                                 );

     

    static void Get_Vertices_Bound(struct Vertex_PointXY *Vertex_P, uint32_t Vertex_Num, struct Bounded_Rectangle *BoundedResult);

     

    static int Point_Is_On_Line(struct Vertex_PointXY point, struct Vertex_PointXY fixed_line_p1, struct Vertex_PointXY fixed_line_p2);

     

    //公共函数声明区

     

     

     

    //私有函数定义区

     

    static int32_t Check_Two_Points_Same_Side_Of_Beeline(  \

                                                                                        struct Vertex_PointXY *fixed_line_PS,\

                                                                                        struct Vertex_PointXY *fixed_line_PE,\

                                                                                        struct Vertex_PointXY *moved_1_PM,\

                                                                                        struct Vertex_PointXY *moved_2_PM\

                                                                                        )

    {

           int return_value = 0;

           struct Check_Two_Points_Same_Side_Of_Beeline_Private *this = (struct Check_Two_Points_Same_Side_Of_Beeline_Private *)malloc(sizeof (struct Check_Two_Points_Same_Side_Of_Beeline_Private));

           this->CTPSSB_dx = fixed_line_PE->x - fixed_line_PS->x;

           this->CTPSSB_dy = fixed_line_PE->y - fixed_line_PS->y;

           this->CTPSSB_dx1 = moved_1_PM->x - fixed_line_PS->x;

           this->CTPSSB_dy1 = moved_1_PM->y - fixed_line_PS->y;

           this->CTPSSB_dx2 = moved_2_PM->x - fixed_line_PE->x;

           this->CTPSSB_dy2 = moved_2_PM->y - fixed_line_PE->y;

           return_value = ((this->CTPSSB_dx * this->CTPSSB_dy1 - this->CTPSSB_dy * this->CTPSSB_dx1) * (this->CTPSSB_dx * this->CTPSSB_dy2 - this->CTPSSB_dy * this->CTPSSB_dx2) > 0 ? 1 : 0);

           free(this);

           return return_value;

    }

     

    static int32_t Check_Two_Lines_Intersect(\

                                                                                 struct Vertex_PointXY *line1_start_p,\

                                                                                 struct Vertex_PointXY *line1_end_p,\

                                                                                 struct Vertex_PointXY *line2_start_p,\

                                                                                 struct Vertex_PointXY *line2_end_p\

                                                                                 )

    {

           struct Check_Two_Lines_Intersect_Private CTLIP_V;

           memset(&CTLIP_V, 0, sizeof(CTLIP_V));

           CTLIP_V.temp[0] = Check_Two_Points_Same_Side_Of_Beeline(line1_start_p, line1_end_p, line2_start_p, line2_end_p);

           CTLIP_V.temp[1] = Check_Two_Points_Same_Side_Of_Beeline(line2_start_p, line2_end_p, line1_start_p, line1_end_p);

           CTLIP_V.return_value = ((CTLIP_V.temp[0] == 0) && (CTLIP_V.temp[1] == 0)) ? 1 : 0;

           return CTLIP_V.return_value ;

    }

     

    static void Get_Vertices_Bound(struct Vertex_PointXY *Vertex_P, uint32_t Vertex_Num, struct Bounded_Rectangle *BoundedResult)

    {

           int i = 0;

           if(Vertex_Num > 0)

           {

                  BoundedResult->min_x = Vertex_P[0].x;

                  BoundedResult->max_x = Vertex_P[0].x;

                  BoundedResult->min_y = Vertex_P[0].y;

                  BoundedResult->max_y = Vertex_P[0].y;

           }

           else

           {

                  BoundedResult->min_x = 0;

                  BoundedResult->max_x = 0;

                  BoundedResult->min_y = 0;

                  BoundedResult->max_y = 0;

           }

           for(i = 1; i < Vertex_Num; i++)

           {

                  if(Vertex_P[i].x < BoundedResult->min_x)

                  {

                         BoundedResult->min_x = Vertex_P[i].x;

                  }

                  if(Vertex_P[i].y < BoundedResult->min_y)

                  {

                         BoundedResult->min_y = Vertex_P[i].y;

                  }

                  if(Vertex_P[i].x > BoundedResult->max_x)

                  {

                         BoundedResult->max_x = Vertex_P[i].x;

                  }

                  if(Vertex_P[i].y > BoundedResult->max_y)

                  {

                         BoundedResult->max_y = Vertex_P[i].y;

                  }

           }

     

    }

     

    //计算差乘 P0P1 X P0P2

    static double Multiplication_Cross(struct Vertex_PointXY P1, struct Vertex_PointXY P2, struct Vertex_PointXY P0)

    {

           return ((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y));

    }

     

    static int Point_Is_On_Line(struct Vertex_PointXY point, struct Vertex_PointXY fixed_line_p1, struct Vertex_PointXY fixed_line_p2)

    {

           struct Point_Is_On_Line_Private this;

           this.temp = (double *) malloc(3 * sizeof(double));

           //if(this.temp == NULL)

           //     return 1;

           this.temp[0] = Multiplication_Cross(fixed_line_p1, fixed_line_p2, point);

           this.temp[1] = (point.x - fixed_line_p1.x) * (point.x - fixed_line_p2.x);

           this.temp[2] = (point.y - fixed_line_p1.y) * (point.y - fixed_line_p2.y);

           this.return_value = (fabs(this.temp[0]) < ESP) && (this.temp[1] <= 0) && (this.temp[2] <= 0);

           free(this.temp);

           return this.return_value;

    }

     

     

    //公共函数声明区

     

     

    int Check_Point_In_Polygon(\

                                                     struct Vertex_PointXY *FixedLinePoints,\

                                                     uint32_t LinePointsNum,\

                                                     struct Vertex_PointXY *MovePoint\

                                                     )

    {

           //struct Check_Point_In_Polygon_Private this;

           int i = 0;

           int j = 0;

           //this.Get_Vertices_Bound = Get_Vertices_Bound;

           //this.Check_Two_Lines_Intersect = Check_Two_Lines_Intersect;

           //this.Point_Is_On_Line = Point_Is_On_Line;

           REGISTER_CHECK_POINT_IN_POLYGON_PRIVATE_VALUE(this);

     

     

           if(LinePointsNum < 3)

           {

                  return 0;

           }

     

           (*this.Get_Vertices_Bound)(FixedLinePoints, LinePointsNum, &this.BoundedRectangle);

           if(MovePoint->x < this.BoundedRectangle.min_x || MovePoint->x > this.BoundedRectangle.max_x || MovePoint->y < this.BoundedRectangle.min_y || MovePoint->y > this.BoundedRectangle.max_y)

           {

                  return 2;

           }

           this.RadialLineEndP.x = this.BoundedRectangle.max_x;

           this.RadialLineEndP.y = MovePoint->y;

     

           for(i = 0; i < LinePointsNum; i++)

           {

                  j = (i + 1) % LinePointsNum;

                  if((*this.Point_Is_On_Line)(*MovePoint, FixedLinePoints[i], FixedLinePoints[j]))

                  {

                         return 1;

                  }

     

                  if(fabs(FixedLinePoints[i].y - FixedLinePoints[j].y) < ESP)//如果固定点平行射线就不管了,肯定不会相交

                  {

                         continue;

                  }

     

                  if((*this.Point_Is_On_Line)(FixedLinePoints[i], *MovePoint, this.RadialLineEndP))//从这里往下主要是判断凸多边形2种的特殊情况

                  {

                         if(FixedLinePoints[i].y > FixedLinePoints[j].y )

                         {

                                this.CrossCount++;

     

                         }

                  }

                  else if((*this.Point_Is_On_Line)(FixedLinePoints[j], *MovePoint, this.RadialLineEndP))

                  {

                         if(FixedLinePoints[j].y > FixedLinePoints[i].y)

                         {

                                this.CrossCount++;

                         }

                  }

                  else if((*this.Check_Two_Lines_Intersect)(FixedLinePoints + i, FixedLinePoints + j, MovePoint, &this.RadialLineEndP))//判断射线与线段是否相交

                  {

                         this.CrossCount++;

                  }

           }

     

           if(this.CrossCount % 2 == 1) //是奇数,说明点在多边形内,返回0

           {

                  return 0;

           }

           else

           {

                  return 2;  //偶数返回2,说明点在多边形外

           }

     

    }

     

     

     

     

     

     

     

    #include "check_point_in_polygon.h"

     

     

     

    void display(num)

    {

           switch(num)

           {

                  case 0 : printf("Point is in the polygon!\n");break;

                  case 1 : printf("Point is on the polygon!\n");break;

                  case 2 : printf("Point is outside the polygon!\n");break;

     

           }

    }

     

    int main(void)

    {

           struct Vertex_PointXY testtab[4] = {

                         {0,0},{0,8},{2,2},{4,0},

           };

     

           struct Vertex_PointXY a = {-1, 2};

           struct Vertex_PointXY b = {100, 100};

           struct Vertex_PointXY c = {0 , 0};

           struct Vertex_PointXY d = {1,2};

     

     

     

           printf("%d \n",CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, a));

           display(CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, a));

           printf("%d \n",CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, b));

           display(CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, b));

           printf("%d \n",CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, c));

           display(CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, c));

           printf("%d \n",CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, d));

           display(CHECK_POINT_IN_POLYGON_INTAFACE(testtab, 4, d));

     

           return 0;

    }

  • 相关阅读:
    封装的图片预加载,数据加载到浏览器底部加载数据
    自己封装的弹出层插件
    在规定的时间内出现动画.html
    WEB前端资源集
    前端优化几项
    移动H5前端性能优化指南
    微信小程序IDE(微信web开发者工具)安装、破解手册--转载
    微信小程序开发—快速掌握组件及API的方法---转载
    STM32数据类型定义
    HDOJ 4802 GPA
  • 原文地址:https://www.cnblogs.com/nickchan/p/3104535.html
Copyright © 2011-2022 走看看