Peano
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4
5#include <lang/assert.h>
6#include <lang/type.h>
7#include <lang/numvec.h>
8#include <lang/math.h>
9
10template<Dimensionality dim, Precision fp>
11class Point : public NumVec<fp, dim::N> {
12public:
13 using D = dim;
14 using P = fp;
15
16 Point() = default;
17
18 explicit Point(fp val) : NumVec<fp, dim::N>(val) {}
19
20 Point(std::initializer_list<fp> list) : NumVec<fp, dim::N>(list) {}
21
22 explicit Point(const fp(&list)[dim::N]) : NumVec<fp, dim::N>(list) {}
23
24 Point(const Point &other) : NumVec<fp, dim::N>(other) {}
25
26 Point(const NumVec<fp, dim::N> &other) : NumVec<fp, dim::N>(other) {}
27
28 fp distance(const Point &p) const {
29 auto diff = p - *this;
30 auto diff2 = diff * diff;
31 auto dist = std::sqrt(diff2.sum());
32 return dist;
33 }
34};
35
36template<Dimensionality dim, Precision fp, bool topBoundaryInclusive = false>
37struct Region {
38private:
39 bool _betweenIn(const fp min, const fp val, const fp max) const {
40 return (min <= val) & (val <= max);
41 }
42
43 bool _betweenEx(const fp min, const fp val, const fp max) const {
44 return (min <= val) & (val < max);
45 }
46
47 bool between(const fp min, const fp val, const fp max) const {
48 if (topBoundaryInclusive) return this->_betweenIn(min, val, max);
49 else return this->_betweenEx(min, val, max);
50 }
51
52public:
53 using D = dim;
54 using P = fp;
55
57
60
61 static Region fromInclusiveBounds(const Point &low, const Point &high) {
62 auto highEx = high;
63 for (i32 axis = 0; axis < dim::N; axis++) {
64 highEx[axis] = std::nexttoward(highEx[axis], highEx[axis] + 1);
65 }
66 return Region(low, highEx);
67 }
68
69 bool operator==(const Region &r) const {
70 return this->low == r.low & this->high == r.high;
71 }
72
73 bool operator!=(const Region &r) const {
74 return this->low != r.low | this->high != r.high;
75 }
76
77 P size() const {
78 auto delta = this->high - this->low;
79
80 P size = 1;
81
82 for (i32 i = 0; i < dim::N; i++) {
83 size *= delta[i];
84 }
85
86 return size;
87 }
88
89 bool contains(const Point &p) const {
90 bool result = true;
91 for (i32 i = 0; i < dim::N; i++) {
92 result &= between(this->low[i], p[i], this->high[i]);
93 }
94 return result;
95 }
96
97 bool containsEx(const Point &p) const {
98 bool result = true;
99 for (i32 i = 0; i < dim::N; i++) {
100 result &= _betweenIn(this->low[i], p[i], this->high[i]);
101 }
102 return result;
103 }
104
106 auto result = NumVec<i32, dim::N>(0);
107
108 for (i32 i = 0; i < dim::N; i++) {
109 result[i] = -1 * !between(this->low[i], p[i], this->high[i]);
110 }
111
112 return result;
113 }
114
115 // https://silentmatt.com/rectangle-intersection/
116 bool overlaps(const Region &r) const {
117 bool res = true;
118 for (i32 i = 0; i < dim::N; i++) {
119 res &= this->low[i] < r.high[i] & this->high[i] > r.low[i];
120 }
121 return res;
122 }
123
124 bool contains(const Region &r) const {
125 bool result = true;
126
127 for (i32 i = 0; i < dim::N; i++) {
128 auto lmin = this->low[i];
129 auto lmax = this->high[i];
130
131 auto rmin = r.low[i];
132 auto rmax = r.high[i];
133
134 if (topBoundaryInclusive) {
135 result &= between(lmin, rmin, lmax) & between(lmin, rmax, lmax);
136 } else {
137 result &= between(lmin, rmin, lmax) & ((lmin <= rmax) & (rmax <= lmax));
138 }
139 }
140
141 return result;
142 }
143
144 bool sharesBoundary(const Region &r) const {
145 auto lowDelta = this->low - r.low;
146 bool isLowZero = false;
147
148 for (u32 i = 0; i < D::N; i++) isLowZero |= lowDelta[i] == 0;
149
150 if (isLowZero) return true;
151
152 auto highDelta = this->high - r.high;
153
154 bool isHighZero = false;
155 for (u32 i = 0; i < D::N; i++) isHighZero |= highDelta[i] == 0;
156
157 if (isHighZero) return true;
158
159 return false;
160 }
161
162 Region intersection(const Region &r) const {
163 Point iLow, iHigh;
164
165 for (i32 i = 0; i < dim::N; i++) {
166 iLow[i] = std::max(this->low[i], r.low[i]);
167 iHigh[i] = std::min(this->high[i], r.high[i]);
168 }
169
170 bool valid = true;
171
172 for (int i = 0; i < dim::N; i++) {
173 valid &= iLow[i] < iHigh[i];
174 }
175
176 if (valid) return Region{iLow, iHigh};
177 else return Region{Point{}, Point{}};
178 }
179
180 Point centre() const {
181 return (this->low + this->high) / 2;
182 }
183
184 void split(u32 n, Region *regions) const {
185 Point inc;
186
187 for (i32 i = 0; i < dim::N; i++) {
188 inc[i] = (this->high[i] - this->low[i]) / n;
189 }
190
191 for (u32 i = 0; i < (u32) std::pow(n, dim::N); i++) {
192 Point pLow = this->low;
193 Point pHigh = this->low;
194
195 for (u32 d = 0; d < dim::N; d++) {
196 auto didx = (i / (u32) std::pow(n, d)) % n;
197 pLow[d] += inc[d] * didx;
198 pHigh[d] += inc[d] * (didx + 1);
199 }
200
201 regions[i] = Region{pLow, pHigh};
202 }
203 }
204
205 u32 splitIdx(u32 n, const Point &p) const {
206 if (n == 2) {
207 auto center = this->low + (this->high - this->low) / 2;
208
209 u32 idx = 0;
210
211 for (u32 d = 0; d < dim::N; d++) {
212 idx += (center[d] <= p[d]) * std::pow(n, d);
213 }
214
215 return idx;
216 }
217
218 auto pnorm = (p - this->low) / (this->high - this->low);
219
220 auto pidx = (pnorm * n).floor();
221
222 u32 idx = 0;
223 for (u32 d = 0; d < dim::N; d++) {
224 idx += pidx[d] * std::pow(n, d);
225 }
226
227 assert(idx < std::pow(n, dim::N))
228 return idx;
229 }
230
231 friend std::ostream &operator<<(std::ostream &stream, const Region &value) {
232 stream << "{ L:" << value.low << " H:" << value.high << " }";
233 return stream;
234 }
235};
236
237template<typename dim, typename fp, bool topBoundaryInclusive = false> requires Dimensionality<dim> and Precision<fp>
238struct Geometry {
239 using D = dim;
240 using P = fp;
241
244
246
248
249 static constexpr u32 TwoPowerN() { return PowerN<2>(); }
250
251 template<u32 N>
252 static constexpr u32 PowerN() { return pow_constexpr(N, D::N); }
253};
#define assert(...)
Definition LinuxAMD.h:28
Point(const Point &other)
Definition geometry.h:24
Point(fp val)
Definition geometry.h:18
fp P
Definition geometry.h:14
dim D
Definition geometry.h:13
Point(const NumVec< fp, dim::N > &other)
Definition geometry.h:26
Point()=default
Point(const fp(&list)[dim::N])
Definition geometry.h:22
Point(std::initializer_list< fp > list)
Definition geometry.h:20
fp distance(const Point &p) const
Definition geometry.h:28
const float r
Definition hydro_iact.h:68
constexpr T pow_constexpr(T val, T exp)
Definition math.h:8
static constexpr u32 TwoPowerN()
Definition geometry.h:249
static constexpr u32 PowerN()
Definition geometry.h:252
Point low
Definition geometry.h:58
void split(u32 n, Region *regions) const
Definition geometry.h:184
bool containsEx(const Point &p) const
Definition geometry.h:97
friend std::ostream & operator<<(std::ostream &stream, const Region &value)
Definition geometry.h:231
Region intersection(const Region &r) const
Definition geometry.h:162
bool overlaps(const Region &r) const
Definition geometry.h:116
static Region fromInclusiveBounds(const Point &low, const Point &high)
Definition geometry.h:61
NumVec< i32, dim::N > containsAxis(const Point &p) const
Definition geometry.h:105
bool contains(const Point &p) const
Definition geometry.h:89
Point centre() const
Definition geometry.h:180
P size() const
Definition geometry.h:77
Point high
Definition geometry.h:59
bool _betweenEx(const fp min, const fp val, const fp max) const
Definition geometry.h:43
u32 splitIdx(u32 n, const Point &p) const
Definition geometry.h:205
fp P
Definition geometry.h:54
bool sharesBoundary(const Region &r) const
Definition geometry.h:144
bool operator!=(const Region &r) const
Definition geometry.h:73
bool operator==(const Region &r) const
Definition geometry.h:69
bool contains(const Region &r) const
Definition geometry.h:124
bool _betweenIn(const fp min, const fp val, const fp max) const
Definition geometry.h:39
dim D
Definition geometry.h:53
bool between(const fp min, const fp val, const fp max) const
Definition geometry.h:47
std::uint32_t u32
Definition type.h:11
std::int32_t i32
Definition type.h:10