Skip to content

Commit d20e460

Browse files
committed
updated mirror in Flat Geometry
1 parent 2ce2d59 commit d20e460

1 file changed

Lines changed: 68 additions & 57 deletions

File tree

src/jiangly/math/09A-Flat-Geometry.hpp

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/** 平面几何(Point)
22
* 2023-09-22: https://qoj.ac/submission/185408
3-
**/
4-
template<class T>
3+
**/
4+
template <class T>
55
struct Point {
66
T x;
77
T y;
88
Point(const T &x_ = 0, const T &y_ = 0) : x(x_), y(y_) {}
9-
10-
template<class U>
9+
10+
template <class U>
1111
operator Point<U>() {
1212
return Point<U>(U(x), U(y));
1313
}
@@ -60,59 +60,59 @@ struct Point {
6060
}
6161
};
6262

63-
template<class T>
63+
template <class T>
6464
struct Line {
6565
Point<T> a;
6666
Point<T> b;
6767
Line(const Point<T> &a_ = Point<T>(), const Point<T> &b_ = Point<T>()) : a(a_), b(b_) {}
6868
};
6969

70-
template<class T>
70+
template <class T>
7171
T dot(const Point<T> &a, const Point<T> &b) {
7272
return a.x * b.x + a.y * b.y;
7373
}
7474

75-
template<class T>
75+
template <class T>
7676
T cross(const Point<T> &a, const Point<T> &b) {
7777
return a.x * b.y - a.y * b.x;
7878
}
7979

80-
template<class T>
80+
template <class T>
8181
T square(const Point<T> &p) {
8282
return dot(p, p);
8383
}
8484

85-
template<class T>
85+
template <class T>
8686
double length(const Point<T> &p) {
8787
return std::sqrt(square(p));
8888
}
8989

90-
template<class T>
90+
template <class T>
9191
double length(const Line<T> &l) {
9292
return length(l.a - l.b);
9393
}
9494

95-
template<class T>
95+
template <class T>
9696
Point<T> normalize(const Point<T> &p) {
9797
return p / length(p);
9898
}
9999

100-
template<class T>
100+
template <class T>
101101
bool parallel(const Line<T> &l1, const Line<T> &l2) {
102102
return cross(l1.b - l1.a, l2.b - l2.a) == 0;
103103
}
104104

105-
template<class T>
105+
template <class T>
106106
double distance(const Point<T> &a, const Point<T> &b) {
107107
return length(a - b);
108108
}
109109

110-
template<class T>
110+
template <class T>
111111
double distancePL(const Point<T> &p, const Line<T> &l) {
112112
return std::abs(cross(l.a - l.b, l.a - p)) / length(l);
113113
}
114114

