Counter-Clockwise
For given three points p0,p1,p2, print
COUNTER_CLOCKWISE
if p0,p1,p2 make a counterclockwise turn (1),
CLOCKWISE
if p0,p1,p2 make a clockwise turn (2),
ONLINE_BACK
if p2 is on a line p2,p0,p1 in this order (3),
ONLINE_FRONT
if p2 is on a line p0,p1,p2 in this order (4),
ON_SEGMENT
if p2 is on a segment p0p1 (5).
Input
xp0 yp0 xp1 yp1 q xp20 yp20 xp21 yp21 ... xp2q−1 yp2q−1
In the first line, integer coordinates of p0 and p1 are given. Then, q queries are given for integer coordinates of p2.
Output
For each query, print the above mentioned status.
Constraints
- 1 ≤ q ≤ 1000
- −10000 ≤ xi, yi ≤ 10000
- p0 and p1 are not identical.
Sample Input 1
0 0 2 0 2 -1 1 -1 -1
Sample Output 1
COUNTER_CLOCKWISE CLOCKWISE
Sample Input 2
0 0 2 0 3 -1 0 0 0 3 0
Sample Output 2
ONLINE_BACK ON_SEGMENT ONLINE_FRONT
题目大意:
给定多组数据,分别判断每组中的两个向量对应 5种不同的位置关系(如图)中的哪一种,并输出该种关系对应的名称。
题解:
牵扯到了如何判断向量共线,如何求向量模长以及如何求解两个向量夹角大于0 / 小于0 的知识点
根据叉乘的意义:
当 A, B 夹角大于 0 小于 180° 时 结果为正,此时 B向量 在 A向量 的 “上方” 也就是左边
同理可知当叉乘结果小于0 B向量 在 A向量的 “下方”,也就是右边。
而点乘的结果可以用于判断是否在反方向
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps = 1e-10;
int sign(double x)
{
if (fabs(x) < eps) return 0;
else if (x > 0) return 1;
return -1;
}
struct Point
{
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) { }
Point operator + (const Point& t) { return Point(x + t.x, y + t.y); }
Point operator - (const Point& t) { return Point(x - t.x, y - t.y); }
Point operator * (const double t) { return Point(x * t, y * t); }
Point operator / (const double t) { return Point(x / t, y / t); }
bool operator == (const Point& t) { return !sign(x - t.x) && !sign(y - t.y); }
};
typedef Point Vector;
Point O, A, B;
double cross(Vector A, Vector B)
{
return A.x * B.y - A.y * B.x;
}
double dot(Vector A, Vector B)
{
return A.x * B.x + A.y * B.y;
}
bool to_left_test(Vector A, Vector B) // A 是否在 B 的左边
{
return cross(B, A) > 0;
}
double norm(Vector A)
{
return sqrt(dot(A, A));
}
int main()
{
cin >> O.x >> O.y >> A.x >> A.y;
int p;
cin >> p;
while (p--)
{
cin >> B.x >> B.y;
Vector v1 = B - O, v2 = A - O;
if (sign(cross(B - O, A - O)) == 0)
{
if (dot(v1, v2) < -eps) puts("ONLINE_BACK");
else if (norm(v1) <= norm(v2)) puts("ON_SEGMENT");
else puts("ONLINE_FRONT");
}
else
{
if (to_left_test(v1, v2))puts("COUNTER_CLOCKWISE");
else puts("CLOCKWISE");
}
}
return 0;
}