点在多边形内_如何判定点是否在给定的多边形中

朋友昨天问我一问题:“如何判定某点是否在多个点组成的多边形之内“。我想了一晚上也没想出怎么解决这个问题,甚至做梦都迷迷糊糊的梦到了这个问题,但是没找到怎么解决。

今早起来后,被这个有趣的问题继续困扰着。想解决问题的冲动,却苦于没有足够能力解决,驱使我到网上查找解决途径。

方法1:R

没有什么问题是R解决不了的;如果有,大概率是搜索的关键词用的不对。R中有个sp package,其中有个point.in.polygon函数,可以判定点是否在给定的多边形内。用法介绍如下图:

abbbe3e81bc2e863b5921bcac59c9a21.png

用法其实很简单,把多边形的点对应的横坐标列入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))

结果如下:

1a46c3904727691b30ed1091e59f0c9b.png

(1, 1)点输出的结果是3,意思是此点在四边形的顶点上。

(2, 3)点输出的结果是0,意思是此点在四边形的外部。

(0.5, 0.5)点输出的结果是1, 意思是此点在四边形的内部。

R函数point.in.polygon用的算法是什么呢?

请参考github上的代码

edzer/sp​github.com
d681924036950065721370a8109bc4cd.png

有兴趣的同学可以检查下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 polygon​www.eecs.umich.edu
063ce1ee292e0cb9875045ccdb4302bf.png

给出了几种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.pdf​ir.nctu.edu.tw
  • Grid method

bb8c921f91a48c10754c6f8b1cf4724f.png
  • Ray intersection method

46f4d213a6385ca81f240dd9a94dc49c.png
  • Sum of angles method

c8d6537c9afc28ceb250db0f14794d97.png
  • Swath method

c931745989ce25529edebe351af3b007.png
  • Sign of offset method

1e1b9cb94d7de18926c9f9a25637da08.png
  • Sum of area method

03353e88b9f71cabe6c6631618fc0c9c.png
  • Orientation method

8291f1914918360278bd1242cffc4097.png
  • Wedge method

403dbdd23b84b12efca5c7cf77f6e1bd.png

更多方法细节请参考文中所参考的几篇文章,我写的这篇文章毫无创意,完全是因为对这个问题的困惑而寻找解决方法最后从网上所搜查找的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值