ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:41.73KB ,
资源ID:7557484      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7557484.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(判断点是否在多边形内的5种方法.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

判断点是否在多边形内的5种方法.docx

1、判断点是否在多边形内的5种方法判断点是否在多边形内的5种方法 判断点是否在多边形内(凸包和任意多边形分类讨论)/*POJ 1548:判断是否为凸包,判断点(圆是否在凸包内),其中判定点是否在多边形内是主要部分Sample Input5 1.5 1.5 2.01.0 1.02.0 2.01.75 2.01.0 3.00.0 2.05 1.5 1.5 2.01.0 1.02.0 2.01.75 2.51.0 3.00.0 2.01Sample OutputHOLE IS ILL-FORMEDPEG WILL NOT FIT*/法1、2:叉积判定、面积法判定(适用于凸包)。#include#incl

2、ude#include#include#include#include#include#include#include#include#includeusing namespace std;#define maxn 10005double x_multi(point p1,point p2,point p3) return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);bool point_is_inside() /叉积判断点在凸包内部! 只针对于凸多边形。圆心连接每一条边的端点得到的叉积必须同向。 以此可以延伸出面积法判定点是否在凸包内部。这

3、两种方法都局限于在凸多边形 point p1; p1.x=pegx,p1.y=pegy; int i,flag=1; double tmp1=0.0,tmp2; for(i=0;in;i+) tmp2=Fabs(x_multi(p1,pi,p(i+1)%n); if(tmp1*tmp2-eps) flag=0; break; tmp1=tmp2; return flag;double Len_ab(point p1,point p2) return sqrt(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);bool circle_is_inside

4、() /判断圆是否在凸包内 if(pegr=0.0) return true; int i; double ans; point peg,t; peg.x=pegx,peg.y=pegy; for(i=0;in;i+) /判断圆心到多边形的每一条边的最短距离是否不小于半径 t=peg; t.x+=pi.y-p(i+1)%n.y; t.y+=p(i+1)%n.x-pi.x; if(Fabs(x_multi(peg,t,pi)*x_multi(peg,t,p(i+1)%n)=1) /如果垂足不在线段上则选择到线段两个端点距离较小的 ans=Fabs(Len_ab(peg,pi)-Len_ab(pe

5、g,p(i+1)%n)=-1?Len_ab(peg,pi):Len_ab(peg,p(i+1)%n); else ans=fabs(x_multi(peg,p(i+1)%n,pi)/Len_ab(pi,p(i+1)%n); / 否则利用面积/底边得到最小距离 if(ans-pegr=3) scanf(%lf%lf%lf,&pegr,&pegx,&pegy); for(i=0;in;i+) scanf(%lf%lf,&pi.x,&pi.y); double tmp1=0.0,tmp2; bool flag=true; for(i=0;in;i+) /判断是否为凸包,即叉积一直是顺时针或一直是逆时

6、针 tmp2=Fabs(x_multi(pi,p(i+1)%n,p(i+2)%n); /精度控制,否则一直wrong if(tmp1*tmp2=min_x&p3.x=min_y&p3.y=max_y) return true; return false;bool Is_intersected(point p1,point p2,point p3,point p4) /线段相交 double d1=x_multi(p1,p2,p3); double d2=x_multi(p1,p2,p4); double d3=x_multi(p3,p4,p1); double d4=x_multi(p3,p4

7、,p2); if(d1*d20.0&d3*d40.0) return true;/ if(d1=0.0&Onsegment(p1,p2,p3) /由于前面的特判,低处的交点不作为计算 / return true; if(d2=0.0&Onsegment(p1,p2,p4) return true; if(d3=0.0&Onsegment(p3,p4,p1) return true; if(d4=0.0&Onsegment(p3,p4,p2) return true; return false;double Dot(point p1,point p2,point p3) /点积 return (

8、p2.x-p1.x)*(p3.x-p1.x)+(p2.y-p1.y)*(p3.y-p1.y);int pointonsegment(point p0,point p1,point p2) /判断点是否在线段上 return Fabs(x_multi(p0,p1,p2)=0&Fabs(Dot(p0,p1,p2)=0;bool point_is_inside() int i,num=0; point p1,peg,p2,p3; p1.x=999999999.0,p1.y=pegy,peg.x=pegx,peg.y=pegy; /p1坐为在射线极远处的一个点,可以将射线看做线段 for(i=0;ip

9、3.y) /画图知在与多边形端点相交的时候直接计算交的次数都无法直接判定是否在多边形的内外。一条线段的端点有高低之分,此时规定高点的交点为有效交点 swap(p2,p3); if(Is_intersected(peg,p1,p2,p3) num+; return num%2=1;/法4:角度和判定法,适用于任意多边形。如果点在多边形内则点连接多边形每条边的到的角度*叉积和为360. 在边上的话为180.double x_multi(point p1,point p2,point p3) return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y)

10、;double Len_ab(point p1,point p2) return sqrt(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);double Dot(point p1,point p2,point p3) return (p2.x-p1.x)*(p3.x-p1.x)+(p2.y-p1.y)*(p3.y-p1.y);int pointonsegment(point p1,point p2,point p3) return Fabs(x_multi(p1,p2,p3)=0&Fabs(Dot(p1,p2,p3)=0;bool point_is

11、_inside() int i; double sum=0.0; for(i=0;in;i+) if(p0=pi) /点在多边形端点上 return true; if(pi=p(i+1)%n) /去重点 continue; if(pointonsegment(p0,pi,p(i+1)%n) /点在多边形边上 return true; double a=Len_ab(p0,pi); double b=Len_ab(p0,p(i+1)%n); double c=Len_ab(pi,p(i+1)%n); sum+=Fabs(x_multi(p0,pi,p(i+1)%n)*acos(a*a+b*b-c

12、*c)/(2.0*a*b); /计算角度和,叉积大于0则加上,小于0则减去 sum=fabs(sum); if(Fabs(sum-2.0*pi)=0) return true; return false;/法5:改进弧长法(适用于任意多边形)权威算法!精度很高! 以下对于该算法的解析摘自该算法只需O(1)的附加空间,时间复杂度为O(n),系数很小;最大的优点是具有很高的精度,只需做乘法和减法,若针对整数坐标则完全没有精度问题.而且实现起来也非常简单,比转角法和射线法都要好写且不易出错. 有关弧长法的介绍:弧长法要求多边形是有向多边形,一般规定沿多边形的正向,边的左侧为多边形的内侧域.以被测点为

13、圆心作单位圆,将全部有向边向单位圆作径向投影,并计算其中单位圆上弧长的代数和,若代数和为0,则点在多边形外部;若代数和为2,则点在多边形内部;若代数和为,则点在多边形上. 根据上面的介绍,其实弧长法就是转角法,但它的改进方法比较比较厉害:将坐标原点平移到被测点P,这个新坐标系将平面划分为4个象限,对每个多边形顶点P,只考虑其所在的象限,然后按邻接顺序访问多边形的各个顶点P,分析Pi和Pi+1,有下列三种情况: (1) Pi+1在Pi的下一象限,此时弧长和加/2; (2)Pi+1在Pi的上一象限,此时弧长和减/2; (3)Pi+1在Pi的相对象限,首先计算f=pi+1.y*pi.x-pi+1.x

14、*pi.y(叉积),若f=0,则点在多边形上;若f0,弧长和加.最后对算出的代数和和上述的情况一样判断即可.实现的时候还有两点要注意: 1 若P的某个坐标为0时,一律当正号处理; 2 若被测点和多边形的顶点重合时要特殊处理. 还有一个问题那就是当多边形的某条边在坐标轴上而且两个顶点分别在原点的两侧时会出错,如边(3,0)(-3,0),按以上的处理,象限分别是第一和第二,这样会使代数和加/2,有可能导致最后结果是被测点在多边形外,而实际上被测点是在多边形上(该边穿过该点). 对于这点,处理办法是:每次计算Pi和Pi+1时,就计算叉积和点积,判断该点是否在该边上,是则判断结束,否则继续上述过程,这

15、样牺牲了时间,但保证了正确性. 具体实现的时候,由于只需知道当前点和上一点的象限位置,所以附加空间只需O(1).实现的时候可以把上述的/2改成1,改成2,这样便可以完全使用整数进行计算,不必考虑顶点的顺序,逆时针和顺时针都可以处理,只是最后的代数和符号不同而已int get_tmp(point p0) return p0.x=0?(p0.y=0?0:3):(p0.y=0?1:2);bool point_is_inside() int tmp1,tmp2,sum=0,i; point p0,p1; p0.x=pegx,p0.y=pegy; p1.x=p0.x-p0.x,p1.y=p0.y-p0.

16、y; tmp1=get_tmp(p1); for(i=0;in;i+) if(pi=p0) break; int t0=Fabs(x_multi(p0,pi,p(i+1)%n); int t1=Fabs(pi.x-p0.x)*(p(i+1)%n.x-p0.x); int t2=Fabs(pi.y-p0.y)*(p(i+1)%n.y-p0.y); if(!t0&t1=0&t20) sum+=2; else sum-=2; break; case 3: sum-; break; tmp1=tmp2; if(in|sum) /被测点在多边形边上或者在多边形内部 return true; return false;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1