给出点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