115-
template<class T>
115+
template <class T>
116116
double distancePS(const Point<T> &p, const Line<T> &l) {
117117
if (dot(p - l.a, l.b - l.a) < 0) {
118118
return distance(p, l.a);
@@ -123,41 +123,40 @@ double distancePS(const Point<T> &p, const Line<T> &l) {
123123
return distancePL(p, l);
124124
}
125125

126-
template<class T>
126+
template <class T>
127127
Point<T> rotate(const Point<T> &a) {
128128
return Point(-a.y, a.x);
129129
}
130130

131-
template<class T>
131+
template <class T>
132132
int sgn(const Point<T> &a) {
133133
return a.y > 0 || (a.y == 0 && a.x > 0) ? 1 : -1;
134134
}
135135

136-
template<class T>
136+
template <class T>
137137
bool pointOnLineLeft(const Point<T> &p, const Line<T> &l) {
138138
return cross(l.b - l.a, p - l.a) > 0;
139139
}
140140

141-
template<class T>
141+
template <class T>
142142
Point<T> lineIntersection(const Line<T> &l1, const Line<T> &l2) {
143143
return l1.a + (l1.b - l1.a) * (cross(l2.b - l2.a, l1.a - l2.a) / cross(l2.b - l2.a, l1.a - l1.b));
144144
}
145145

146-
template<class T>
146+
template <class T>
147147
bool pointOnSegment(const Point<T> &p, const Line<T> &l) {
148-
return cross(p - l.a, l.b - l.a) == 0 && std::min(l.a.x, l.b.x) <= p.x && p.x <= std::max(l.a.x, l.b.x)
149-
&& std::min(l.a.y, l.b.y) <= p.y && p.y <= std::max(l.a.y, l.b.y);
148+
return cross(p - l.a, l.b - l.a) == 0 && std::min(l.a.x, l.b.x) <= p.x && p.x <= std::max(l.a.x, l.b.x) && std::min(l.a.y, l.b.y) <= p.y && p.y <= std::max(l.a.y, l.b.y);
150149
}
151150

152-
template<class T>
151+
template <class T>
153152
bool pointInPolygon(const Point<T> &a, const std::vector<Point<T>> &p) {
154153
int n = p.size();
155154
for (int i = 0; i < n; i++) {
156155
if (pointOnSegment(a, Line(p[i], p[(i + 1) % n]))) {
157156
return true;
158157
}
159158
}
160-
159+
161160
int t = 0;
162161
for (int i = 0; i < n; i++) {
163162
auto u = p[i];
@@ -169,15 +168,15 @@ bool pointInPolygon(const Point<T> &a, const std::vector<Point<T>> &p) {
169168
t ^= 1;
170169
}
171170
}
172-
171+
173172
return t == 1;
174173
}
175174

176175
// 0 : not intersect
177176
// 1 : strictly intersect
178177
// 2 : overlap
179178
// 3 : intersect at endpoint
180-
template<class T>
179+
template <class T>
181180
std::tuple<int, Point<T>, Point<T>> segmentIntersection(const Line<T> &l1, const Line<T> &l2) {
182181
if (std::max(l1.a.x, l1.b.x) < std::min(l2.a.x, l2.b.x)) {
183182
return {0, Point<T>(), Point<T>()};
@@ -219,11 +218,11 @@ std::tuple<int, Point<T>, Point<T>> segmentIntersection(const Line<T> &l1, const
219218
auto cp2 = cross(l2.a - l1.b, l2.b - l1.b);
220219
auto cp3 = cross(l1.a - l2.a, l1.b - l2.a);
221220
auto cp4 = cross(l1.a - l2.b, l1.b - l2.b);
222-
221+
223222
if ((cp1 > 0 && cp2 > 0) || (cp1 < 0 && cp2 < 0) || (cp3 > 0 && cp4 > 0) || (cp3 < 0 && cp4 < 0)) {
224223
return {0, Point<T>(), Point<T>()};
225224
}
226-
225+
227226
Point p = lineIntersection(l1, l2);
228227
if (cp1 != 0 && cp2 != 0 && cp3 != 0 && cp4 != 0) {
229228
return {1, p, p};
@@ -232,15 +231,15 @@ std::tuple<int, Point<T>, Point<T>> segmentIntersection(const Line<T> &l1, const
232231
}
233232
}
234233

235-
template<class T>
234+
template <class T>
236235
double distanceSS(const Line<T> &l1, const Line<T> &l2) {
237236
if (std::get<0>(segmentIntersection(l1, l2)) != 0) {
238237
return 0.0;
239238
}
240239
return std::min({distancePS(l1.a, l2), distancePS(l1.b, l2), distancePS(l2.a, l1), distancePS(l2.b, l1)});
241240
}
242241

243-
template<class T>
242+
template <class T>
244243
bool segmentInPolygon(const Line<T> &l, const std::vector<Point<T>> &p) {
245244
int n = p.size();
246245
if (!pointInPolygon(l.a, p)) {
@@ -254,7 +253,7 @@ bool segmentInPolygon(const Line<T> &l, const std::vector<Point<T>> &p) {
254253
auto v = p[(i + 1) % n];
255254
auto w = p[(i + 2) % n];
256255
auto [t, p1, p2] = segmentIntersection(l, Line(u, v));
257-
256+
258257
if (t == 1) {
259258
return false;
260259
}
@@ -269,44 +268,37 @@ bool segmentInPolygon(const Line<T> &l, const std::vector<Point<T>> &p) {
269268
}
270269
} else {
271270
if (p1 != u && p1 != v) {
272-
if (pointOnLineLeft(l.a, Line(v, u))
273-
|| pointOnLineLeft(l.b, Line(v, u))) {
271+
if (pointOnLineLeft(l.a, Line(v, u)) || pointOnLineLeft(l.b, Line(v, u))) {
274272
return false;
275273
}
276274
} else if (p1 == v) {
277275
if (l.a == v) {
278276
if (pointOnLineLeft(u, l)) {
279-
if (pointOnLineLeft(w, l)
280-
&& pointOnLineLeft(w, Line(u, v))) {
277+
if (pointOnLineLeft(w, l) && pointOnLineLeft(w, Line(u, v))) {
281278
return false;
282279
}
283280
} else {
284-
if (pointOnLineLeft(w, l)
285-
|| pointOnLineLeft(w, Line(u, v))) {
281+
if (pointOnLineLeft(w, l) || pointOnLineLeft(w, Line(u, v))) {
286282
return false;
287283
}
288284
}
289285
} else if (l.b == v) {
290286
if (pointOnLineLeft(u, Line(l.b, l.a))) {
291-
if (pointOnLineLeft(w, Line(l.b, l.a))
292-
&& pointOnLineLeft(w, Line(u, v))) {
287+
if (pointOnLineLeft(w, Line(l.b, l.a)) && pointOnLineLeft(w, Line(u, v))) {
293288
return false;
294289
}
295290
} else {
296-
if (pointOnLineLeft(w, Line(l.b, l.a))
297-
|| pointOnLineLeft(w, Line(u, v))) {
291+
if (pointOnLineLeft(w, Line(l.b, l.a)) || pointOnLineLeft(w, Line(u, v))) {
298292
return false;
299293
}
300294
}
301295
} else {
302296
if (pointOnLineLeft(u, l)) {
303-
if (pointOnLineLeft(w, Line(l.b, l.a))
304-
|| pointOnLineLeft(w, Line(u, v))) {
297+
if (pointOnLineLeft(w, Line(l.b, l.a)) || pointOnLineLeft(w, Line(u, v))) {
305298
return false;
306299
}
307300
} else {
308-
if (pointOnLineLeft(w, l)
309-
|| pointOnLineLeft(w, Line(u, v))) {
301+
if (pointOnLineLeft(w, l) || pointOnLineLeft(w, Line(u, v))) {
310302
return false;
311303
}
312304
}
@@ -317,40 +309,40 @@ bool segmentInPolygon(const Line<T> &l, const std::vector<Point<T>> &p) {
317309
return true;
318310
}
319311

320-
template<class T>
312+
template <class T>
321313
std::vector<Point<T>> hp(std::vector<Line<T>> lines) {
322314
std::sort(lines.begin(), lines.end(), [&](auto l1, auto l2) {
323315
auto d1 = l1.b - l1.a;
324316
auto d2 = l2.b - l2.a;
325-
317+
326318
if (sgn(d1) != sgn(d2)) {
327319
return sgn(d1) == 1;
328320
}
329-
321+
330322
return cross(d1, d2) > 0;
331323
});
332-
324+
333325
std::deque<Line<T>> ls;
334326
std::deque<Point<T>> ps;
335327
for (auto l : lines) {
336328
if (ls.empty()) {
337329
ls.push_back(l);
338330
continue;
339331
}
340-
332+
341333
while (!ps.empty() && !pointOnLineLeft(ps.back(), l)) {
342334
ps.pop_back();
343335
ls.pop_back();
344336
}
345-
337+
346338
while (!ps.empty() && !pointOnLineLeft(ps[0], l)) {
347339
ps.pop_front();
348340
ls.pop_front();
349341
}
350-
342+
351343
if (cross(l.b - l.a, ls.back().b - ls.back().a) == 0) {
352344
if (dot(l.b - l.a, ls.back().b - ls.back().a) > 0) {
353-
345+
354346
if (!pointOnLineLeft(ls.back().a, l)) {
355347
assert(ls.size() == 1);
356348
ls[0] = l;
@@ -359,11 +351,11 @@ std::vector<Point<T>> hp(std::vector<Line<T>> lines) {
359351
}
360352
return {};
361353
}
362-
354+
363355
ps.push_back(lineIntersection(ls.back(), l));
364356
ls.push_back(l);
365357
}
366-
358+
367359
while (!ps.empty() && !pointOnLineLeft(ps.back(), ls[0])) {
368360
ps.pop_back();
369361
ls.pop_back();
@@ -372,11 +364,30 @@ std::vector<Point<T>> hp(std::vector<Line<T>> lines) {
372364
return {};
373365
}
374366
ps.push_back(lineIntersection(ls[0], ls.back()));
375-
367+
376368
return std::vector(ps.begin(), ps.end());
377369
}
378370

371+
template <class T>
372+
Point<T> mirror(const Line<T> &l, const Point<T> P) {
373+
Point<T> A(l.a.x, l.a.y);
374+
Point<T> B(l.b.x, l.b.y);
375+
376+
Point<T> v = B - A;
377+
T len2 = dot(v, v);
378+
379+
if (len2 == 0) {
380+
return Point<T>(2 * A.x - P.x, 2 * A.y - P.y);
381+
}
382+
383+
T t = dot(P - A, v) / len2;
384+
Point<T> proj = A + v * t;
385+
386+
// 对称点 = 投影点的关于 P 的镜像 = 2*proj - P
387+
return Point<T>(2.0 * proj.x - P.x, 2.0 * proj.y - P.y);
388+
}
389+
379390
using real = long double;
380391
using P = Point<real>;
381392

382-
constexpr real eps = 0;
393+
constexpr real eps = 0;

0 commit comments

Comments
 (0)