1. 程式人生 > >[計算幾何] (二維)圓與直線的交點

[計算幾何] (二維)圓與直線的交點

給出圓心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