计算几何公式(点到直线距离,点到线段距离等)

参照学校大佬的模板整理出

定义

const double eps=1e-18;
//记录点的横纵坐标
struct Pot{
	double x,y;
};
//记录线段的起始点和终点
struct Line{
	Pot st,ed;
};
//记录圆的圆心和半径
struct Circle{
	Pot p;
	double r;
};

判断小数大小和正负

//判断小数的正负,如果绝对值小于精度就返回0,小于0就返回-1,否则返回1
int sign(double x){
	if(fabs(x)<eps)return 0;
	if(x<0)return -1;
	return 1;
}
//比较小数的大小,如果x-y小于精度那么认为他们相等,如果x<y就返回-1,x大于y就返回1
int dcmp(double x,double y){
	if(fabs(x-y)<eps)return 0;
	if(x<y)return -1;
	return 1;
}

两个点的坐标加减乘除运算

Pot operator + (Pot a,Pot b){
	return {(a.x+b.x),(a.y +b.y )};
}
//两个点相减的坐标
Pot operator - (Pot a,Pot b){
	return {(a.x -b.x ),(a.y -b.y )};
}
//判断两个点是否坐标相等
bool operator == (Pot a,Pot b){
	if(dcmp(a.x,b.x)==0&&dcmp(a.y,b.y)==0)return 1;
	return 0;
}

两个向量运算


//求一个向量长度乘c之后的向量
Pot operator * (Pot a,double c){
	return {(a.x*c),(a.y *c)};
}
//求一个向量除以c之后的向量
Pot operator / (Pot a,double c){
	return {(a.x/c),(a.y /c)};
}
//向量a在向量b上的投影与b长度的乘积
//a*b=|a||b|cos(c)
double dot(Pot a,Pot b){
	return a.x*b.x+a.y *b.y  ;
}
//向量a与b张成的平行四边形的有向面积,b在a的逆时针方向为正
//a*b=|a||b|sin(c)
double cross(Pot a,Pot b){
	return a.x *b.y -b.x *a.y ;
}

点到点的距离

//a到原点的距离
double get_length(Pot a){
	return sqrt(dot(a,a));
}
//点a和点b之间的距离
double dist(Pot a,Pot b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

点到线的距离

//点p到直线ab的距离
double dist_to_line(Pot p,Pot a,Pot b){
	Pot v1=b-a,v2=p-a;
	return fabs(cross(v1,v2)/get_length(v1));
}
//点p到线段ab的距离
double dist_to_seg(Pot p,Pot a,Pot b){
	if(a==b)return get_length(p-a);
	Pot v1=b-a,v2=p-a,v3=p-b;
	if(sign(dot(v1,v2))<0)return get_length(v2);
	if(sign(dot(v1,v3))>0)return get_length(v3);
	return dist_to_line(p,a,b);
}

两直线交点,判断线段是否相交

//求两直线的交点,v为p的向量,w为q的向量
Pot get_Line_inter(Pot p,Pot v,Pot q,Pot w){
	Pot u=p-q;
	double t=cross(w,u)/cross(v,w);
	return p+v*t;
}
//判断两线段是否相交
bool xiangjiao(Pot a1,Pot a2,Pot b1,Pot b2){
	double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1);
	double c3=cross(b2-b1,a2-b1),c4=cross(b2-b1,a1-b1);
	return sign(c1)*sign(c2)<=0&&sign(c3)*sign(c4)<=0;
}

返回点aob形成的角的角度

//返回角aOb的角度,返回的是弧度
double get_angle(Pot a,Pot b){
	return acos(dot(a,b)/get_length(a)/get_length(b));
}

已知三点坐标求形成的三角形面积

//返回三个点构成的三角形面积的两倍
double area(Pot a,Pot b,Pot c){
	return cross(b-a,c-a);
}

已知三条边长求三角形面积

//三条边长求三角形面积
double helen(double a,double b,double c){
	double p=(a+b+c)/2;
	return sqrt(p*(p-a)*(p-b)*(p-c));
}

一个点绕原点顺时针旋转x度

//返回三个点构成的三角形面积的两倍
double area(Pot a,Pot b,Pot c){
	return cross(b-a,c-a);
}

判断点是否在线段上

//判断点p是否在线段ab上
bool on_seg(Pot p,Pot a,Pot b){
	return sign(cross(p-a,p-b))==0&&sign(dot(p-a,p-b))<=0;
}

n个点组成的多边形的面积

//n个点从0到n-1求多边形面积
double Polygon_area(Pot p[],int n){
	double s=0;
	for(int i=1;i+1<n;i++){
		s+=cross(p[i]-p[0],p[i+1]-p[i]);
	}
	return s/2;
}

点在直线上的投影

//点p在直线ab上的投影
Pot get_line_pro(Pot p,Pot a,Pot b){
	Pot v=b-a;
	return a+v*(dot(v,p-a)/dot(v,v));
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值