问题,求上图中线段AB 和线段CD的交点P的坐标
根据《算法艺术与信息学竞赛》,公式如下
原理:
利用叉积求得点P分线段DC的比,然后利用高中学习的定比分点坐标公式求得分点P的坐标
c++代码如下
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;const double eps = 1e-6;
struct Point
{
Point(){}
Point(double x,double y):x(x),y(y){}
double x,y;
};int sgn(double x)
{
return x<-eps ? -1 : (x>eps);
}double Cross(const Point& p1,const Point& p2,const Point& p3,const Point& p4)
{
return (p2.x-p1.x)*(p4.y-p3.y) - (p2.y-p1.y)*(p4.x-p3.x);
}double Area(const Point& p1,const Point& p2,const Point& p3)
{
return Cross(p1,p2,p1,p3);
}double fArea(const Point& p1,const Point& p2,const Point& p3)
{
return fabs(Area(p1,p2,p3));
}bool Meet(const Point& p1,const Point& p2,const Point& p3,const Point& p4)
{
return max(min(p1.x,p2.x),min(p3.x,p4.x)) <= min(max(p1.x,p2.x),max(p3.x,p4.x))
&& max(min(p1.y,p2.y),min(p3.y,p4.y)) <= min(max(p1.y,p2.y),max(p3.y,p4.y))
&& sgn(Cross(p3,p2,p3,p4) * Cross(p3,p4,p3,p1)) >= 0
&& sgn(Cross(p1,p4,p1,p2) * Cross(p1,p2,p1,p3)) >= 0;
}Point Inter(const Point& p1,const Point& p2,const Point& p3,const Point& p4)
{
double k = fArea(p1,p2,p3) / fArea(p1,p2,p4);
return Point((p3.x + k*p4.x)/(1+k),(p3.y + k*p4.y)/(1+k));
}int main()
{
Point p1(300, 300);
Point p2(500, 500);Point p3(500, 300);
Point p4(300, 500);if (Meet(p1, p2, p3, p4))
{
cout<< "p1p2和p3p4相交" <<endl;
Point re = Inter(p1, p2, p3, p4);
cout << re.x<<endl;
cout << re.y <<endl;
}
else
{
cout<< "p1p2和p3p4不相交" <<endl;
}Point p5(100, 100);
Point p6(100, 500);
if (Meet(p1, p2, p5, p6))
{
cout<< "p1p2和p5p6相交" <<endl;
Point re = Inter(p1, p2, p5, p6);
cout << re.x<<endl;
cout << re.y <<endl;
}
else
{
cout<< "p1p2和p5p6不相交" <<endl;
}
return 0;
}
执行结果如下图