1. 算法思路

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



算法步骤如下:

  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.000001 using 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;
}

运行结果如下:

3. 改进空间

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

判断点在多边形内算法的C++实现的更多相关文章

  1. hdu 1756:Cupid's Arrow(计算几何,判断点在多边形内)

    Cupid's Arrow Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  2. zoj 1081 判断点在多边形内

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=81Points Within Time Limit: 2 Second ...

  3. php之判断点在多边形内的api

    1.判断点在多边形内的数学思想:以那个点为顶点,作任意单向射线,如果它与多边形交点个数为奇数个,那么那个点在多边形内,相关公式: <?php class AreaApi{ //$area是一个多 ...

  4. POJ 2318 TOYS | 二分+判断点在多边形内

    题意: 给一个矩形的区域(左上角为(x1,y1) 右下角为(x2,y2)),给出n对(u,v)表示(u,y1) 和 (v,y2)构成线段将矩形切割 这样构成了n+1个多边形,再给出m个点,问每个多边形 ...

  5. ZOJ 1081 Points Within | 判断点在多边形内

    题目: 给个n个点的多边形,n个点按顺序给出,给个点m,判断m在不在多边形内部 题解: 网上有两种方法,这里写一种:射线法 大体的思想是:以这个点为端点,做一条平行与x轴的射线(代码中射线指向x轴正方 ...

  6. R树判断点在多边形内-Java版本

    1.什么是RTree 待补充 2.RTree java依赖 rtree的java开源版本在GitHub上:https://github.com/davidmoten/rtree 上面有详细的使用说明 ...

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

    判断一点是否在不规则图像的内部算法,如下图是由一个个点组成的不规则图像,判断某一点是否在不规则矩形内部,先上效果图 算法实现如下,算法简单,亲试有效 public class PositionAlgo ...

  8. hdu 1756 判断点在多边形内 *

    模板题 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> ...

  9. A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&判断点在多边形内&判断圆在多边形内)

    题目大意:首先给一个圆的半径和圆心,然后给一个多边形的所有点(多边形按照顺时针或者逆时针给的),求,这个多边形是否是凸多边形,如果是凸多边形在判断这个圆是否在这个凸多边形内.   分析:判断凸多边形可 ...

随机推荐

  1. Vue.js-08:第八章 - 组件的基础知识

    一.前言 在之前的学习中,我们对于 Vue 的一些基础语法进行了简单的了解,通过之前的代码可以清晰的看出,我们在使用 Vue 的整个过程,最终都是在对 Vue 实例进行的一系列操作. 这里就会引出一个 ...

  2. python中线程和进程(二)

    目录 线程同步 Event Lock RLock Condition Barrier semaphore GIL 线程同步 线程同步,即线程之间协同工作,一个线程访问某些数据时,其他线程不能访问这些数 ...

  3. user 不在 sudoers 文件中。此事将被报告。

    在使用sudo -i或su root命令时,被提示出“user不在 sudoers 文件中.此事将被报告”的错误信息.这是因为当前登录的账号不在sudo权限里面.sudo命令可以让你以root身份执行 ...

  4. Windows上搭建远程访问服务

    Windows上搭建远程访问服务 转自:https://blog.51cto.com/13871378/2153308?source=dra 概述:允许客户机通过拨号连接或虚拟专用网连接到公司局域网, ...

  5. 知名区块链人脸识别公司iFace Chain [爱妃链] 支招,如何防止钱包数字币被盗...

    最近众多钱包发行方跑路频发,让非常多的用户蒙受巨大经济损失,知名区块链人脸识别公司iFace Chain [爱妃链] 前日做客某区块链媒体为网友支招,如何防止钱包数字币被盗. 那么,用户怎么降低Tok ...

  6. redis的hash类型!!!!

    Hash类型 redsi的hash是基本类型之一,键值本身又是一对键值结构,是string类型的field和value的映射表,或者说是集合,适合存储对象. Hash的增操作 127.0.0.1:63 ...

  7. 【Netty】(5)源码 Bootstrap

    [Netty]5 源码 Bootstrap 上一篇讲了AbstractBootstrap,为这篇做了个铺垫. 一.概述 Bootstrap 是 Netty 提供的一个便利的工厂类, 我们可以通过它来完 ...

  8. 使用C#+XPath+HtmlAgilityPack轻松搞一个资源下载器

    HtmlAgilityPack简介 HtmlAgilityPack是一个开源的解析HTML元素的类库,最大的特点是可以通过XPath来解析HMTL,如果您以前用C#操作过XML,那么使用起HtmlAg ...

  9. Linux+.Net Core+Nginx(在Linux上使用Nginx反向代理.Net Core 项目)

    Linux+.Net Core+Nginx 之前的文章中有提到关于使用Nginx在linux来实现反向代理,今天我们继续加点料.在Centos7中部署.NetCore,然后使用Nginx进行反向代理! ...

  10. 总结http get和post的区别

    这个问题几乎面试的时候都会问到,是一个老生常谈的话题,然而随着不断的学习,对于以前的认识有很多误区,所以还是需要不断地总结的,学而时习之,不亦说乎. 什么是http? get.post常见的区别 ge ...