[計算幾何] (二維)圓與直線的交點
阿新 • • 發佈:2018-11-27
給出圓心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