11/* * 平面几何(Point)
22 * 2023-09-22: https://qoj.ac/submission/185408
3- **/
4- template <class T >
3+ **/
4+ template <class T >
55struct 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 >
6464struct 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 >
7171T 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 >
7676T 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 >
8181T square (const Point<T> &p) {
8282 return dot (p, p);
8383}
8484
85- template <class T >
85+ template <class T >
8686double length (const Point<T> &p) {
8787 return std::sqrt (square (p));
8888}
8989
90- template <class T >
90+ template <class T >
9191double length (const Line<T> &l) {
9292 return length (l.a - l.b );
9393}
9494
95- template <class T >
95+ template <class T >
9696Point<T> normalize (const Point<T> &p) {
9797 return p / length (p);
9898}
9999
100- template <class T >
100+ template <class T >
101101bool 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 >
106106double distance (const Point<T> &a, const Point<T> &b) {
107107 return length (a - b);
108108}
109109
110- template <class T >
110+ template <class T >
111111double 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 >
116116double 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 >
127127Point<T> rotate (const Point<T> &a) {
128128 return Point (-a.y , a.x );
129129}
130130
131- template <class T >
131+ template <class T >
132132int 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 >
137137bool 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 >
142142Point<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 >
147147bool 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 >
153152bool 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 >
181180std::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 >
236235double 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 >
244243bool 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 >
321313std::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+
379390using real = long double ;
380391using P = Point<real>;
381392
382- constexpr real eps = 0 ;
393+ constexpr real eps = 0 ;
0 commit comments