1. 程式人生 > >[計算幾何] (二維)兩線段的交點座標

[計算幾何] (二維)兩線段的交點座標

 給出點A1,A2,B1,B2的座標, 分別構成線段A1A2, 線段B1B2, 求兩線段的交點座標

 

線段A1A2,B1B2如下圖所示, 並建立輔助線(圖片來源於<<挑戰程式設計競賽2>>)

Step1: 先求出B1點到直線A1A2的距離d1, 和B2點到直線A1A2的距離d2

  可根據向量法求出(A1B1為向量, 其它一樣)

d1=\frac{|A1B1\times A1A2|}{|A1A2|}         d2=\frac{|A1B2\times A1A2|}{|A1A2|}

Step2: 求出 t

可根據相似三角形    d1 : d2= t : (1-t)

得  t=\frac{d1}{d1+d2}

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