-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCounter_Clockwise.cpp
More file actions
206 lines (184 loc) · 4.97 KB
/
Counter_Clockwise.cpp
File metadata and controls
206 lines (184 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <bits/stdc++.h>
using namespace std;
typedef long long llong;
// 二次元座標を表す構造体
// ベクトル演算も扱う
struct Point
{
double x;
double y;
enum PositonRelate {
COUNTER_CLOCKWISE = 1,
CLOCKWISE,
ONLINE_BACK,
ONLINE_FRONT,
ON_SEGMENT,
NONE,
};
Point () {
x = 0;
y = 0;
}
Point(double px, double py) {
x = px;
y = py;
}
Point operator+(Point p2)
{
Point P_Add = Point(0, 0);
P_Add.x = x + p2.x;
P_Add.y = y + p2.y;
return P_Add;
}
Point operator-(Point p2)
{
Point P_Min = Point(0, 0);
P_Min.x = x - p2.x;
P_Min.y = y - p2.y;
return P_Min;
}
// 自身をスカラー倍する
Point operator*(double scal)
{
x *= scal;
y *= scal;
return Point(x,y);
}
// 自身との内積を計算する
double InnerProduct(Point p2)
{
return (x*p2.x + y*p2.y);
}
// 2点のベクトルの外積を計算する
double OuterProduct(Point p2)
{
return (x*p2.y - y*p2.x);
}
// 自身のノルム(大きさの2乗)を返す
double Norm()
{
return x*x + y*y;
}
// 自身のベクトルの大きさを返す
double Magnitude()
{
return sqrt(Norm());
}
// 自身を始点として点p2となす線分に、
// 点p3を射影した時の座標を求める
Point Projection(Point p2, Point p3)
{
// 始点p1→p3へのベクトル
Vector vec1(p3.x - x, p3.y - y);
// 始点p1→p2へのベクトル
Vector vec2(p2.x - x, p2.y - y);
double tmp = vec2.InnerProduct(vec1) / vec2.Norm();
return Point(x, y) + vec2 * tmp;
}
// 自身を始点として点p2となす線分に対して
// 点p3と線対称になる点の座標を求める
Point Reflection(Point p2, Point p3)
{
// 点p3から線分上に射影した点までのベクトル
Vector vec1 = Projection(p2, p3) - p3;
return p3 + vec1 * 2;
}
// 自身ともう一点の距離を求める
double CalcDistancePtoP(Point p)
{
Point tmp = p - Point(x, y);
return tmp.Magnitude();
}
// 自身と2点を通る直線間の距離を求める
double CalcDistanceLineToP(Point p2, Point p3)
{
Point tmp = Point(x, y);
Vector vec1 = p3-p2;
Vector vec2 = tmp - p2;
return vec1.OuterProduct(vec2) / vec1.Magnitude();
}
// 自身と2点を通る線分間の距離を求める
double CalcDistanceSegmentToP(Point p2, Point p3)
{
Point p = Point(x, y);
if((p3-p2).InnerProduct(p-p2) < 0.0) return (p-p2).Magnitude();
if((p2-p3).InnerProduct(p-p3) < 0.0) return (p-p3).Magnitude();
return p.CalcDistanceLineToP(p2, p3);
}
// 自身と他の2点の位置関係を調べる
PositonRelate JudgePosition3Points(Point p2, Point p3)
{
// 外積・内積を利用して3点の位置関係を調べる
Point p1 = Point(x, y);
Vector vec1 = p2-p1;
Vector vec2 = p3-p1;
double res_outer = vec1.OuterProduct(vec2);
double res_inner = vec1.InnerProduct(vec2);
// 反時計回り
if (res_outer > 0)
{
return COUNTER_CLOCKWISE;
}
// 時計回り
else if (res_outer < 0)
{
return CLOCKWISE;
}
// p3→p1→p2の順番で一直線上
else if (res_inner < 0)
{
return ONLINE_BACK;
}
// p1→p1→p3の順番で一直線上
else if (res_inner >= 0 && vec1.Magnitude() < vec2.Magnitude())
{
return ONLINE_FRONT;
}
// p3線分p1p2上に存在する
else if (res_inner >= 0 && vec1.Magnitude() >= vec2.Magnitude())
{
return ON_SEGMENT;
} else {
return NONE;
}
}
using Vector = Point;
using Line = Point;
};
int main() {
int x1(0), y1(0), x2(0), y2(0);
cin >> x1 >> y1 >> x2 >> y2;
Point p1(x1, y1);
Point p2(x2, y2);
int q(0);
cin >> q;
for (int i = 0; i < q; i++)
{
int x(0),y(0);
cin >> x >> y;
Point p3(x,y);
Point::PositonRelate res = p1.JudgePosition3Points(p2, p3);
switch (res)
{
case Point::COUNTER_CLOCKWISE:
cout << "COUNTER_CLOCKWISE" << "\n";
break;
case Point::CLOCKWISE:
cout << "CLOCKWISE" << "\n";
break;
case Point::ONLINE_BACK:
cout << "ONLINE_BACK" << "\n";
break;
case Point::ONLINE_FRONT:
cout << "ONLINE_FRONT" << "\n";
break;
case Point::ON_SEGMENT:
cout << "ON_SEGMENT" << "\n";
break;
default:
;assert(0);
break;
}
}
return 0;
}