白书几何模板

/*
白书几何模板
*/
const double eps = 1e-10;
struct Point{
	double x,y;//点的坐标类型自己定
	Point(double x = 0,double y = 0):x(x),y(y){}
};

typedef Point Vector;//向量就是点的表示

Vector operator + (Vector A,Vector B){
	return Vector(A.x + B.x,A.y + B.y);
}
Vector operator -(Vector A,Vector B){
	return Vector(A.x - B.x,A.y - B.y);
}
Vector operator *(Vector A,double p){
	return Vector(A.x * p,A.y * p);
}
Vector operator /(Vector A,double p){
	return Vector(A.x / p,A.y / p);
}
//以上重载操作符
int dcmp(double x){
	if(fabs(x) < eps)return 0;//两数的减差小于eps就返回0
	else return x < 0 ? -1 : 1;//  < 输出-1     > 输出1
}
bool operator == (const Point & A,const Point & B){
	return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;
}
double Dot(Vector A,Vector B){//向量点乘
	return A.x * B.x + A.y * B.y;
}
double Length(Vector A){//向量的长度
	return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B){//返回亮相两夹角的角度
	return acos(Dot(A,B) / Length(A) / Length(B));
}
double Cross(Vector A,Vector B){//两向量叉乘
	return A.x * B.y - A.y * B.x;
}
Vector Rotate(Vector A,double rad){//rad是弧度
	return Vector(A.x * cos(rad) - A.y * sin(rad),A.x * sin(rad) + A.y * cos(rad));
}
Vector Normal(Vector A){//计算向量的单位法线,保证该向量为非0向量
	double L = Length(A);
	return Vector(-A.y / L,A.x / L);
}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){//计算两直线的交点,确保两直线只有一个交点,且Cross(v,w)非零
	Vector u = P - Q;
	double t = Cross(w,u) / Cross(v,w);
	return P + v * t;
}
double DistanceToLine(Point P,Point A,Point B){//直线为AB,计算点P到AB的距离
	Vector v1 = B - A,v2 = P - A;
	return fabs(Cross(v1,v2)) / Length(v1);//如果不取绝对值,得到的是有向距离
}
Point GetlLineProjection(Point P,Point A,Point B){
	Vector v = B - A;
	return A + v * (Dot(v,P - A) / Dot(v,v));
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){//判断两线段是否相交,其中交点一定要恰好有一个,一个线段的某一点不在另一个线段的端点上
	double c1 = Cross(a2 - a1,b1 - a1),c2 = Cross(a2 - a1,b2 - a1),
		   c3 = Cross(b2 - b1,a1 - b1),c4 = Cross(b2 - b1,a2 - b1);
	return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}//如果c1,c2同时为0,则说明两线段有部分重叠,如果不全为0,其中一个为0,则说明一个线段的端点在另一个线段上
bool OnSegment(Point p,Point a1,Point a2){//判断线段的端点是否在另一个线段上
	return dcmp(Cross(a1 - p,a2 - p)) == 0 && dcmp(Dot(a1 - p,a2 - p)) < 0;
}   


/*
以下为和圆有关的函数
*/
struct Circle{
	Point c;
	double r;
	Circle(Point c,double r):c(c),r(r){}
	Circle(){}
	Point point(double a){//给出角度,求圆上的点
		return Point(c.x + cos(a) * r,c.y + sin(a) * r);
	}
};

//求圆和直线的交点,假设直线为AB,圆为c,得到修改的t1,t2,若存在的话,则交点P是A + ti * (B - A)
int getLineCircleIntersection(Point A,Point B,Circle c,double &t1,double &t2){
	Vector v = B - A;//求出直线的向量
	double a = v.x,b = A.x - c.c.x,c = v.y,d = A.y - c.c.y;
	double e = a * a + c * c,f = 2 * (a * b + c * d),g = b * b + d * d - c.r * c.r;
	double delta = f * f - 4 * e * g;
	if(dcmp(delta) < 0)return 0;//相离
	if(dcmp(delta) == 0){//相切
		t1 = t2 = -f / (2 * e);
		return 1;
	}
	//接下来是相交
	t1 = (-f - sqrt(delta)) / (2 * e);
	t2 = (-f + sqrt(delta)) / (2 * e);
}

//以下为求两圆的交点
double angle(Vector v){return atan2(v.y,v.x);}//其中atan2(y,x)表示出发点是原点,目标点是(x,y)的射线与x正半轴的夹角的角度
//如果有交点,设交点为P1,P2
int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point> & sol){//其中sol存交点
	double d = Length(C1.c - C2.c);
	if(dcmp(d) == 0){//圆心重合
		if(dcmp(C1.r - C2.r) == 0){
			if(dcmp(C1.r - C2.r) == 0)return -1;//两圆重合
			return 0;//大圆包含小圆,无交点
		}
	}
	if(dcmp(C1.r + C2.r - d) < 0)return 0;//两圆半径相加小于距离,外离
	if(dcmp(fabs(C1.r - C2.r) - d) > 0)return 0;//大圆包含小圆
	double a = angle(C2.c - C1.c);//向量C1C2的极角
	double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));//C1C2到C1P1的角
	Point p1 = C1.point(a - da),p2 = C1.point(a + da);
	sol.push_back(p1);
	if(p1 == p2)return 1;//相切
	sol.push_back(p2);
	return 2;
}

//以下为从一个点出发,求已知圆的切线
//过点p到圆c的切线,v[i]是第i条切线,返回切线数
int getTangents(Point p,Circle c,vector<Vector> &v){
	Vector u = C.c - p;
	double dist = Length(u);
	if(dist < C.r)return 0;//点在圆内,无切线
	else if(dcmp(dist - C.r) == 0){//p在圆上,只有一条切线
		v.push_back(Rotate(u,PI / 2));//其中PI为常数3.1415926.....
		return 1;
	}else {
		double ang = asin(C.r / dist);
		v.push_back(Rotate(u,-ang));
		v.push_back(Rotate(u,+ang));
		return 2;
	}
}

//以下为知道两个圆,求两个圆的公切线
int getTangents(Circle A,Circle B,vector<Point> &a,vector<Point> &b){
	int cnt = 0;
	if(A.r < B.r){swap(A,B);swap(a,b);}
	int d2 = (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
	int rdiff = A.r - B.r;
	int rsum = A.r + B.r;
	if(d2 < rdiff * rdiff)return 0;//内含无切线
	double base = atan2(B.y - A.y,B.x - A.x);
	if(d2 == 0 && A.r == B.r)return -1;//两圆重合,无限多条切线
	if(d2 == rdiff * rdiff){
		a.push_back(A.getPoint(base));b.push_back(B.getPoint(base));
		return 1;//内切,一条切线
	}
	//以上为一个圆在另一个园内,以下为有外公切线
	double ang = acos((A.r - B.r) / sqrt(d2));
	a.push_back(A.getPoint(base + ang));b.push_back(B.getPoint(base + ang));
	a.push_back(A.getPoint(base - ang));b.push_back(B.getPoint(base - ang));
	if(d2 == rsum * rsum){//一条内公切线,即两圆外切
		a.push_back(A.getPoint(base));b.push_back(B.getPoint(base));
	}else if(d2 > rsum * rsum){//两圆外离
		double ang = acos((A.r + B.r) / sqrt(d2));
		a.push_back(A.getPoint(base + ang));b.push_back(B.getPoint(PI + base + ang));//其中PI为圆周率常数
		a.push_back(A.getPoint(base - ang));b.push_back(B.getPoint(PI + base - ang));
	}
	return cnt;//返回切线条数

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值