[计算几何] (二维)圆与直线的交点

给出圆心O的坐标, 和半径r, 再给出点A,B的坐标构成直线AB, 求出圆与直线AB交点的坐标

如下图

 Step1: 首先求出圆心c在直线l 上的投影点pr的坐标

可通过求解向量p1pr(p1pr的长度 * p1p2的单位向量)

Step2: 计算向量p1p2的单位向量e, 再勾股定理求出base的长度, 进而求出向量base

Step3: 最后,以pr作为起点, 向正or负方向加上该向量, 就可以得到圆与直线的交点了

程序代码参考

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
typedef struct node
{
	double x, y;
}NODE;
inline NODE Vector(NODE A, NODE B);  //向量AB
double cross(NODE A, NODE B, NODE P);
inline double dis2(NODE a, NODE b);
double disLine(NODE A, NODE B, NODE P);
double dot(NODE A, NODE B, NODE P);
NODE prxy(NODE A, NODE B, NODE O);
NODE Vbase(NODE A, NODE B, NODE O, int r);
int main()
{
	NODE A, B, O;
	double r;
	cin >> O.x >> O.y>>r;
	cin >> A.x >> A.y >> B.x >> B.y;
	NODE Base = Vbase(A, B, O, r);      //向量base
	NODE pr = prxy(A, B, O);            //点pr
	NODE x1 = { Base.x + pr.x, Base.y + pr.y };
	NODE x2 = { pr.x - Base.x, pr.y - Base.y };
	if (disLine(A, B, O) > r)
		cout << "没有交点" << endl;
	else
		cout << x1.x << ' ' << x1.y << ' ' << x2.x << ' ' << x2.y << endl;	
	return 0;
}
NODE Vbase(NODE A,NODE B,NODE O,int r)    //求向量base
{
	double base = sqrt(r*r - disLine(A, B, O)*disLine(A, B, O));
	NODE AB = Vector(A, B);
	NODE e = { AB.x / sqrt(dis2(A, B)), AB.y / sqrt(dis2(A, B)) };
	return{ e.x*base, e.y*base };
}
NODE prxy(NODE A,NODE B,NODE O)   //求点pr的坐标, 点pr是圆心O到直线AB的垂足
{
	NODE AO = Vector(A, O);
	NODE AB = Vector(A, B);
	double l = dot(A, B, O) / sqrt(dis2(A, B));
	NODE e = { AB.x / sqrt(dis2(A, B)), AB.y / sqrt(dis2(A, B)) };
	NODE Apr = { e.x*l, e.y*l };
	return{ A.x + Apr.x, A.y + Apr.y };
}
double disLine(NODE A, NODE B, NODE P)   //点P到直线AB的距离
{
	return fabs(cross(A,B,P))/sqrt(dis2(A,B));
}
double dot(NODE A, NODE B, NODE P)    //向量AB,AP的内积
{
	NODE AB = Vector(A, B);
	NODE AP = Vector(A, P);
	return AB.x*AP.x + AB.y*AP.y;
}
inline double dis2(NODE a, NODE b)            //点a,b距离的平方
{
	return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}
double cross(NODE A, NODE B, NODE P)   //向量AB与向量AP的外积
{
	NODE AB = Vector(A, B);
	NODE AP = Vector(A, P);
	return AB.x*AP.y - AB.y*AP.x;
}
inline NODE Vector(NODE A, NODE B)    //向量AB
{
	return{ B.x - A.x, B.y - A.y };
}

参考书籍: 挑战程序设计竞赛2

猜你喜欢

转载自blog.csdn.net/Mr_HCW/article/details/82857715