关于几何算法的一个简单问题

jwd_1_cool 2003-08-18 09:28:17
谁能给我贴个
判断点是否在多边形内或上的c/c++程序啊?

另:如何将输入的多边形点,(可能是顺时针,也可能是逆时针顺序)转化到一个数组里按逆时针排列。

参考 zju1081 ,这道题过的人不少,若能相告,3x
...全文
59 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jwd_1_cool 2003-08-24
  • 打赏
  • 举报
回复
继续
jwd_1_cool 2003-08-20
  • 打赏
  • 举报
回复
我怎么也看不出我和超超的程序有什么区别,但就是wa
我也试过copy超超的小函数,但还是不行,现在将的未改的最初程序,贴上来,实在是痛苦啊




#include<iostream.h>
#include<math.h>
int n,m;
#define infinity 1e200
#define EP 1e-10

struct TPoint{
double x,y;
};

struct TLineSeg{
TPoint a,b;
};

double max(double a,double b)
{
return a>b?a:b;
}
double min(double a,double b)
{
return a<b?a:b;
}

double multiply(TPoint p1,TPoint p2,TPoint p0)
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}



//确定两条线段是否相交
bool intersect(TLineSeg u,TLineSeg v)
{
return( (max(u.a.x,u.b.x)>=min(v.a.x,v.b.x))&&
(max(v.a.x,v.b.x)>=min(u.a.x,u.b.x))&&
(max(u.a.y,u.b.y)>=min(v.a.y,v.b.y))&&
(max(v.a.y,v.b.y)>=min(u.a.y,u.b.y))&&
(multiply(v.a,u.b,u.a)*multiply(u.b,v.b,u.a)>=0)&&
(multiply(u.a,v.b,v.a)*multiply(v.b,u.b,v.a)>=0));
}

//判断点p是否在线段l上 不包括端点
bool online(TLineSeg l,TPoint p)
{
return( (multiply(l.b,p,l.a)==0)&&( ((p.x-l.a.x)*(p.x-l.b.x)<0 )||( (p.y-l.a.y)*(p.y-l.b.y)<0 )) );
}
//包括端点
bool online2(TLineSeg l,TPoint p)
{
return( (multiply(l.b,p,l.a)==0)&&( ((p.x-l.a.x)*(p.x-l.b.x)<=0 )||( (p.y-l.a.y)*(p.y-l.b.y)<=0 )) );
}

//判断两个点是否相等
bool Euqal_Point(TPoint p1,TPoint p2)
{
return((fabs(p1.x-p2.x)<EP)&&(fabs(p1.y-p2.y)<EP));
}

//一种线段相交判断函数,当且仅当u,v相交并且交点不是u,v的端点时函数为true;
bool intersect_A(TLineSeg u,TLineSeg v)
{
return((intersect(u,v))&&
(!Euqal_Point(u.a,v.a))&&
(!Euqal_Point(u.a,v.b))&&
(!Euqal_Point(u.b,v.a))&&
(!Euqal_Point(u.b,v.b)));
}


/*===============================================

判断点q是否在多边形Polygon内,
其中多边形是任意的凸或凹多边形,
Polygon中存放多边形的逆时针顶点序列

================================================*/

int InsidePolygon(int vcount,TPoint Polygon[],TPoint q)
{
int c=0,i,n;
TLineSeg l1,l2;

l1.a=q;
l1.b=q;
l1.b.x=infinity;
n=vcount;
for (i=0;i<vcount;i++)
{
l2.a=Polygon[i];
l2.b=Polygon[(i+1)%n];
if(online2(l2,q))return 1;
if ( (intersect_A(l1,l2))||
(
(online(l1,Polygon[(i+1)%n]))&&
(
(!online(l1,Polygon[(i+2)%n]))&&
(multiply(Polygon[i],Polygon[(i+1)%n],l1.a)*multiply(Polygon[(i+1)%n],Polygon[(i+2)%n],l1.a)>0)
||
(online(l1,Polygon[(i+2)%n]))&&
(multiply(Polygon[i],Polygon[(i+2)%n],l1.a)*multiply(Polygon[(i+2)%n],Polygon[(i+3)%n],l1.a)>0)
)
)
) c++;
}
return(c%2!=0);
}
TPoint p[100];
int main()
{
int cs(1);
bool first=true;
while(cin>>n){
if(n==0)return 0;
if(!first) cout<<endl;
cout<<"Problem "<<cs++<<':'<<endl;
cin>>m;
TPoint t;
for(int i=0;i<n;i++){
cin>>t.x>>t.y;
p[i]=t;
}

for(int i=0;i<m;i++){
cin>>t.x>>t.y;

if(InsidePolygon(n,p,t))
cout<<"Within"<<endl;
else cout<<"Outside"<<endl;
}
first=false;
}
return 1;
}
jwd_1_cool 2003-08-20
  • 打赏
  • 举报
