朋友昨天问我一问题:“如何判定某点是否在多个点组成的多边形之内“。我想了一晚上也没想出怎么解决这个问题,甚至做梦都迷迷糊糊的梦到了这个问题,但是没找到怎么解决。
今早起来后,被这个有趣的问题继续困扰着。想解决问题的冲动,却苦于没有足够能力解决,驱使我到网上查找解决途径。
方法1:R
没有什么问题是R解决不了的;如果有,大概率是搜索的关键词用的不对。R中有个sp package,其中有个point.in.polygon函数,可以判定点是否在给定的多边形内。用法介绍如下图:
用法其实很简单,把多边形的点对应的横坐标列入pol.x, 对应的纵坐标列入pol.y。把要检查的点对应的横坐标列入point.x, 对应的纵坐标列入point.y。结果的解释如下:
- 0 代表点在多边形外部;
- 1代表点在多边形内部;
- 2代表点在多边形的边上;
- 3代表点在多边形的顶点。
试举一例:
试判断点(1, 1)和点(2, 3)和点(0.5, 0.5)是否在以(0.0), (1.1), (0.1), (1. 0)点组成的四边形内。
R程序如下:
library(sp)
point.in.polygon(c(1, 2, 0.5), c(1, 3, 0.5), c(0, 0, 1, 1),c(0, 1, 0, 1))
结果如下:
(1, 1)点输出的结果是3,意思是此点在四边形的顶点上。
(2, 3)点输出的结果是0,意思是此点在四边形的外部。
(0.5, 0.5)点输出的结果是1, 意思是此点在四边形的内部。
R函数point.in.polygon用的算法是什么呢?
请参考github上的代码
edzer/spgithub.com有兴趣的同学可以检查下R中另外一个函数pit2d算得得结果是否跟point.in.polygon一致
library(ptinpoly)
ver=cbind(c(0, 0, 1, 1),
c(0, 1, 0, 1))
quer=cbind(c(1, 2, 0.5),
c(1, 3, 0.5))
pip2d(ver, quer)
方法2:C语言
Paul Bourke在Determining if a point lies on the interior of a polygon博文
Determining if a point lies on the interior of a polygonwww.eecs.umich.edu给出了几种C语言代码实现判定, 试看一例:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#define INSIDE 0
#define OUTSIDE 1
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) {
xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if (p1.x == p2.x || p.x <= xinters)
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
return(OUTSIDE);
else
return(INSIDE);
}
方法3:通用算法
除了R语言和C语言之外,最重要的是背后的算法是什么样的?懂了算法,编程不是难事。网上有诸多算法判定,Huang chong-wei在文章On the conmplexity of point-in-polygonal gorithms中给出了八个算法的对比结果
https://ir.nctu.edu.tw/bitstream/11536/749/1/A1997WM15100010.pdfir.nctu.edu.tw- Grid method
- Ray intersection method
- Sum of angles method
- Swath method
- Sign of offset method
- Sum of area method
- Orientation method
- Wedge method
更多方法细节请参考文中所参考的几篇文章,我写的这篇文章毫无创意,完全是因为对这个问题的困惑而寻找解决方法最后从网上所搜查找的结果。