算法思路

判断平面内点是否在多边形内有多种算法,其中射线法是其中比较好理解的一种,而且能够支持凹多边形的情况。该算法的思路很简单,就是从目标点出发引一条射线,看这条射线和多边形所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。如下图所示:

算法步骤如下:

  1. 已知点point(x,y)和多边形Polygon的点有序集合(x1,y1;x2,y2;….xn,yn;);
  2. 以point为起点,以无穷远为终点作平行于X轴的射线line(x,y; -∞,y);循环取得多边形的每一条边side(xi,yi;xi+1,yi+1):
    1). 判断point(x,y)是否在side上,如果是,则返回true。
    2). 判断line与side是否有交点,如果有则count++。
  3. 判断交点的总数count,如果为奇数则返回true,偶数则返回false。

2. 具体实现

在具体的实现过程中,其实还有一个极端情况需要注意:当射线line经过的是多边形的顶点时,判断就会出现异常情况。针对这个问题,可以规定线段的两个端点,相对于另一个端点在上面的顶点称为上端点,下面是下端点。如果射线经过上端点,count加1,如果经过下端点,则count不必加1。具体实现如下:

#include<iostream>
#include <cmath>
#include <vector>
#include <algorithm>#define EPSILON 0.000001using namespace std;//二维double矢量
struct  Vec2d
{double x, y;Vec2d(){x = 0.0;y = 0.0;}Vec2d(double dx, double dy){x = dx;y = dy;}void Set(double dx, double dy){x = dx;y = dy;}
};//判断点在线段上
bool IsPointOnLine(double px0, double py0, double px1, double py1, double px2, double py2)
{bool flag = false;double d1 = (px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0);if ((abs(d1) < EPSILON) && ((px0 - px1) * (px0 - px2) <= 0) && ((py0 - py1) * (py0 - py2) <= 0)){flag = true;}return flag;
}//判断两线段相交
bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
{bool flag = false;double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);if (d != 0){double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d;double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d;if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1)){flag = true;}}return flag;
}//判断点在多边形内
bool Point_In_Polygon_2D(double x, double y, const vector<Vec2d> &POL)
{   bool isInside = false;int count = 0;//double minX = DBL_MAX;for (int i = 0; i < POL.size(); i++){minX = std::min(minX, POL[i].x);}//double px = x;double py = y;double linePoint1x = x;double linePoint1y = y;double linePoint2x = minX -10;         //取最小的X值还小的值作为射线的终点double linePoint2y = y;//遍历每一条边for (int i = 0; i < POL.size() - 1; i++){  double cx1 = POL[i].x;double cy1 = POL[i].y;double cx2 = POL[i + 1].x;double cy2 = POL[i + 1].y;if (IsPointOnLine(px, py, cx1, cy1, cx2, cy2)){return true;}if (fabs(cy2 - cy1) < EPSILON)   //平行则不相交{continue;}if (IsPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x, linePoint2y)){if (cy1 > cy2)         //只保证上端点+1{count++;}}else if (IsPointOnLine(cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y)){if (cy2 > cy1)         //只保证上端点+1{count++;}}else if (IsIntersect(cx1, cy1, cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y))   //已经排除平行的情况{count++;}}if (count % 2 == 1){isInside = true;}return isInside;
}int main()
{   //定义一个多边形(六边形)vector<Vec2d> POL;    POL.push_back(Vec2d(268.28, 784.75));POL.push_back(Vec2d(153.98, 600.60));POL.push_back(Vec2d(274.63, 336.02));POL.push_back(Vec2d(623.88, 401.64));POL.push_back(Vec2d(676.80, 634.47));POL.push_back(Vec2d(530.75, 822.85));POL.push_back(Vec2d(268.28, 784.75));             //将起始点放入尾部,方便遍历每一条边//if (Point_In_Polygon_2D(407.98, 579.43, POL)){cout << "点(407.98, 579.43)在多边形内" << endl;}else{cout << "点(407.98, 579.43)在多边形外" << endl;}//if (Point_In_Polygon_2D(678.92, 482.07, POL)){cout << "点(678.92, 482.07)在多边形内" << endl;}else{cout << "点(678.92, 482.07)在多边形外" << endl;}return 0;
}

运行结果如下:

改进空间

  1. 很多情况下在使用该算法之前,需要一个快速检测的功能:当点不在多边形的外包矩形的时候,那么点一定不在多边形内。
  2. 判断点在线上函数IsPointOnLine()和判断线段相交函数IsIntersect()这里并不是最优算法,可以改成向量计算,效率应该更高。

