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;
}
暂时只用到这些,待补充