如何判断一个点在多边形内

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何判断一个点在多边形内相关的知识,希望对你有一定的参考价值。

参考技术A 对于凸多边形而言(以三角形ABC为例),假设存在一个点D,若这个点在三角形的内部,则以该点为起点,和原多边形的任意两个连续的且尊照多边形组成方向
的点(如DAB、DBC、DCA)组成的三角形讲都是一个方向,如DAB和DBC都是顺时针方向。若这个点在三角形的外部,则会出现DAB、DBC、DCA三个三角形方向不一致的情形,即其中有一个不同于另外两个(如一个顺,两个逆)。到这里我们就知道了如何判断一个点在一个三角形内部的算法,总结一下就是通过判断该点同三角形连续两点组成三角形的顺逆性(归于面积的正负)来得到结果的。
实际上,对于其他的凸多边性也可以用一样的方法,只是这个时候判断的三角形的数目增加了,不管怎么样,只要点在多边形内部他们的顺逆都是一样的。对于凹多边形而言,情况就要相对复杂一些了。此时,判断一个点是否在其内部的计算量会增加比较多。具体算法如下:此时三角形一个个的判断可能会失效,我们应当两个同时判断。即判断该点是否同时在多边形的连续两个三角形之中,相当于是求两个三角形的交集,直到完成多边形封闭。

如何判断点在一个区域内?用户绘制区域(射线法)判断点在多边形区域,报警区域

参考文章:判断一个点是否在指定区域内

文章目录

VS测试代码:test.c(测试传入坐标顺时针、逆时针,发现没啥区别!)

#pragma warning(disable : 4996)
#include<stdio.h>
#include<stdlib.h>

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)

typedef struct

    double x, y;
Point;


int InsidePolygon(Point* polygon, int N, Point p)

    int counter = 0;
    int i;
    double xinters;
    Point p1, p2;
    p1 = polygon[0];
    for (i = 1; i <= N; i++)
    
        p2 = polygon[i % N];
        if (p.y > MIN(p1.y, p2.y))
        
            //低
            if (p.y <= MAX(p1.y, p2.y))
            
                //高
                if (p.x <= MAX(p1.x, p2.x))
                
                    //右
                    if (p1.y != p2.y)
                    
                        //简单忽略平行X轴这种情况
                        xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                        //交叉点坐标 参考./media/point-and-polygon/xinters.jpg
                        if (p1.x == p2.x || p.x <= xinters)
                            counter++;
                    
                
            
        
        p1 = p2;
    
    if (counter % 2 == 0)
        return 0;
    else
        return 1;


int main()

    Point points[4] =  0, 1, 3, 0, 3, 4, 0, 3 ;	//逆时针闭合图形
    Point points[4] =  0, 1, 0, 3, 3, 4, 3, 0 ;	//顺时针闭合图形	//测试发现,顺时针和逆时针的结果是相同的
    //Point p0 =  0, 0 ;    //0   //外
    //Point p0 =  0, 1 ;    //1   //边界
    //Point p0 =  1, 0 ;    //0   //外
    //Point p0 =  2, 1 ;    //1   //内
    //Point p0 =  2, 2 ;    //1     //内
    //Point p0 =  2, 3 ;    //1   //内
    //Point p0 =  2, 4 ;    //0   //外
    //Point p0 =  4, 0 ;        //0     //外
    //Point p0 =  -2, -2 ;    //0   //外  
    //Point p0 =  -2, 2 ;       //0     外
    //Point p0 =  2, -2 ;       //0     //外
    Point p0 =  1, 1 ;    //1 //内
    printf("is point in polygon: %d\\n", InsidePolygon(points, sizeof(points) / sizeof(Point), p0)); //在区域外返回0,区域内返回1,边界上没有测试

    return 0;

测试从外部横向穿越多边形顶点、从内部穿越多边形顶点、穿越水平边的情况

#pragma warning(disable : 4996)
#include<stdio.h>
#include<stdlib.h>

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)

typedef struct

    double x, y;
Point;


int InsidePolygon(Point* polygon, int N, Point p)

    int counter = 0;
    int i;
    double xinters;
    Point p1, p2;
    p1 = polygon[0];
    for (i = 1; i <= N; i++)
    
        p2 = polygon[i % N];
        if (p.y > MIN(p1.y, p2.y))
        
            //低
            if (p.y <= MAX(p1.y, p2.y))
            
                //高
                if (p.x <= MAX(p1.x, p2.x))
                
                    //右
                    if (p1.y != p2.y)
                    
                        //简单忽略平行X轴这种情况
                        xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                        //交叉点坐标 参考./media/point-and-polygon/xinters.jpg
                        if (p1.x == p2.x || p.x <= xinters)
                            counter++;
                    
                
            
        
        p1 = p2;
    
    if (counter % 2 == 0)
        return 0;
    else
        return 1;


