题目: 面试题 16.03. 交点
解题思路
思路:
- 两条直线相交:叉乘,向量叉乘 符号为逆时针旋转共线为正,顺时针旋转为负。值为向量组成的三角形面积的2倍。
- 点
(X, Y)
在线段上(X1,Y1) (X2,Y2)
:X>=min(X1,X2)&&X<=max(X1,X2)&&Y>=min(Y1,Y2)&&Y<=min(X2,Y2)
- 判断两条线段是否相交:
如果四个点组成一个四边形,则必然存在交点
如果四个点组成三角形,则一端端点必为交点
如果四个点共线,如果有交点,答案必然是两条线段中X较小的点,然后判断该点是否在另一条直线上即可,否则两条共线的线段不相交。
- 定比分点:点(x,y)在线段内部时,求(x,y)的坐标
x=(x1+ax2)/(1+a);y=(y1+ay2)/(1+a);
下面分别讨论三种情况
用线段 L1 = (X1, Y1) (X2, Y2)
表示第一条线段
L2 = (A1, B1) (A2, B2)
表示第二条线段
四点组成四边形
线段L1的端点必然存在线段L2的两侧
线段L2的端点必然存在线段L1的两侧
且交点在必然存在线段的内部,根据定比分点公式计算即可
判断两个点是否处于线段两侧
根据叉乘的性质,如果在其线段两侧,叉乘符号必然相反,相乘符号为负;如在同侧,乘积必然大于0;如一端端点在线段上,其叉乘必然为0。
以 判断(X1,Y1)(X2,Y2)是否处于线段L2的两侧 为例
- 构造向量L=(A2-A1,B2-B1),L1=(X1-A1,Y1-B1),L2=(X2-A1,X2-B1)
- 判断(L x L1) * (L x L2)的符号即可
- 此处需要注意同时需要判断另一条线段是否能把两个端点放在两侧,否则不能保证四点组成四边形。
// 判断(X1,Y1)(X2,Y2)是否处于线段L2的两侧
int crossA1X1 = cross(A2 - A1, B2 - B1, X1 - A1, Y1 - B1), crossA1X2 = cross(A2 - A1, B2 - B1, X2 - A1, Y2 - B1);
四点组成三角形
如一端端点在线段上,其叉乘必然为0,利用叉乘判断哪个点在线段上,即为答案
四点共线
- 分别找出L1 L2线段中x较小的点(X,Y),(A,B)
- 判断(X,Y)是否在线段L2上,判断(A,B)是否在L1上
- 若存在一个点在另一条线段上即为答案,否则两条线段相离,无交点
代码
class Solution {
public:
vector<double> intersection(vector<int>& start1, vector<int>& end1, vector<int>& start2, vector<int>& end2) {
vector<double> ans;
int X1 = start1[0], X2 = end1[0], A1 = start2[0], A2 = end2[0];
int Y1 = start1[1], Y2 = end1[