判断某点在多边形内——方法一相关推荐

  1. 判断点是否处于多边形内的三种方法(转)

    1. 叉乘判别法(只适用于凸多边形)想象一个凸多边形,其每一个边都将整个2D屏幕划分成为左右两边,连接每一边的第一个端点和要测试的点得到一个矢量v,将两个2维矢量扩展成3维的,然后将该边与v叉乘,判断 ...

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

    一.从三角形开始说起---怎么判断一个点在三角形内 三角形是最简单的多边形了.先说说三角形有哪些判断方法. 参考自:判断一个点是否在三角形内部 - 知乎 几种方法判断平面点在三角形内_独L无二的博客- ...

  3. 判断一点是否在多边形内(附Java实现代码)

    引射线法:从目标点出发引一条射线,看这条射线和多边形所有边的交点数射线法 时间复杂度:O(n) 适用范围:任意多边形 个人认为是非常不错的算法(不需考虑精度误差和多边形点给出的顺序),可以作为第一选择 ...

  4. 射线法判断点是否在多边形内-JAVA

    1.定义点 public class Point {private BigDecimal x;private BigDecimal y;public Point() {};@Overridepubli ...

  5. 判断点是否位于多边形内(包含凹多边形)

    如果判断点是否在凸多边形内,则有多种方法,方法简单,计算速度也快,直接使用物理引擎做判断也行 但实际问题中遇到的多边形不一定是凸多边形,它可能是凹边行或者复合多边形判断一个点在多边形内或多边形外,射线 ...

  6. python射线法判断点是否在多边形内

    python3射线法判断点是否在多边形内 射线法 首先我们要先理解什么是射线法.射线法的意思是:在随机点上做一条平行于x轴的射线,方向是x轴正方向,看这条射线与多边形区域的交点个数,如果是偶数,那么这 ...

  7. PHP 判断点是否在多边形内

    如何判断一个点是否在一个多边形内,何时会用到这个场景. 我们就模拟一个真是场景.我们公司是快递公司,在本地区域有6个分点.每个分点有3-5个工人负责附近的快递派遣发送,所以根据每个点的服务区域我们就能 ...

  8. 判断某点在多边形内——方法二

    /* 原理: 将测试点的Y坐标与多边形的每一个点进行比较, ** 会得到测试点所在的行与多边形边的所有交点. ** 如果测试点的两边点的个数都是奇数个, ** 则该测试点在多边形内,否则在多边形外. ...

  9. 判断点是否在多边形内——射线法

    1 //判断射线与也线段是否相交, 相交返回1,不相交返回0,在边上返回-1 2 int IsIntersectant( CPoint ptStart, CPoint ptEnd, CPoint pd ...

最新文章

  1. 计算机专业今后的发展方向
  2. 神经架构搜索在视频理解中研究进展的综述
  3. 敏感词库 php,敏感词过滤的php类库
  4. 当前线程等待某些线程运行结束再执行的几种方案。CountDownLatch机制简单解读以及简单实现
  5. 学习记录-交叉编译环境的设置
  6. Java Web笔记之Struts2.1 +Hibernate3.3 +Spring3.0
  7. [TypeScript] vs code TSLint常见错误解决方案
  8. java定义一个方法,返回一个浮点数保留两位小数,考虑四舍五入的结果
  9. 余承东:Mate40系列5000万像素远好于友商1亿像素
  10. js中点击按钮时变色,松开后恢复原来的颜色
  11. UE4之设置打包程序分辨率
  12. 从不同音效材质了解游戏界面音效
  13. 肝脏~卧则回血,坐立向外供血
  14. QQ合并的聊天记录可以通过什么方式转换成链接,点开链接就能看合并的聊天记录?
  15. 网站实现发送帖子的功能
  16. 联想G480如何关闭数字小键盘
  17. 如何利用工具低成本构建华为云灾备方案?
  18. android 应用商店
  19. 模糊数学学习笔记 6:模糊综合评判
  20. 月结4 - GR/IR重分类(Regroup) [F.19/OBYP]

热门文章

  1. shell--4、Shell 数组
  2. 红米3国际稳定版刷机+完美ROOT
  3. 一念心动,一生绵延——如何修复min pulse width?
  4. 【转】在Ubuntu上下载、编译和安装Android最新源代码
  5. 第十八章——基于策略的管理(1)——评估数据库属性
  6. 使用 IntraWeb (29) - 基本控件之 TIWAutherList、TIWAutherINI、TIWAutherEvent
  7. 整理vim格式回车变成空两格
  8. android 文件大小排序,android 文件列表排序
  9. 使用PyInstaller2将Python脚本转化为可执行文件(下-进阶使用)
  10. python干货_Python干货整理,从入门说起(7.4)