33 template<
size_t DIM,
typename T,
class DERIVED>
36 static constexpr
size_t dimension = DIM;
39 using range_t = std::array<point_t, 2>;
42 static constexpr
size_t bits_ =
sizeof(int_t) * 8;
46 static constexpr
size_t max_value_ = int_t(1) << (max_depth_ - 1);
49 static double min_, scale_;
50 static range_t range_;
57 static size_t max_depth() {
62 static constexpr DERIVED
min() {
63 return DERIVED(int_t(1) << max_depth_ * dimension);
66 static constexpr DERIVED
max() {
67 int_t
id = ~static_cast<int_t>(0);
68 for(
size_t i = max_depth_ * dimension + 1; i < bits_; ++i) {
74 static constexpr DERIVED
root() {
75 return DERIVED(int_t(1));
78 static constexpr DERIVED
null() {
83 return value_ == int_t(0);
89 while(
id >>= dimension)
95 assert(bits < int_t(1) << dimension);
102 value_ >>= dimension;
108 while(key_a != key_b) {
119 poped = value_ & ((1 << (dimension)) - 1);
120 assert(poped < (1 << dimension));
121 value_ >>= dimension;
127 poped = value_ & ((1 << (dimension)) - 1);
132 assert(d >=
depth());
133 value_ >>= d * dimension;
138 return DERIVED(value_ >> dimension);
147 value_ >>= (d - to_depth) * dimension;
151 if constexpr(dimension == 3) {
152 ostr << std::oct << value_ << std::dec;
158 while(
id !=
root()) {
160 output.insert(0, std::to_string(poped));
162 output.insert(output.begin(),
'1');
163 ostr << output.c_str();
174 return value_ == bid.value_;
178 return value_ <= bid.value_;
182 return value_ >= bid.value_;
186 return value_ > bid.value_;
190 return value_ < bid.value_;
194 return value_ != bid.value_;
197 operator int_t()
const {
204 template<
size_t D,
typename T,
class DER>
206 operator<<(std::ostream & ostr, const filling_curve<D, T, DER> & k) {
216 template<
size_t DIM,
typename T>
220 static constexpr
size_t dimension = DIM;
221 using coord_t = std::array<int_t, dimension>;
223 using range_t = std::array<point_t, 2>;
246 std::array<int_t, dimension> coords;
248 for(std::size_t i = 0; i < dimension; ++i) {
249 coords[i] = (p[i] - min_) / scale_ *
max_value_;
252 if constexpr(dimension == 1) {
254 value_ |= coords[0] >> dimension;
259 for(int_t mask =
max_value_ >> 1; mask > 0; mask >>= 1, --shift) {
260 std::array<bool, dimension> r;
261 if constexpr(dimension == 2) {
262 r = {!!(mask & coords[0]), !!(mask & coords[1])};
263 int_t bits = ((3 * r[0]) ^ r[1]);
264 value_ |= bits << (shift * 2);
265 rotation2d(mask, coords, r);
267 if constexpr(dimension == 3) {
268 r = {!!(mask & coords[0]), !!(mask & coords[1]), !!(mask & coords[2])};
269 int_t bits = (7 * r[0]) ^ (3 * r[1]) ^ r[2];
270 value_ |= bits << (shift * 3);
271 unrotation3d(mask, coords, r);
274 assert(value_ & int_t(1) << (
max_depth_ * dimension));
279 static void set_range(
const range_t & range) {
281 for(std::size_t i = 0; i < dimension; ++i) {
283 scale_ = range_[1][i] - min_;
290 std::array<int_t, dimension> coords = {};
291 for(int_t mask = int_t(1); mask <=
max_value_; mask <<= 1) {
292 std::array<bool, dimension> r = {};
293 if constexpr(dimension == 3) {
294 r[0] = (!!(key & 4));
295 r[1] = (!!(key & 2)) ^ r[0];
296 r[2] = (!!(key & 1)) ^ r[0] ^ r[1];
297 rotation3d(mask, coords, r);
298 coords[0] += r[0] * mask;
299 coords[1] += r[1] * mask;
300 coords[2] += r[2] * mask;
302 if constexpr(dimension == 2) {
303 r[0] = (!!(key & 2));
304 r[1] = (!!(key & 1)) ^ r[0];
306 rotation2d(mask, coords, r);
307 coords[0] += r[0] * mask;
308 coords[1] += r[1] * mask;
313 assert(key == int_t(1));
314 for(std::size_t j = 0; j < dimension; ++j) {
315 p[j] = min_ + scale_ *
static_cast<double>(coords[j]) /
max_value_ / 2;
325 void rotation2d(
const int_t & n,
326 std::array<int_t, dimension> & coords,
327 const std::array<bool, dimension> & bits) {
330 coords[0] = n - 1 - coords[0];
331 coords[1] = n - 1 - coords[1];
334 std::swap(coords[0], coords[1]);
338 void rotate_90_x(
const int_t & n, coord_t & coords) {
339 coord_t tmp = coords;
340 coords = {tmp[0], n - tmp[2] - 1, tmp[1]};
342 void rotate_90_y(
const int_t & n, coord_t & coords) {
343 coord_t tmp = coords;
344 coords = {tmp[2], tmp[1], n - tmp[0] - 1};
346 void rotate_90_z(
const int_t & n, coord_t & coords) {
347 coord_t tmp = coords;
348 coords = {n - tmp[1] - 1, tmp[0], tmp[2]};
350 void rotate_180_x(
const int_t & n, coord_t & coords) {
351 coord_t tmp = coords;
352 coords = {tmp[0], n - tmp[1] - 1, n - tmp[2] - 1};
354 void rotate_270_x(
const int_t & n, coord_t & coords) {
355 coord_t tmp = coords;
356 coords = {tmp[0], tmp[2], n - tmp[1] - 1};
358 void rotate_270_y(
const int_t & n, coord_t & coords) {
359 coord_t tmp = coords;
360 coords = {n - tmp[2] - 1, tmp[1], tmp[0]};
362 void rotate_270_z(
const int_t & n, coord_t & coords) {
363 coord_t tmp = coords;
364 coords = {tmp[1], n - tmp[0] - 1, tmp[2]};
367 void rotation3d(
const int_t & n,
369 const std::array<bool, dimension> & r) {
370 if(!r[0] && !r[1] && !r[2]) {
372 rotate_270_z(n, coords);
373 rotate_270_x(n, coords);
375 else if(!r[0] && r[2]) {
377 rotate_90_z(n, coords);
378 rotate_90_y(n, coords);
380 else if(r[1] && !r[2]) {
382 rotate_180_x(n, coords);
384 else if(r[0] && r[2]) {
386 rotate_270_z(n, coords);
387 rotate_270_y(n, coords);
389 else if(r[0] && !r[2] && !r[1]) {
391 rotate_90_y(n, coords);
392 rotate_90_z(n, coords);
396 void unrotation3d(
const int_t & n,
398 const std::array<bool, dimension> & r) {
399 if(!r[0] && !r[1] && !r[2]) {
401 rotate_90_x(n, coords);
402 rotate_90_z(n, coords);
404 else if(!r[0] && r[2]) {
406 rotate_270_y(n, coords);
407 rotate_270_z(n, coords);
409 else if(r[1] && !r[2]) {
411 rotate_180_x(n, coords);
413 else if(r[0] && r[2]) {
415 rotate_90_y(n, coords);
416 rotate_90_z(n, coords);
418 else if(r[0] && !r[2] && !r[1]) {
420 rotate_270_z(n, coords);
421 rotate_270_y(n, coords);
430 template<
size_t DIM,
typename T>
435 static constexpr
size_t dimension = DIM;
436 using coord_t = std::array<int_t, dimension>;
438 using range_t = std::array<point_t, 2>;
461 std::array<int_t, dimension> coords;
462 for(
size_t i = 0; i < dimension; ++i) {
464 (p[i] - min_) / scale_ * (int_t(1) << (bits_ - 1) / dimension);
468 for(
size_t j = 0; j < dimension; ++j) {
469 int_t bit = (coords[j] & int_t(1) << i) >> i;
470 value_ |= bit << (k * dimension + j);
476 static void set_range(
const range_t & range) {
478 for(std::size_t i = 0; i < dimension; ++i) {
480 scale_ = range_[1][i] - min_;
486 std::array<int_t, dimension> coords;
487 coords.fill(int_t(0));
490 while(
id >> dimension != int_t(0)) {
491 for(
size_t j = 0; j < dimension; ++j) {
492 coords[j] |= (((int_t(1) << j) &
id) >> j) << d;
497 constexpr int_t m = (int_t(1) <<
max_depth_) - 1;
498 for(
size_t j = 0; j < dimension; ++j) {
500 p[j] = min_ + scale_ *
static_cast<double>(coords[j]) / m;
511 template<
size_t DIM,
typename T,
class DERIVED>
513 template<
size_t DIM,
typename T,
class DERIVED>
514 typename filling_curve<DIM, T, DERIVED>::range_t
516 template<
size_t DIM,
typename T,
class DERIVED>
int pop_value()
Pop and return the digit popped.
Definition: filling_curve.hh:116
Definition: filling_curve.hh:217
int last_value()
Return the last digit of the key.
Definition: filling_curve.hh:125
void pop(size_t d)
Pop the depth d bits from the end of this key.
Definition: filling_curve.hh:131
static constexpr size_t max_depth_
Maximum number of bits.
Definition: filling_curve.hh:43
static constexpr DERIVED max()
Biggest value possible at max_depth considering the root.
Definition: filling_curve.hh:66
constexpr bool is_null() const
Definition: filling_curve.hh:82
hilbert_curve(const point_t &p, const size_t depth)
Definition: filling_curve.hh:243
void truncate(size_t to_depth)
Truncate this key until it is of depth to_depth.
Definition: filling_curve.hh:142
static constexpr DERIVED min()
Smallest value possible at max_depth considering the root.
Definition: filling_curve.hh:62
Definition: filling_curve.hh:431
void pop()
Definition: filling_curve.hh:100
static constexpr size_t max_value_
Definition: filling_curve.hh:47
morton_curve(const point_t &p, const size_t depth)
Morton key can be generated directly up to the right depth.
Definition: filling_curve.hh:458
static constexpr DERIVED null()
Definition: filling_curve.hh:78
Definition: dimensioned_array.hh:58
void coordinates(point_t &p)
Definition: filling_curve.hh:485
void output_(std::ostream &ostr) const
Output a key using oct in 3d and poping values for 2 and 1D.
Definition: filling_curve.hh:150
Definition: filling_curve.hh:34
size_t depth() const
Definition: filling_curve.hh:86
int conflict_depth(filling_curve key_a, filling_curve key_b)
Search for the depth were two keys are in conflict.
Definition: filling_curve.hh:106
int_t value() const
Get the value associated to this key.
Definition: filling_curve.hh:167
static constexpr DERIVED root()
Definition: filling_curve.hh:74
void coordinates(point_t &p)
Definition: filling_curve.hh:288
virtual void coordinates(point_t &)
Convert this key to coordinates in range.
Definition: filling_curve.hh:171
void push(int_t bits)
Definition: filling_curve.hh:94
constexpr filling_curve parent() const
Return the parent of this key (depth - 1)
Definition: filling_curve.hh:137
Definition: control.hh:31