回复
晕翻,kbsoft(景乐) 你给的那个贴子是什么时候的啊,小虎竟然说自己是第一次做计算几何的题目??

这道题目 典型的很,楼上这位说的我也知道。
我WA了,以后判断了一下,可能又两个原因:
1。 使用int 后面叉乘精度出错,改成double 了
2。 也是我疑惑的,题目输入数据没说是按什么顺序啊,可是象 超超 写的函数里 Polygon[],必须是逆时针的, 这怎么说????
LeeMaRS 2003-08-20
  • 打赏
  • 举报
回复
呵呵, 好久没来转转了, 1081没写总结, 不然可以帖出来给大家看看:)
前段时间又写了一个角度和法的, 感觉比射线法简单得多了. ^^
loewe 2003-08-18
  • 打赏
  • 举报
回复
哈哈,mmmcd(超超) 动作真的好快啊

判断点是否在多边行内,简单得说就是划射线,从这个点向左或又划一条平行的与x轴的射线,用射线和多边行的边去判断交点,如果交点个数是奇数的话,说明点在多边行内了
kbsoft 2003-08-18
  • 打赏
  • 举报
回复
超超的速度好快啊。刚要re就回复了....
ZOJ 1081以前讨论过了

http://search.csdn.net/expert/topic/6/603/2002/9/11/1013280.htm
mmmcd 2003-08-18
  • 打赏
  • 举报
回复
给你
//#include <iostream>
#include <fstream>
#include <cmath>

using namespace std;
#define INF 1E200 //无穷大
#define EP 1E-10 //无穷小
ifstream cin("1081.in");
ofstream cout("1081.out");
struct POINT
{
double x;
double y;
}poly[100];
struct LINESEG
{
POINT s;
POINT e;
};
double max(double a,double b)
{
return a>b?a:b;
}
double min(double a,double b)
{
return a<b?a:b;
}
double multiply(POINT sp,POINT ep,POINT op)
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool online(LINESEG l,POINT p)
{
return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) );
}

/* 如果线段u和v相交(包括相交在端点处)时,返回true */
bool intersect(LINESEG u,LINESEG v)
{
return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&& //排斥实验
(max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&&
(max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&&
(max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&&
(multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=0)&& //跨立实验
(multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0));
}

/* (线段u和v相交)&&(交点不是双方的端点) 时返回true */
bool intersect_A(LINESEG u,LINESEG v)
{
return((intersect(u,v))&&
(!online(u,v.s))&&
(!online(u,v.e))&&
(!online(v,u.e))&&
(!online(v,u.s)));
}

/* 射线法判断点q与多边形polygon的位置关系,要求polygon为简单多边形,顶点按逆时针排列
如果点在多边形内: 返回0
如果点在多边形边上:返回1
如果点在多边形外: 返回2 */

int insidepolygon(int vcount,POINT Polygon[],POINT q)
{
int c=0,i,n;
LINESEG l1,l2;
bool bintersect_a,bonline1,bonline2,bonline3;
double r1,r2;

l1.s=q;
l1.e=q;
l1.e.x=double(INF);
n=vcount;
for (i=0;i<vcount;i++)
{
l2.s=Polygon[i];
l2.e=Polygon[(i+1)%n];
if(online(l2,q))return 1; //如果点在边上,返回1
if ( (bintersect_a=intersect_A(l1,l2))|| //相交且不在端点
(
(bonline1=online(l1,Polygon[(i+1)%n]))&& //第二个端点在射线上
(
(!(bonline2=online(l1,Polygon[(i+2)%n])))&& //前一个端点和后一个端点在射线两侧
((r1=multiply(Polygon[i],Polygon[(i+1)%n],l1.s)*multiply(Polygon[(i+1)%n],Polygon[(i+2)%n],l1.s))>0)
||
(bonline3=online(l1,Polygon[(i+2)%n]))&& //下一条边是水平线,前一个端点和后一个端点在射线两侧
((r2=multiply(Polygon[i],Polygon[(i+2)%n],l1.s)*multiply(Polygon[(i+2)%n],Polygon[(i+3)%n],l1.s))>0)
)
)
) c++;
}
if(c%2 == 1)
return 0;
else
return 2;
}


int N,M;

int main()
{
int cn=1;
while(cin>> N && N)
{
if(cn > 1)cout<<endl;
cout<<"Problem "<<cn<<':'<<endl;cn++;
cin>>M;
for(int i=0;i<N;i++)
{
cin>>poly[i].x>>poly[i].y;
}
POINT q;
for(int i=0;i<M;i++)
{
cin>>q.x>>q.y;
if(insidepolygon(N,poly,q) < 2)
{
cout<<"Within\n";
}
else
{
cout<<"Outside\n";
}
}
}
return 0;
}


33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