计算几何基础知识

USACO上接触到计算几何,有点闷

先巩固一下基础

/**********************************
        计算几何基础知识         
**********************************/ 

#include<Math.h>

#define MaxX 10000
#define EP 1e-10
#define Min(a,b) a>b?b:a
#define Max(a,b) a>b?a:b

typedef struct Point   //点结构 
{
	double x,y;
}Point;

typedef struct Line    //线段结构 
{
	Point s,e;
}Line;

/*返回两点之间欧式距离*/
double Dist(Point a,Point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} 

/*计算向量的叉积*/
double Multiply(Point sp,Point ep,Point op)
{
	return  (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);  
/*返回值>0,sp在opep的顺时针方向。<0,sp在opep的逆时针方向。=0共线,可能同向也可能逆向*/ 
}

/* 判断点是否在线段上*/
int OnLine(Line l,Point P) 
{
/*要求点在线段所在的直线上,且点在以线段为对角线的矩形中*/ 
	if(Multiply(l.s,l.e,P)==0&&(P.x-l.s.x)*(P.x-l.e.x)<=0&&(P.y-l.s.y)*(P.y-l.e.y)<=0)
	   return 1;
 	else	
	   return 0;
}

/* 判断两条线段是否相交*/
int Intersect(Line u,Line v)
{
/*要求通过排斥实验和跨立实验*/ 
	if( Min(u.s.x,u.e.x)<=Max(v.s.x,v.e.x)&&
	    Min(v.s.x,v.e.x)<=Max(u.s.x,u.e.x)&&
	    Min(u.s.y,u.e.y)<=Max(v.s.y,v.e.y)&&
	    Min(v.s.y,v.e.y)<=Max(u.s.y,u.e.y)&&
	    Multiply(u.s,v.s,v.e)*Multiply(u.e,v.s,v.e)>=0&&
	    Multiply(v.s,u.s,u.e)*Multiply(v.e,u.s,u.e)>=0
	    )
	    return 1; 
 /*此相交包括顶点相交*,如需要使用非顶点相交,在条件中加上以下条件:       */ 
 /*     !OnLine(u,v.e)&&!OnLine(u,v.s)&&!Online(v,u.e)&&!Online(v,u.s)    */
 	else 
 		return 0;
} 

/*计算多边形面积*/ 
int AreaOfPolygon(int vcount,Point P[])
{
	if(vcount<3)
		return 0;
	int Area=0,i,j;
	for(i=0;i<vcount;i++){
		j=(i+1)%vcount;
		Area+=(P[i].x*P[j].y-P[i].y*P[j].x)/2;
	}
	return Area<0?-Area:Area;
}

/*
    射线法计算点是否在多边形内
为了统一,我们在计算射线L和多边形的交点时:
1。对于多边形的水平边不作考虑;
2。对于多边形的顶点和L相交的情况,如果该顶点是其所属的边上纵坐标较大的顶点,则计数,否则忽略;
3。对于P在多边形边上的情形,直接可判断P属于多边行。
*/

int IsInPolygon(Point P,int vcount,Point V[])
{
	Line u,v;
	u.s.x=P.x;
	u.s.y=P.y;
	u.e.x=MaxX;
	u.e.y=P.y;
	int i,j,count=0;
	for(i=0;i<vcount;i++){
		j=(i+1)%vcount;
		v.s.x=i.x;
		v.s.y=i.y;
		v.e.x=j.x;
		v.e.y=j.y;
		if(OnLine(v,P))    //判断P是否在某条边上 
			return 1;
		if(v.s.y-v.e.y>EP){ //判断边是否水平 
			if((OnLine(u,i)&&i.y>j.y)||OnLine(u,j)&&j.y>i.y)
				count++;
			else
			if(Intersect(u,v))
				count++;         
		}
	}
	return count%2==1; 
}


 

暂时只用到这些,待补充

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值