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

这段时间也做了一些平面几何的题目,将一些基本的知识写一下,以免忘了(好草率的初衷)。


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*yb-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水平实在太菜,如本博客有错,请多多指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值