int main()



    Point points[6] =  0, 1, 1, 2, 0, 3, 3, 3, 5, 4, 3, 0 ;
    

    //0外1内
    
    //Point p0 =  0, 0 ;  //从外部横向穿越顶点   //0


    //Point p0 =  0, 2 ;    //从内部横向穿越顶点 //0
    //Point p0 =  2, 2 ;    //从内部横向穿越顶点 //1
    
    //Point p0 =  -1, 3 ;  //横向跨越水平线(在多边形外)    //0
    Point p0 =  4, 3 ;  //横向跨越水平线(在多边形内)    //1
    
    printf("is point in polygon: %d\\n", InsidePolygon(points, sizeof(points) / sizeof(Point), p0)); //在区域外返回0,区域内返回1,边界上没有测试

    return 0;

测试发现没啥问题,基本正确

VS测试代码:test.c(测试百分比坐标模式)

#pragma warning(disable : 4996)
#include<stdio.h>
#include<stdlib.h>

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)

typedef struct

    double x, y;
Point;


int InsidePolygon(Point* polygon, int N, Point p)

    int counter = 0;
    int i;
    double xinters;
    Point p1, p2;
    p1 = polygon[0];
    for (i = 1; i <= N; i++)
    
        p2 = polygon[i % N];
        if (p.y > MIN(p1.y, p2.y))
        
            //低
            if (p.y <= MAX(p1.y, p2.y))
            
                //高
                if (p.x <= MAX(p1.x, p2.x))
                
                    //右
                    if (p1.y != p2.y)
                    
                        //简单忽略平行X轴这种情况
                        xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                        //交叉点坐标 参考./media/point-and-polygon/xinters.jpg
                        if (p1.x == p2.x || p.x <= xinters)
                            counter++;
                    
                
            
        
        p1 = p2;
    
    if (counter % 2 == 0)
        return 0;
    else
        return 1;


int main()

    //Point points[4] =  0, 1, 0, 3, 3, 4, 3, 0;  
    Point points[4] =  0, 0.25, 0, 0.75, 1, 1, 1, 0 ; //假设总区域是(0, 0)-> (3, 4)
    

    //0外1内
    
    //Point p0 =  0, 0 ;
    //Point p0 =  0, 0 ;  //0


    //Point p0 =  1, 0 ;
    //Point p0 =  0.33, 0 ; //0
    
    //Point p0 =  2, 0 ;
    //Point p0 =  0.66, 0 ; //0
    
    //Point p0 =  1, 1 ;
    //Point p0 =  0.33, 0.25 ;  //1

    //Point p0 =  1, 2 ;
    //Point p0 =  0.33, 0.5 ;   //1
    // 
    //Point p0 =  2, 2 ;
    //Point p0 =  0.66, 0.5 ;   //1

    //Point p0 =  1, 3 ;
    //Point p0 =  0.33, 0.75 ;    //1

    //Point p0 =  2, 3 ;
    //Point p0 =  0.66, 0.75 ;  //1
    
    //Point p0 =  1, 4 ;
    //Point p0 =  0.33, 1 ; //0

    //Point p0 =  2, 4 ;
    //Point p0 =  0.33, 1 ; //0
    // 
    //Point p0 =  3, 5 ;
    //Point p0 =  1, 1.25 ; //0

    //Point p0 = 4, 0;
    Point p0 = 1.33, 0;  //0


    printf("is point in polygon: %d\\n", InsidePolygon(points, sizeof(points) / sizeof(Point), p0)); //在区域外返回0,区域内返回1,边界上没有测试

    return 0;

百分比坐标测试也没有问题

代码原理

主要是射线法

参考文章:【计算几何】判断一个点是否在多边形内部

以上是关于如何判断一个点在多边形内的主要内容,如果未能解决你的问题,请参考以下文章

如何判断点在一个区域内?用户绘制区域(射线法)判断点在多边形区域,报警区域

点在多边形内判断

点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部

POJ 1584 A Round Peg in a Ground Hole 判断凸多边形 点到线段距离 点在多边形内

[poj] 2318 TOYS || 判断点在多边形内

delphi 判断点在多边形内