您的位置:首页 > 其它

平面几何基本知识——学习笔记(1)

2017-06-16 07:56 281 查看
这段时间也做了一些平面几何的题目,将一些基本的知识写一下,以免忘了(好草率的初衷)。

1.向量

向量的定义为既有方向,又有长度,且可以自由平移的线段(注意不是有向线段,有向线段不可以自由平移,因为具有起点)。

PS:程序实现中,我们经常把向量的起点移到(0,0),然后用终点坐标(x,y)表示这个向量。

向量的定义:

struct data{
double x,y;
data (double x=0,double y=0):x(x),y(y){}//方便读入
};


2.向量的基本运算

这里就是几何运算和一些大小关系……

data operator + (const data a,const data b){return data(a.x+b.x,a.y+b.y);} //向量+向量 点+向量
data operator - (const data a,const data b){return data(a.x-b.x,a.y-b.y);} //点-点
data operator * (const data a,double b){return data(a.x*b,a.y*b);} //向量*点
data operator / (const data a,double b){return data(a.x/b,a.y/b);} //向量/点

bool operator < (const data a,const data b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}    //小于号一般定义在结构体里,要调用STL排序(sort)时更加方便。

const double eps=1e-10;   //这个是为了避免精度,eps的值随题目要求而定。
int dcmp(double x)
{
if (fabs(x)<eps) return 0;
return (x<0)?-1:1;
}
bool operator == (const data a,const data b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y==0);
}  //dcmp是比较差值的函数,减少精度误差。


3.叉积和点积

点积的几何定义是有两个向量a和b,则a和b的点积等于二者长度的乘积再乘上他们夹角的余弦。而点积的代数定义为xa*xb+ya*yb,利用这个可以直接求出两个向量之间的夹角:

double dot(const data a,const data b){return a.x*b.x+a.y*b.y;}
double leng(const data x){return sqrt(dot(x,x));} //求向量长度
double angle(const data a,const data y){return acos(dot(a,b)/leng(a)/leng(b));}  //求夹角


叉积的几何定义是有两个向量a和b,则a和b的叉积等于两者长度的乘积再乘上他们夹角的正弦,而叉积的代数定义为xa*ya-xb*ya;其实两个向量叉积等于其组成的三角形有向面积的两倍。

double cross(const data a,const data b) {return a.x*b.y-a.y*b.x;}
double gets(const data a,const data b,const data c)
{
return cross(b-a,c-a)
}//求三角形有向面积。


4.用参数表示直线(射线、线段)

直线可以用直线上一点P0和方向向量v表示(注意重要的是v的x,y值之比,靠这个来推出直线的斜率,而v本身的大小基本无用)。直线上所有点P满足P=P0+tv,其中t为参数,可以用一种简便的方法求出任意两点(不是同一个)A和B的直线,P0=A,v=B-A,则参数方程为A+(B-A)t。这样写有一个极大的好处,就是可以用同一个参数方程来表示直线,射线和线段,唯一的不同在于取值范围,直线无限制,射线则t>0,线段则0<=t<=1。

5.两直线交点。

设两条直线(用参数方程表示)为a+tb和c+td,则需要求出交点分别在两条直线上的参数,设t1为交点在第一条直线的参数,t2为交点在第二条直线的参数,则x和y坐标可以列出一个方程,解得



代码如下:

data getp(data a,data b,data c,data d)
{
double t=cross(d,a-c)/cross(b,d);
return a+b*t;
}


6.点到直线(线段)距离

点到直线距离不难,有三个点p,a,b,则这三个点可以构成一个平行四边形,设向量b-a为底,那么点到直线距离就是平行四边形的面积除以底,代码如下:

double minLl(const data p,const data a,const data b){
data va=b-a,vb=p-a;
return fabs(cross(va,vb))/leng(va);//如果不取绝对值,叉积将得到有向面积。
}


点到线段距离比点到直线距离略复杂一点,首先求出点在线段所在直线上的距离,设这个点为q,然后判断q的位置,如果是在线段ab上,则所求距离为pq,如果在射线ab上,则所求距离为pb,否则所求距离为pa。至于判断点q的位置吗,可以通过点积进行。

代码如下

double minLs(const data p,const data a,const data b)
{
if (a==b) return leng(p-a);
data va=b-a,vb=p-a,vc=p-b;
if (dcmp(dot(va,vb))<0) return leng(vb);
else if (dcmp(dot(va,vc))>0) return leng(vc);
else return fabs(cross(va,vb))/leng(va);
}


备注:

由于作者fhj水平实在太菜,如本博客有错,请多多指出,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: