给出点A、B的坐标, 构成线段AB, 再给出一点P的坐标, 判断点P与线段AB的位置关系
如下图, 点P与AB的关系可分为5种情况
(1) 点P在线段AB的顺时针方向
(2) 点P在线段AB的逆时针方向
(3) 点P在线段AB的反向延长线上
(4) 点P在线段AB的延长线上
(5) 点P在线段AB上
为了更好的解决此类问题, 借助两个工具: 向量的外积(叉积)和向量的内积(点积)
向量的外积(叉积)
用的形式表示两个向量, 则 与 的外积为
(可通过矩阵导出)
在二维平面上, , 所以二维平面上向量的外积的大小为
向量的内积(点积)
点与线段位置的判定标准
1. 如果向量AB与向量AP的外积(叉积)为正, 则点P在线段AB的逆时针方向, 如上图(1)
2. 如果向量AB与向量AP的外积(叉积)为负, 则点P在线段AB的顺时针方向, 如上图(2)
在上两种情况都不满足的情况下(讨论完外积(叉积), 下面讨论内积(点积))
注意: 必须上两种情况不满足才讨论以下情况
3. 如果向量AB与向量AP的内积(点积)为负, 则点P在线段AB的反向延长线上, 如上图(3)
4. 如果向量AB与向量AP的内积(点积)为非负, 有两种情况分别为上图(4) 和 (5)
4.1. 如果向量AB的模|AB|小于向量AP的模|AP|, 则点P在线段AB的延长线上, 如上图(4)
4.2. 如果向量AB的模|AB|等于或小于向量AP的模|AP|, 则点P在线段AB上, 如上图(5) (|AB|=|AP|时, P点与B点重合)
程序代码
#include<iostream>
#include<cmath>
using namespace std;
typedef struct node
{
double x, y;
}NODE;
double cross(NODE A, NODE B, NODE P) //计算向量AB与AP的外积(叉积)的大小(不包括方向)
{
NODE AB = { B.x - A.x, B.y - A.y };
NODE AP = { P.x - A.x, P.y - A.y };
return AB.x*AP.y - AB.y*AP.x;
}
double dot(NODE A, NODE B, NODE P) //计算向量AB与向量AP的内积(点积)
{
NODE AB = { B.x - A.x, B.y - A.y };
NODE AP = { P.x - A.x, P.y - A.y };
return AB.x*AP.x + AB.y*AP.y;
}
double mol(NODE a,NODE b) //求向量ab的模(也可以说是点a、b的距离)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int dir(NODE A,NODE B,NODE P) //判断点P在线段AB的哪个方向上
{
if (cross(A, B, P) > 0) return 1; //外积大于0,点p在线段AB的逆时针方向
else if (cross(A, B, P) < 0) return 2; //外积小于0,点p在线段AB的顺时针方向
else if (dot(A, B, P) < 0) return 3; //内积小于0,点p在线段AB的反延长线上
else if (dot(A, B, P)>=0) //内积大于0,分两种情况
{
if (mol(A, B) < mol(A, P)) return 4; //如果AB的模小于AP的模, 那么p在线段AB的延长线上
else return 5; //p在线段AB上
}
}
int main()
{
NODE A, B, P;
cin >> A.x >> A.y;
cin >> B.x >> B.y;
cin >> P.x >> P.y;
if (dir(A, B, P) == 1) cout << "COUNTER_CLOCKWISE" << endl; //逆时针
else if (dir(A, B, P) == 2) cout << "CLOCKWISE" << endl; //顺时针
else if (dir(A, B, P) == 3) cout << "ONLINE_BACK" << endl; //反向延长线
else if (dir(A, B, P) == 4) cout << "ONLINE_FRONT" << endl; //延长线
else if (dir(A, B, P) == 5) cout << "ON_SEGMENT" << endl; //线段上
return 0;
}
如果觉得本文对你有启发, 不妨赞一下, 在精神上鼓励鼓励博主;
如果有不懂的地方, 可以在下方留言, 博主一看到便会马上回复;
如果发现本文有错误的地方, 欢迎指正。
参考书籍: 挑战程序设计竞赛2