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

算法步骤如下:
- 已知点point(x,y)和多边形Polygon的点有序集合(x1,y1;x2,y2;….xn,yn;);
- 以point为起点,以无穷远为终点作平行于X轴的射线line(x,y; -∞,y);循环取得多边形的每一条边side(xi,yi;xi+1,yi+1):
1). 判断point(x,y)是否在side上,如果是,则返回true。
2). 判断line与side是否有交点,如果有则count++。 - 判断交点的总数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. 改进空间
- 很多情况下在使用该算法之前,需要一个快速检测的功能:当点不在多边形的外包矩形的时候,那么点一定不在多边形内。
- 判断点在线上函数IsPointOnLine()和判断线段相交函数IsIntersect()这里并不是最优算法,可以改成向量计算,效率应该更高。
判断点在多边形内算法的C++实现的更多相关文章
- hdu 1756:Cupid's Arrow(计算几何,判断点在多边形内)
Cupid's Arrow Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- zoj 1081 判断点在多边形内
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=81Points Within Time Limit: 2 Second ...
- php之判断点在多边形内的api
1.判断点在多边形内的数学思想:以那个点为顶点,作任意单向射线,如果它与多边形交点个数为奇数个,那么那个点在多边形内,相关公式: <?php class AreaApi{ //$area是一个多 ...
- POJ 2318 TOYS | 二分+判断点在多边形内
题意: 给一个矩形的区域(左上角为(x1,y1) 右下角为(x2,y2)),给出n对(u,v)表示(u,y1) 和 (v,y2)构成线段将矩形切割 这样构成了n+1个多边形,再给出m个点,问每个多边形 ...
- ZOJ 1081 Points Within | 判断点在多边形内
题目: 给个n个点的多边形,n个点按顺序给出,给个点m,判断m在不在多边形内部 题解: 网上有两种方法,这里写一种:射线法 大体的思想是:以这个点为端点,做一条平行与x轴的射线(代码中射线指向x轴正方 ...
- R树判断点在多边形内-Java版本
1.什么是RTree 待补充 2.RTree java依赖 rtree的java开源版本在GitHub上:https://github.com/davidmoten/rtree 上面有详细的使用说明 ...
- 点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部
判断一点是否在不规则图像的内部算法,如下图是由一个个点组成的不规则图像,判断某一点是否在不规则矩形内部,先上效果图 算法实现如下,算法简单,亲试有效 public class PositionAlgo ...
- hdu 1756 判断点在多边形内 *
模板题 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> ...
- A Round Peg in a Ground Hole - POJ 1584 (判断凸多边形&判断点在多边形内&判断圆在多边形内)
题目大意:首先给一个圆的半径和圆心,然后给一个多边形的所有点(多边形按照顺时针或者逆时针给的),求,这个多边形是否是凸多边形,如果是凸多边形在判断这个圆是否在这个凸多边形内. 分析:判断凸多边形可 ...
随机推荐
- ES 13 - Elasticsearch的元字段 (_index、_type、_source、_routing等)
目录 1 标识元字段 1.1 _index - 文档所属的索引 1.2 _uid - 包含_type和_id的复合字段 1.3 _type - 文档的类型 1.4 _id - 文档的id 2 文档来源 ...
- 优雅地 `async/await`
async/await 虽然取代了回调,使用类似同步的代码组织方式让代码更加简洁美观,但错误处理时需要加 try/catch. 比如下面这样,一个简单的 Node.js 中使用 async/await ...
- Oracle数据库升级注意事项
1 备份配置参数 数据库升级前的配置参数要备份,如PGA大小 这样数据库升级后还可以升级前的配置,而不至于使用安装升级时的默认配置 2 检查版本兼容 确认数据库升级后是否对生产环境上的代码有影响,如果 ...
- 5个常常被大家忽略的Python小技巧
下面我挑选出的这几个技巧常常会被人们忽略,但它们在日常编程中能真正的给我们带来不少帮助. 1. 字典推导(Dictionary comprehensions)和集合推导(Set comprehensi ...
- dubbo 序列化机制之 hessian2序列化实现原理分析
对于远程通信,往往都会涉及到数据持久化传输问题.往大了说,就是,从A发出的信息,怎样能被B接收到相同信息内容!小点说就是,编码与解码问题! 而在dubbo或者说是java的远程通信中,编解码则往往伴随 ...
- .NET Core微服务之基于MassTransit实现数据最终一致性(Part 2)
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构与说明 在上一篇中,我们了解了MassTransit这个开源组件的基本用法,这一篇我们结合一个小案例来了解在ASP.NET C ...
- 【反编译系列】四、反编译so文件(IDA_Pro)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 安卓应用程序的开发语言是java,但是由于java层的代码很容易被反编译,而反编译c/c++程序的难度比较大,所以现在很多安卓应用程 ...
- 【Android Studio安装部署系列】三十七、从Android Studio3.2升级到Android Studio3.4【以及创建Android Q模拟器】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 保持Android Studio开发环境的最新版本. 下载Android Studio3.4 使用Android Studio自带的 ...
- Android中EditText显示明文与密文的两种方式
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 记录输入框显示.隐藏密码的简单布局以及实现方式. 效果图 代码分析 方式一 /**方式一:*/ private void sh ...
- debian The type initializer for 'System.Drawing.KnownColors' threw an exception
Change the "System.Drawing" reference of "CoreCompat.System.Drawing"if you thro ...