[計算幾何] (二維)兩線段的交點座標
阿新 • • 發佈:2018-11-27
給出點A1,A2,B1,B2的座標, 分別構成線段A1A2, 線段B1B2, 求兩線段的交點座標
線段A1A2,B1B2如下圖所示, 並建立輔助線(圖片來源於<<挑戰程式設計競賽2>>)
Step1: 先求出B1點到直線A1A2的距離d1, 和B2點到直線A1A2的距離d2
可根據向量法求出(A1B1為向量, 其它一樣)
Step2: 求出 t
可根據相似三角形 d1 : d2= t : (1-t)
得
Step3: 求出交點點O的座標
根據比例縮放可求出向量B1O, t為小數, 向量B1O=t * 向量B1B2
又因為向量B1O=點O座標 - 點B1座標, 而B1座標已知, 可求出點O的座標
程式程式碼參考
#include<iostream> #include<cmath> #include<cstdio> using namespace std; typedef struct node { double x, y; }NODE; inline NODE Vector(NODE a, NODE b); double dis2(NODE a, NODE b); double cross(NODE A, NODE B, NODE P); double dot(NODE A, NODE B, NODE P); int dir(NODE A, NODE B, NODE P); double disLine(NODE A, NODE B, NODE P); int main() { NODE A1, A2, B1, B2; cin >> A1.x >> A1.y >> A2.x >> A2.y; cin >> B1.x >> B1.y >> B2.x >> B2.y; if (dir(A1, A2, B1)*dir(A1, A2, B2) <= 0 && dir(B1, B2, A1)*dir(B1, B2, A2) <= 0) {//判斷有無交點 double t = disLine(A1, A2, B1) / (disLine(A1, A2, B1) + disLine(A1, A2, B2)); NODE B1B2 = Vector(B1, B2); NODE inter = { B1.x + B1B2.x*t, B1.y + B1B2.y*t }; cout << inter.x << ' ' << inter.y << endl; } else cout << "沒有交點" << endl; return 0; } inline NODE Vector(NODE a, NODE b) //向量ab { return{ b.x - a.x, b.y - a.y }; } double dis2(NODE a, NODE 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) //向量的外積 { NODE AB = Vector(A,B); NODE AP = Vector(A,P); return AB.x*AP.y - AB.y*AP.x; } double dot(NODE A, NODE B, NODE P) //向量的內積 { NODE AB = Vector(A,B); NODE AP = Vector(A,P); return AB.x*AP.x + AB.y*AP.y; } int dir(NODE A, NODE B, NODE P) //點與線段方位判定 { if (cross(A, B, P) > 0) return -1; else if (cross(A, B, P)<0) return 1; else if (dot(A, B, P) < 0) return -2; else if (dot(A, B, P) >= 0) { if (dis2(A, B) < dis2(A, P)) return 2; else return 0; } } double disLine(NODE A, NODE B, NODE P) //點P到直線AB的距離 { return fabs(cross(A, B, P)) / sqrt(dis2(A, B)); }
參考書籍: 挑戰程式設計競賽2