当前位置:网站首页>点在多边形内外的判断
点在多边形内外的判断
2022-06-29 09:18:00 【是Mally呀!】
点在多边形内外的判断
备注:
主要依据《算法竞赛入门经典训练指南》的思路,2020.7.4
射线法和转角法适用于所有多边形
一、射线法:
从这一点出发,引向无穷远点的一条射线,根据交点情况确定点的位置
优点:简单,算法竞赛中常用
缺点:如果多边形是弧形的,不能用下面的那个代码
算法:
- 以要判断的点为起点,任做一条射线,计算该射线与多边形的交点的数
- 若有偶数个交点,则点在多边形外;否则,点在多边形内
- 若与线段所在的端点处重合或相交,则要进行复杂的判断;此时可另取一条射线
如下是《算法竞赛入门经典训练指南》的代码
const double eps=1e-8;
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
else return x<0?-1:1;
}
int isPointInPolygon(Point p,Polygon poly )
{
int wn=0;
int n=v.size();
for(int i=0;i<n;++i){
if(isPointonSegment(p,poly[i],poly[(i+1)%n]))return -1;
int k=dcmp(Cross(poly[i+1]%n-poly[i],p-poly[i]));
int d1=dcmp(poly[i].y-p.y);
int d2=dcmp(poly[(i+1)%n].y-p.y);
if(k>0 && d1<=0 &&d2>0)wn++; //如果边与射线的右端相交
if(k<0 && d1>0 &&d2<=0)wn--; //如果边与射线的左端相交
}
}
代码采用的是射线法,令这条射线为向右,那么它的负方向就是想做,如果交点在右边,交点数就加价,如果交点在左边,交点数减减。再看下面细分析。
计算射线与多边形的交点,那要先排除没有交点的情况,以图表示则为
而(除去点在边上)有交点的情况就是
这也是代码最后两句的思路。
二、转角法:
计算多边形每条边的转角,最后相消为0,则点在多边形内部,否则点在多边形外部
优点:即使多边形的边是弧形的,此算法也不受影响
缺点:需要计算大量的反三角函数,不仅速度慢,而且容易产生精度误差。
算法:
把多边形每条边的转角加起来:如果是360度,则点在多边形内;如果是0度,点在多边形外;如果是180度,则点在多边形边上;
直接求角度要用反三角函数,精度差且费时
如果是凸多边形,就用叉积
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=110;
const double pi=3.1415926;
struct point{
double x,y;
};
point poly[maxn];
int n,q;
double ang(double x1,double y1,double x2,double y2)
{
double ans=x1*x2+y1*y2;
double base=sqrt(x1*x1+y1*y1)*sqrt(x2*x2+y2*y2);
ans/=base;
return acos(ans);
}
int inpolygon(point p)
{
double angle=0;
for(int i=0;i<n;i++){
double x1=poly[i].x-p.x;
double y1=poly[i].y-p.y;
double x2=poly[(i+1)%n].x-p.x;
double y2=poly[(i+1)%n].y-p.y;
angle+=ang(x1,y1,x2,y2);
}
if(fabs(angle-2*pi)<0.000001){
return true;
}else{
return false;
}
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=0;i<n;i++){
scanf("%lf%lf",&poly[i].x,&poly[i].y);
}
point p;
for(int i=0;i<q;i++){
scanf("%lf%lf",&p.x,&p.y);
if(inpolygon(p)){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
边栏推荐
- Pipeline details of IPC (interprocess communication)
- How to traverse objects in the vector container
- 自定义mvc框架实现
- 367. effective complete square dichotomy
- PHP内存马技术研究与查杀方法总结
- ImageView picture fill problem
- JVM之虚拟机栈之动态链接
- Leetcode MySQL database topic 181
- leetcode MYSQL数据库题目181
- 2020-09-25 boost库的noncopyable,用于单例模式
猜你喜欢

container

Application of decorator mode, packaging ServletRequest and adding addparameter method

linux环境下安装配置redis,并设置开机自启动

JVM之方法的绑定机制

Alternative implementation of Scrollview pull-down header amplification

容器

A 2.5D Cancer Segmentation for MRI Images Based on U-Net

Binding mechanism of JVM methods

Zabbix4.4 configure the indicators of the monitoring server and solve the garbled graphics pages

阿里云服务器安装配置redis,无法远程访问
随机推荐
JVM之方法返回地址
zabbix4.4配置监控服务器指标,以及图形页乱码解决
数据源连接池未关闭的问题 Could not open JDBC Connection for transaction
linux下centos7中mysql5.7安装教程
Database common interview questions (with answers)
Gmail:如何快速将邮件全部已读
券商经理给的开户二维码办理股票开户安全吗?我想开个户
Slider validation code
Monitoring data source connection pool usage
Constructing SQL statements by sprintf() function in C language
KDevelop new project
In XML layout, the button is always displayed on the top layer
RecyclerView 通用适配器封装
A 2.5D Cancer Segmentation for MRI Images Based on U-Net
遍历vector容器中的对象的方式
Flutter 基础组件之 GridView
滑块验证代码
C语言中通过sprintf()函数构造sql语句
2019.11.13训练总结
聊聊你理解的线程与并发

