GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 17.6% 12 / 0 / 68
Functions: 100.0% 3 / 0 / 3
Branches: 100.0% 12 / 0 / 12

geometry/point.hpp
Line Branch Exec Source
1 #pragma once
2
3 #include <complex>
4 #include <tuple>
5 #include <iostream>
6 #include <numeric>
7
8 template <typename T, typename AreaT=T> struct Point {
9 public:
10 T x, y;
11 3331997 Point() : x(0), y(0) {}
12 130742101 Point(T x_, T y_) : x(x_), y(y_) {}
13 template <typename U, typename V> explicit Point(const Point<U, V>& p) : x(p.x), y(p.y) {}
14 Point(const std::pair<T, T>& p) : x(p.first), y(p.second) {}
15 Point(const std::complex<T>& p) : x(real(p)), y(imag(p)) {}
16 explicit operator std::pair<T, T> () const { return std::pair<T, T>(x, y); }
17 explicit operator std::complex<T> () const { return std::complex<T>(x, y); }
18 auto as_pair() const { return std::pair<T, T>(*this); }
19 auto as_complex() const { return std::complex<T>(*this); }
20
21 friend std::ostream& operator << (std::ostream& o, const Point& p) { return o << '(' << p.x << ',' << p.y << ')'; }
22 3331997 friend std::istream& operator >> (std::istream& i, Point& p) { return i >> p.x >> p.y; }
23
8/8
✓ Branch 2 → 3 taken 4640300 times.
✓ Branch 2 → 4 taken 60730740 times.
✓ Branch 3 → 4 taken 87 times.
✓ Branch 3 → 5 taken 4640213 times.
✓ Branch 5 → 6 taken 4638812 times.
✓ Branch 5 → 7 taken 60732228 times.
✓ Branch 6 → 7 taken 73 times.
✓ Branch 6 → 8 taken 4638739 times.
126101867 friend bool operator == (const Point& a, const Point& b) { return a.x == b.x && a.y == b.y; }
24 friend bool operator != (const Point& a, const Point& b) { return !(a==b); }
25
26 Point operator + () const { return Point(+x, +y); }
27 Point operator - () const { return Point(-x, -y); }
28
29 Point& operator += (const Point& p) { x += p.x, y += p.y; return *this; }
30 Point& operator -= (const Point& p) { x -= p.x, y -= p.y; return *this; }
31 Point& operator *= (const T& t) { x *= t, y *= t; return *this; }
32 Point& operator /= (const T& t) { x /= t, y /= t; return *this; }
33
34 friend Point operator + (const Point& a, const Point& b) { return Point(a.x+b.x, a.y+b.y); }
35 friend Point operator - (const Point& a, const Point& b) { return Point(a.x-b.x, a.y-b.y); }
36 friend Point operator * (const Point& a, const T& t) { return Point(a.x*t, a.y*t); }
37 friend Point operator * (const T& t ,const Point& a) { return Point(t*a.x, t*a.y); }
38 friend Point operator / (const Point& a, const T& t) { return Point(a.x/t, a.y/t); }
39
40 AreaT dist2() const { return AreaT(x) * AreaT(x) + AreaT(y) * AreaT(y); }
41 auto dist() const { return std::sqrt(dist2()); }
42 Point unit() const { return *this / this->dist(); }
43 auto angle() const { return std::atan2(y, x); }
44
45 T int_norm() const { return std::gcd(x,y); }
46 Point int_unit() const { if (!x && !y) return *this; return *this / this->int_norm(); }
47
48 // Convenient free-functions, mostly for generic interop
49 friend auto norm(const Point& a) { return a.dist2(); }
50 friend auto abs(const Point& a) { return a.dist(); }
51 friend auto unit(const Point& a) { return a.unit(); }
52 friend auto arg(const Point& a) { return a.angle(); }
53 friend auto int_norm(const Point& a) { return a.int_norm(); }
54 friend auto int_unit(const Point& a) { return a.int_unit(); }
55
56 Point perp_cw() const { return Point(y, -x); }
57 Point perp_ccw() const { return Point(-y, x); }
58
59 18497507 friend AreaT dot(const Point& a, const Point& b) { return AreaT(a.x) * AreaT(b.x) + AreaT(a.y) * AreaT(b.y); }
60 193085463 friend AreaT cross(const Point& a, const Point& b) { return AreaT(a.x) * AreaT(b.y) - AreaT(a.y) * AreaT(b.x); }
61 friend AreaT cross3(const Point& a, const Point& b, const Point& c) { return cross(b-a, c-a); }
62
63 // Complex numbers and rotation
64 friend Point conj(const Point& a) { return Point(a.x, -a.y); }
65
66 // Returns conj(a) * b
67 friend Point dot_cross(const Point& a, const Point& b) { return Point(dot(a, b), cross(a, b)); }
68 friend Point cmul(const Point& a, const Point& b) { return dot_cross(conj(a), b); }
69 friend Point cdiv(const Point& a, const Point& b) { return dot_cross(b, a) / b.dist2(); }
70
71 // Must be a unit vector; otherwise multiplies the result by abs(u)
72 Point rotate(const Point& u) const { return dot_cross(conj(u), *this); }
73 Point unrotate(const Point& u) const { return dot_cross(u, *this); }
74
75 friend bool lex_less(const Point& a, const Point& b) {
76 return std::tie(a.x, a.y) < std::tie(b.x, b.y);
77 }
78
79 friend bool same_dir(const Point& a, const Point& b) { return cross(a,b) == 0 && dot(a,b) > 0; }
80
81 // check if 180 <= s..t < 360
82
2/2
✓ Branch 2 → 3 taken 112244573 times.
✓ Branch 2 → 4 taken 18497507 times.
130742080 friend bool is_reflex(const Point& a, const Point& b) { auto c = cross(a,b); return c ? (c < 0) : (dot(a, b) < 0); }
83
84 // operator < (s,t) for angles in [base,base+2pi)
85 friend bool angle_less_from(const Point& base, const Point& s, const Point& t) {
86 int r = is_reflex(base, s) - is_reflex(base, t);
87 return r ? (r < 0) : (0 < cross(s, t));
88 }
89 // operator < (s,t) for angles in (base,base+2pi]
90 65371040 friend bool angle_less_upto(const Point& base, const Point& s, const Point& t) {
91 65371040 int r = is_reflex(t, base) - is_reflex(s, base);
92
2/2
✓ Branch 2 → 3 taken 3027657 times.
✓ Branch 2 → 4 taken 62343383 times.
65371040 return r ? (r < 0) : (0 < cross(s, t));
93 }
94
95 friend auto angle_cmp_from(const Point& base) {
96 return [base](const Point& s, const Point& t) { return angle_less_from(base, s, t); };
97 }
98 21 friend auto angle_cmp_upto(const Point& base) {
99 65371040 return [base](const Point& s, const Point& t) { return angle_less_upto(base, s, t); };
100 }
101 friend auto angle_cmp_center_from(const Point& center, const Point& dir) {
102 return [center, dir](const Point& s, const Point& t) -> bool { return angle_less_from(dir, s-center, t-center); };
103 }
104 friend auto angle_cmp_center_upto(const Point& center, const Point& dir) {
105 return [center, dir](const Point& s, const Point& t) -> bool { return angle_less_upto(dir, s-center, t-center); };
106 }
107
108 // is p in [s,t] taken ccw? 1/0/-1 for in/border/out
109 friend int angle_between(const Point& s, const Point& t, const Point& p) {
110 if (same_dir(p, s) || same_dir(p, t)) return 0;
111 return angle_less_from(s, p, t) ? 1 : -1;
112 }
113 };
114