UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
range_map.hpp
1
42#ifndef UFO_CONTAINER_RANGE_MAP_HPP
43#define UFO_CONTAINER_RANGE_MAP_HPP
44
45// UFO
46#include <ufo/core/range.hpp>
47
48namespace ufo
49{
50template <typename Key, typename T>
52{
53 // FIXME: Use std::piecewise_construct more
54
55 public:
56 //
57 // Tags
58 //
59
60 using key_type = Range<Key>;
61 using mapped_type = T;
62 // FIXME: Key should be const: using value_type = std::pair<key_type const,
63 // mapped_type>;
64 using value_type = std::pair<key_type, mapped_type>;
65 using size_type = typename std::vector<value_type>::size_type;
66 using difference_type = typename std::vector<value_type>::difference_type;
67 using key_compare = typename key_type::Comparator;
68 using allocator_type = typename std::vector<value_type>::allocator_type;
69 using reference = typename std::vector<value_type>::reference;
70 using const_reference = typename std::vector<value_type>::const_reference;
71 using pointer = typename std::vector<value_type>::pointer;
72 using const_pointer = typename std::vector<value_type>::const_pointer;
73 using iterator = typename std::vector<value_type>::iterator;
74 using const_iterator = typename std::vector<value_type>::const_iterator;
75 using reverse_iterator = typename std::vector<value_type>::reverse_iterator;
76 using const_reverse_iterator = typename std::vector<value_type>::const_reverse_iterator;
77 // FIXME: using node_type =
78 // FIXME: using insert_return_type =
79
80 //
81 // Value compare
82 //
83
85 using is_transparent = std::true_type;
86
87 // [[nodiscard]] constexpr bool operator()(value_type const& lhs,
88 // value_type const& rhs) const
89 // {
90 // return comp_(lhs.first, rhs.first);
91 // }
92
93 [[nodiscard]] constexpr bool operator()(typename key_compare::range_t lhs,
94 value_type const& rhs) const
95 {
96 return comp_(lhs, rhs.first);
97 }
98
99 [[nodiscard]] constexpr bool operator()(value_type const& lhs,
100 typename key_compare::range_t rhs)
101 {
102 return comp_(lhs.first, rhs);
103 }
104
105 protected:
106 key_compare comp_;
107 };
108
109 //
110 // Constructors
111 //
112
113 RangeMap() {}
114
115 template <class InputIt,
116 typename = std::enable_if_t<std::is_base_of_v<
117 std::input_iterator_tag,
118 typename std::iterator_traits<InputIt>::iterator_category>>>
119 RangeMap(InputIt first, InputIt last)
120 {
121 insert(first, last);
122 }
123
124 RangeMap(RangeMap const& other) : ranges_(other.ranges_) {}
125
126 template <typename Key2>
127 RangeMap(RangeMap<Key2, T> const& other)
128 {
129 // FIXME: Make sure it does not throw
130 insert(std::cbegin(other), std::cend(other));
131 }
132
133 RangeMap(RangeMap&& other) : ranges_(std::move(other.ranges_)) {}
134
135 RangeMap(std::initializer_list<value_type> init) { insert(init); }
136
137 //
138 // Destructor
139 //
140
141 ~RangeMap() {}
142
143 //
144 // Assignment operator
145 //
146
147 RangeMap& operator=(RangeMap const& other)
148 {
149 ranges_ = other.ranges_;
150 return *this;
151 }
152
153 template <typename Key2>
154 RangeMap& operator=(RangeMap<Key2, T> const& other)
155 {
156 // FIXME: Make sure it does not throw
157 clear();
158 insert(std::cbegin(other), std::cend(other));
159 return *this;
160 }
161
162 RangeMap& operator=(RangeMap&& other)
163 {
164 ranges_ = std::move(other.ranges_);
165 return *this;
166 }
167
168 RangeMap& operator=(std::initializer_list<value_type> ilist)
169 {
170 clear();
171 insert(ilist);
172 return *this;
173 }
174
175 //
176 // Get allocator
177 //
178
179 allocator_type get_allocator() const noexcept { return ranges_.get_allocator(); }
180
181 //
182 // Element access
183 //
184
185 // TODO: T& at()
186
187 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
188 [[nodiscard]] T const& get(K key)
189 {
190 auto it = find(key);
191 if (end() == it) {
192 throw std::out_of_range("Key is not stored in the container.");
193 }
194 return it->second;
195 }
196
197 //
198 // Iterators
199 //
200
201 iterator begin() noexcept { return std::begin(ranges_); }
202
203 const_iterator begin() const noexcept { return std::begin(ranges_); }
204
205 const_iterator cbegin() const noexcept { return std::cbegin(ranges_); }
206
207 iterator end() noexcept { return std::end(ranges_); }
208
209 const_iterator end() const noexcept { return std::end(ranges_); }
210
211 const_iterator cend() const noexcept { return std::cend(ranges_); }
212
213 reverse_iterator rbegin() noexcept { return std::rbegin(ranges_); }
214
215 const_reverse_iterator rbegin() const noexcept { return std::rbegin(ranges_); }
216
217 const_reverse_iterator crbegin() const noexcept { return std::crbegin(ranges_); }
218
219 reverse_iterator rend() noexcept { return std::rend(ranges_); }
220
221 const_reverse_iterator rend() const noexcept { return std::rend(ranges_); }
222
223 const_reverse_iterator crend() const noexcept { return std::crend(ranges_); }
224
225 //
226 // Capacity
227 //
228
229 [[nodiscard]] bool empty() const noexcept { return ranges_.empty(); }
230
231 [[nodiscard]] size_type size() const noexcept { return ranges_.size(); }
232
233 [[nodiscard]] size_type max_size() const noexcept { return ranges_.max_size(); }
234
235 [[nodiscard]] size_type numRanges() const noexcept { return size(); }
236
237 template <typename Key2 = Key>
238 [[nodiscard]] std::enable_if_t<std::is_integral_v<Key2>, size_type> numValues() const
239 {
240 return std::accumulate(begin(), end(), numRanges(), [](auto cur, auto elem) {
241 return cur + (elem.first.upper() - elem.first.lower());
242 });
243 }
244
245 //
246 // Modifiers
247 //
248
249 void clear() noexcept { ranges_.clear(); }
250
251 std::pair<iterator, bool> insert(value_type const& value)
252 {
253 std::cout << value.first.lower() << ' ' << value.first.upper() << '\n';
254 key_type key = value.first;
255
256 // Subtract one to easily determine if [lower, upper] should be combined
257 // with a range [X, lower - 1]. E.g., [8, 15] should be combined with [1, 7]
258 // to become [1, 15]. Also note the protection against underflow
259 Key const lower_up = decrement(key.lower());
260
261 // Add one to easily determine if [lower, upper] should be combined with a
262 // range [upper + 1, X]. E.g., [4, 15] should be combined with [16, 21] to
263 // become [4, 21]. Also note the protection against overflow
264 Key const upper_op = increment(key.upper());
265
266 auto [lower, upper] = equal_range(lower_up, key.upper());
267
268 if (end() == lower) {
269 std::cout << "1\n";
270 // Add new range to the end
271 // E.g., [21, 35] should be added at the end of [1, 4], [7, 15] to become
272 // [1, 4], [7, 15], [21, 35].
273 ranges_.push_back(value);
274 return {std::prev(end()), true};
275 } else if (lower == upper && upper_op < upper->first.lower()) {
276 std::cout << "2\n";
277 // Add new range to the front or middle
278 // E.g., [4, 7] should be added to the middle of [0, 2], [9, 24] to become
279 // [0, 2], [4, 7], [9, 24].
280 auto it = ranges_.insert(lower, value);
281 return {it, true};
282 }
283 std::cout << "3\n";
284
285 auto lower_dist = std::distance(begin(), lower);
286 auto upper_dist = std::distance(begin(), upper);
287
288 bool inserted = false;
289
290 // FIXME: Fix inserted
291
292 //
293 // Fix beginning
294 //
295
296 if (lower_up == lower->first.upper() && value.second != lower->second) {
297 auto lower_next = std::next(lower);
298 if (value.second == lower_next->second) {
299 // Extend
300 lower_next->first.setRange(key.lower(), lower_next->first.upper());
301 } else {
302 // Add
303 ranges_.emplace(lower_next, key_type(key.lower()), value.second);
304 ++upper_dist;
305 }
306 ++lower_dist;
307 } else if (key.lower() < lower->first.lower()) {
308 if (increment(key.lower()) < lower->first.lower() ||
309 value.second != lower->second) {
310 // Add
311 ranges_.emplace(lower, key_type(key.lower(), decrement(lower->first.lower())),
312 value.second);
313 ++upper_dist;
314 } else {
315 // Extend
316 lower->first.setRange(key.lower(), lower->first.upper());
317 }
318 }
319
320 lower = std::next(begin(), lower_dist);
321 upper = std::next(begin(), upper_dist);
322
323 //
324 // Fix end
325 //
326
327 auto upper_prev = std::prev(upper);
328
329 if (end() == upper) {
330 if (value.second == upper_prev->second) {
331 // Extend
332 upper_prev->first.setRange(upper_prev->first.lower(), key.upper());
333 --upper_dist;
334 } else {
335 // Add
336 ranges_.emplace_back(key_type(increment(upper_prev->first.upper()), key.upper()),
337 value.second);
338 }
339 } else if (key.upper() < upper->first.lower()) {
340 if (upper_op < upper->first.lower() || value.second != upper->second) {
341 // Add
342 ranges_.emplace(upper,
343 key_type(increment(upper_prev->first.upper()), key.upper()),
344 value.second);
345 } else {
346 // Extend
347 upper->first.setRange(key.upper(), upper->first.upper());
348 }
349 }
350
351 lower = std::next(begin(), lower_dist);
352 upper = std::next(begin(), upper_dist);
353
354 //
355 // Fix middle
356 //
357
358 for (auto it = lower; it != upper; ++it) {
359 if (value.second == it->second) {
360 continue;
361 }
362 auto it_next = std::next(it);
363 if (value.second == it_next->second) {
364 // Extend
365 it_next->first.setRange(increment(it->first.upper()), it_next->first.upper());
366 } else if (increment(it->first.upper()) <= decrement(it_next->first.lower())) {
367 // Add
368 ranges_.emplace(
369 it_next,
370 key_type(increment(it->first.upper()), decrement(it_next->first.lower())),
371 value.second);
372 ++upper_dist;
373 }
374 }
375
376 lower = std::next(begin(), lower_dist);
377 upper = std::next(begin(), upper_dist);
378
379 for (auto it = lower; it != std::prev(upper);) {
380 if (value.second != it->second) {
381 continue;
382 }
383 auto it_next = std::next(it);
384 if (value.second == it_next->second) {
385 // Combine ranges
386 it->first.setRange(it->first.lower(), it_next->first.upper());
387 it = erase(it_next);
388 std::prev(it);
389 --upper_dist;
390 upper = std::next(begin(), upper_dist);
391 } else {
392 // Extend current range
393 it->first.setRange(it->first.lower(), decrement(it_next->first.lower()));
394 ++it;
395 }
396 }
397
398 lower = std::next(begin(), lower_dist);
399 upper = std::next(begin(), upper_dist);
400
401 return {lower, inserted};
402 }
403
404 template <class P,
405 typename = std::enable_if_t<std::is_constructible_v<value_type, P&&>>>
406 std::pair<iterator, bool> insert(P&& value)
407 {
408 return emplace(std::forward<P>(value));
409 }
410
411 std::pair<iterator, bool> insert(value_type&& value)
412 {
413 key_type key = value.first;
414
415 // Subtract one to easily determine if [lower, upper] should be combined
416 // with a range [X, lower - 1]. E.g., [8, 15] should be combined with [1, 7]
417 // to become [1, 15]. Also note the protection against underflow
418 Key const lower_up = decrement(key.lower());
419
420 // Add one to easily determine if [lower, upper] should be combined with a
421 // range [upper + 1, X]. E.g., [4, 15] should be combined with [16, 21] to
422 // become [4, 21]. Also note the protection against overflow
423 Key const upper_op = increment(key.upper());
424
425 auto [lower, upper] = equal_range(lower_up, key.upper());
426
427 if (end() != lower && lower->first.upper() < key.lower() &&
428 value.second != lower->second) {
429 // To make sure that lower always points to the correct when returned.
430 // It functions the same without this, however the returned iterator will
431 // be one before the actual sometimes.
432 ++lower;
433 }
434
435 // Easy cases
436 if (end() == lower) {
437 // Add new range to the end
438 // E.g., [21, 35] should be added at the end of [1, 4], [7, 15] to become
439 // [1, 4], [7, 15], [21, 35].
440 ranges_.push_back(value);
441 return {std::prev(end()), true};
442 } else if (lower == upper) {
443 if (upper_op < lower->first.lower() ||
444 (key.upper() < lower->first.lower() && value.second != lower->second)) {
445 // Add new range to the front or middle
446 // E.g., [4, 7] should be added to the middle of [0, 2], [9, 24] to become
447 // [0, 2], [4, 7], [9, 24].
448 auto it = ranges_.insert(lower, value);
449 return {it, true};
450 } else if (value.second == lower->second) {
451 bool inserted = key.lower() < lower->first.lower();
452 lower->first.setRange(std::min(key.lower(), lower->first.lower()),
453 lower->first.upper());
454 return {lower, inserted};
455 } else if (key.lower() < lower->first.lower()) {
456 lower = ranges_.emplace(
457 lower, key_type(key.lower(), decrement(lower->first.lower())), value.second);
458 return {lower, true};
459 } else {
460 return {lower, false};
461 }
462 }
463
464 // Difficult cases
465 upper = end() != upper ? upper : std::prev(upper);
466
467 auto lower_dist = std::distance(begin(), lower);
468 auto upper_dist = std::distance(begin(), upper);
469
470 bool inserted = false;
471
472 // Fix lower
473 if (key.lower() < lower->first.lower()) {
474 inserted = true;
475 if (value.second == lower->second) {
476 // Extend
477 lower->first.setRange(key.lower(), lower->first.upper());
478 } else {
479 // Add
480 lower = ranges_.emplace(
481 lower, key_type(key.lower(), decrement(lower->first.lower())), value.second);
482 ++upper_dist;
483 upper = std::next(begin(), upper_dist);
484 }
485 }
486
487 // Fix upper
488 if (key.upper() > upper->first.upper()) {
489 inserted = true;
490 if (value.second == upper->second) {
491 // Extend
492 upper->first.setRange(upper->first.lower(), key.upper());
493 } else {
494 // Add
495 upper = ranges_.emplace(std::next(upper),
496 key_type(increment(upper->first.upper()), key.upper()),
497 value.second);
498 lower = std::next(begin(), lower_dist);
499 ++upper_dist;
500 }
501 } else if (upper_op < upper->first.lower()) {
502 inserted = true;
503 auto upper_prev = std::prev(upper); // lower cannot be the same as upper
504 // here, hence there is a prev
505 if (value.second == upper_prev->second) {
506 // Extend
507 upper_prev->first.setRange(upper_prev->first.lower(), key.upper());
508 --upper_dist;
509 upper = upper_prev;
510 } else if (increment(upper_prev->first.upper()) < key.upper()) {
511 // Add
512 upper = ranges_.emplace(
513 upper, key_type(increment(upper_prev->first.upper()), key.upper()),
514 value.second);
515 lower = std::next(begin(), lower_dist);
516 }
517 }
518
519 // Everything between (lower, upper) should be filled in
520 for (auto it = std::next(lower); std::next(upper) != it; ++it) {
521 auto it_prev = std::prev(it);
522 if (value.second == it_prev->second) {
523 if (value.second == it->second) {
524 inserted = true;
525 // Combine
526 it_prev->first.setRange(it_prev->first.lower(), it->first.upper());
527 it = erase(it);
528 std::prev(it);
529 --upper_dist;
530 } else {
531 // Extend uppwards
532 auto old = it_prev->first;
533 it_prev->first.setRange(it_prev->first.lower(), decrement(it->first.lower()));
534 inserted = inserted || old != it_prev->first;
535 }
536 } else if (value.second == it->second) {
537 // Extend downards
538 auto old = it->first;
539 it->first.setRange(increment(it_prev->first.upper()), it->first.upper());
540 inserted = inserted || old != it->first;
541 } else if (auto temp = increment(it_prev->first.upper());
542 temp < it->first.lower()) {
543 inserted = true;
544 // Add
545 it = ranges_.emplace(it, key_type(temp, decrement(it->first.lower())),
546 value.second);
547 ++upper_dist;
548 }
549 upper = std::next(begin(), upper_dist);
550 }
551
552 lower = std::next(begin(), lower_dist);
553 if (end() != upper && upper->first.upper() <= key.upper()) {
554 ++upper;
555 }
556 return {lower, inserted};
557 }
558
559 iterator insert(const_iterator hint, value_type const& value)
560 {
561 // FIXME: Use hint
562 return insert(value).first;
563 }
564
565 template <class P>
566 iterator insert(const_iterator hint, P&& value)
567 {
568 // FIXME: Use hint
569 return insert(std::forward<P>(value)).first;
570 }
571
572 iterator insert(const_iterator hint, value_type&& value)
573 {
574 // FIXME: Use hint
575 return insert(std::forward<value_type>(value)).first;
576 }
577
578 template <class InputIt,
579 typename = std::enable_if_t<std::is_base_of_v<
580 std::input_iterator_tag,
581 typename std::iterator_traits<InputIt>::iterator_category>>>
582 void insert(InputIt first, InputIt last)
583 {
584 // FIXME: Correct?
585 std::for_each(first, last, [this](auto&&... args) { this->insert(args...); });
586 }
587
588 void insert(std::initializer_list<value_type> ilist)
589 {
590 insert(std::cbegin(ilist), std::cend(ilist));
591 }
592
593 // FIXME: insert_return_type insert(node_type&& nh);
594
595 // FIXME: iterator insert(const_iterator hint, node_type&& nh);
596
597 /*
598 * Insertion that additionally assigns if parts of key are already present in map
599 * E.g., if the map contains: [1,3]:2, [6,9]:1 and [3, 8]:1 is inserted the resulting
600 * map will be: [1,2]:2, [3, 9]:1.
601 */
602 template <class M>
603 std::pair<iterator, bool> insert_or_assign(key_type key, M&& obj)
604 {
605 // Subtract one to easily determine if [lower, upper] should be combined
606 // with a range [X, lower - 1]. E.g., [8, 15] should be combined with [1, 7]
607 // to become [1, 15]. Also note the protection against underflow
608 Key const lower_up = decrement(key.lower());
609
610 // Add one to easily determine if [lower, upper] should be combined with a
611 // range [upper + 1, X]. E.g., [4, 15] should be combined with [16, 21] to
612 // become [4, 21]. Also note the protection against overflow
613 Key const upper_op = increment(key.upper());
614
615 auto [lower, upper] = equal_range(lower_up, key.upper());
616
617 // Fix lower
618 if (end() != lower && lower->first.upper() < key.lower() && obj != lower->second) {
619 ++lower;
620 }
621
622 if (end() == lower) {
623 // Add new range to the end
624 // E.g., [21, 35] should be added at the end of [1, 4], [7, 15] to become
625 // [1, 4], [7, 15], [21, 35].
626 ranges_.emplace_back(key, std::forward<M>(obj));
627 return {std::prev(end()), true};
628 } else if (lower == upper) {
629 if (upper_op < lower->first.lower() ||
630 (key.upper() < lower->first.lower() && obj != lower->second)) {
631 // Add new range to the front or middle
632 // E.g., [4, 7] should be added to the middle of [0, 2], [9, 24] to become
633 // [0, 2], [4, 7], [9, 24].
634 lower = ranges_.emplace(lower, key, std::forward<M>(obj));
635 return {lower, true};
636 } else if (obj == lower->second) {
637 // Extend
638 bool inserted = key.lower() < lower->first.lower();
639 lower->first.setRange(std::min(key.lower(), lower->first.lower()),
640 lower->first.upper());
641 return {lower, inserted};
642 } else if (key.lower() <= lower->first.lower()) {
643 // Split into two
644 lower->first.setRange(upper_op, lower->first.upper());
645 lower = ranges_.emplace(lower, key, std::forward<M>(obj));
646 return {lower, true};
647 } else {
648 // Split into three
649 auto max = lower->first.upper();
650 lower->first.setRange(lower->first.lower(), decrement(key.lower()));
651 lower = ranges_.emplace(std::next(lower), key_type(increment(key.upper()), max),
652 lower->second);
653 lower = ranges_.emplace(lower, key, std::forward<M>(obj));
654 return {lower, true};
655 }
656 }
657
658 bool inserted = false; // FIXME: Update
659
660 // Fix lower
661 if (lower->first.lower() < key.lower()) {
662 if (lower->second == obj) {
663 key.setRange(lower->first.lower(), key.upper());
664 } else {
665 lower->first.setRange(lower->first.lower(), decrement(key.lower()));
666 ++lower;
667
668 if (end() == lower) {
669 ranges_.emplace_back(key, std::forward<M>(obj));
670 return {std::prev(end()), true};
671 }
672 }
673 }
674
675 // Fix upper
676 if (end() != upper) {
677 if (upper->second != obj) {
678 upper->first.setRange(std::max(upper_op, upper->first.lower()),
679 upper->first.upper());
680 } else if (upper_op >= upper->first.lower()) {
681 key.setRange(key.lower(), upper->first.upper());
682 ++upper;
683 }
684 }
685
686 if (lower == upper) {
687 lower = ranges_.emplace(lower, key, std::forward<M>(obj));
688 return {lower, true};
689 }
690
691 // Erase
692 auto lower_dist = std::distance(begin(), lower);
693 erase(std::next(lower), upper);
694 lower = std::next(begin(), lower_dist);
695
696 // Assign
697 lower->first = key;
698 lower->second = std::forward<M>(obj);
699
700 return {lower, inserted};
701 }
702
703 template <class M>
704 iterator insert_or_assign(const_iterator hint, key_type key, M&& obj)
705 {
706 // FIXME: Use hint
707 return insert_or_assign(key, std::forward<M>(obj)).first;
708 }
709
710 template <class... Args>
711 std::pair<iterator, bool> emplace(Args&&... args)
712 {
713 // FIXME: Construct value_type only if needed
714 return insert(value_type(std::forward<Args>(args)...));
715 }
716
717 template <class... Args>
718 iterator emplace_hint(const_iterator hint, Args&&... args)
719 {
720 // FIXME: Use hint
721 return emplace(std::forward<Args>(args)...).first;
722 }
723
724 template <class... Args>
725 std::pair<iterator, bool> try_emplace(key_type k, Args&&... args)
726 {
727 // FIXME: Construct value_type only if needed
728 return insert(value_type(std::piecewise_construct, std::forward_as_tuple(k),
729 std::forward_as_tuple(std::forward<Args>(args)...)));
730 }
731
732 template <class... Args>
733 iterator try_emplace(const_iterator hint, key_type k, Args&&... args)
734 {
735 // FIXME: Use hint
736 return try_emplace(k, std::forward<Args>(args)...).first;
737 }
738
739 iterator erase(const_iterator pos) { return ranges_.erase(pos); }
740
741 iterator erase(const_iterator first, const_iterator last)
742 {
743 return ranges_.erase(first, last);
744 }
745
746 size_type erase(key_type key)
747 {
748 // FIXME: What should num_removed correspond to in here?
749
750 auto [lower, upper] = equal_range(key);
751
752 Key const lower_up = decrement(key.lower());
753 Key const upper_op = increment(key.upper());
754
755 size_type num_removed = 0;
756
757 if (end() == lower || (lower == upper && key.upper() < lower->first.lower())) {
758 // Nothing to erase
759 } else if (lower == upper) {
760 num_removed = 1;
761
762 if (key.lower() <= lower->first.lower()) {
763 // Erase lower part of a single range
764 lower->first.setRange(upper_op, lower->first.upper());
765 } else {
766 // Erase middle part of a single range (split it into two ranges)
767 auto cur_upper = lower->first.upper();
768 lower->first.setRange(lower->first.lower(), lower_up);
769 ranges_.emplace(std::next(lower), upper_op, cur_upper);
770 }
771 } else {
772 if (end() != upper) {
773 num_removed = upper->first.lower() < upper_op ? 1 : 0;
774 upper->first.setRange(std::max(upper->first.lower(), upper_op),
775 upper->first.upper());
776 }
777
778 num_removed += std::distance(lower, upper);
779
780 if (key.lower() <= lower->first.lower()) {
781 // Erase [lower, upper) ranges
782 ranges_.erase(lower, upper);
783 } else {
784 // Erase (lower, upper) ranges
785 lower->first.setRange(lower->first.lower(), lower_up);
786 ranges_.erase(std::next(lower), upper);
787 }
788 }
789
790 return num_removed;
791 }
792
793 template <typename Key2>
794 size_type erase(Range<Key2> key)
795 {
796 return erase(key_type(key));
797 }
798
799 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
800 size_type erase(K key)
801 {
802 return erase(key_type(key));
803 }
804
805 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
806 size_type erase(K lower, K upper)
807 {
808 return erase(key_type(lower, upper));
809 }
810
811 void swap(RangeMap& other) noexcept(
812 std::allocator_traits<allocator_type>::is_always_equal::value &&
813 std::is_nothrow_move_assignable<value_compare>::value) // FIXME: Look
814 // at noexcept
815 {
816 ranges_.swap(other.ranges_);
817 }
818
819 // FIXME: node_type extract(const_iterator position);
820
821 // FIXME: node_type extract(key_type const& k);
822
823 // void merge(RangeMap& source)
824 // {
825 // // FIXME: Implement
826 // }
827
828 // void merge(RangeMap&& source)
829 // {
830 // // FIXME: Implement
831 // }
832
833 //
834 // Lookup
835 //
836
837 [[nodiscard]] size_type count(key_type key) const { return contains(key) ? 1 : 0; }
838
839 template <typename Key2>
840 [[nodiscard]] size_type count(Range<Key2> key)
841 {
842 return count(key_type(key));
843 }
844
845 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
846 [[nodiscard]] size_type count(K key)
847 {
848 return count(key_type(key));
849 }
850
851 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
852 [[nodiscard]] size_type count(K lower, K upper)
853 {
854 return count(key_type(lower, upper));
855 }
856
857 iterator find(key_type key)
858 {
859 // FIXME: A single range can occupy mulitple indices now since the mapped
860 // value can be different. How should this be handled?
861 auto lower = lower_bound(key);
862
863 return end() != lower && lower->first.lower() <= key.lower() &&
864 lower->first.upper() >= key.upper()
865 ? lower
866 : end();
867 }
868
869 template <typename Key2>
870 iterator find(Range<Key2> key)
871 {
872 return find(key_type(key));
873 }
874
875 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
876 iterator find(K key)
877 {
878 return find(key_type(key));
879 }
880
881 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
882 iterator find(K lower, K upper)
883 {
884 return find(key_type(lower, upper));
885 }
886
887 const_iterator find(key_type key) const
888 {
889 // FIXME: A single range can occupy mulitple indices now since the mapped
890 // value can be different. How should this be handled?
891 auto lower = lower_bound(key);
892
893 return end() != lower && lower->first.lower() <= key.lower() &&
894 lower->first.upper() >= key.upper()
895 ? lower
896 : end();
897 }
898
899 template <typename Key2>
900 const_iterator find(Range<Key2> key) const
901 {
902 return find(key_type(key));
903 }
904
905 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
906 const_iterator find(K key) const
907 {
908 return find(key_type(key));
909 }
910
911 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
912 const_iterator find(K lower, K upper) const
913 {
914 return find(key_type(lower, upper));
915 }
916
917 [[nodiscard]] bool contains(key_type key) const
918 {
919 // FIXME: A single range can occupy mulitple indices now since the mapped
920 // value can be different. How should this be handled?
921 auto lower = lower_bound(key);
922 return end() != lower && lower->first.lower() <= key.lower() &&
923 lower->first.upper() >= key.upper();
924 }
925
926 template <typename Key2>
927 [[nodiscard]] bool contains(Range<Key2> key) const
928 {
929 return contains(key_type(key));
930 }
931
932 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
933 [[nodiscard]] bool contains(K key) const
934 {
935 return contains(key_type(key));
936 }
937
938 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
939 [[nodiscard]] bool contains(K lower, K upper) const
940 {
941 return contains(key_type(lower, upper));
942 }
943
944 [[nodiscard]] std::pair<iterator, iterator> equal_range(key_type key)
945 {
946 typename key_compare::range_t const s_range{key.lower(), key.upper()};
947 return std::equal_range(begin(), end(), s_range, comp_);
948 }
949
950 template <typename Key2>
951 [[nodiscard]] std::pair<iterator, iterator> equal_range(Range<Key2> key)
952 {
953 return equal_range(key_type(key));
954 }
955
956 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
957 [[nodiscard]] std::pair<iterator, iterator> equal_range(K key)
958 {
959 return equal_range(key_type(key));
960 }
961
962 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
963 [[nodiscard]] std::pair<iterator, iterator> equal_range(K lower, K upper)
964 {
965 return equal_range(key_type(lower, upper));
966 }
967
968 [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(key_type key) const
969 {
970 typename key_compare::range_t const s_range{key.lower(), key.upper()};
971 return std::equal_range(begin(), end(), s_range, comp_);
972 }
973
974 template <typename Key2>
975 [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(
976 Range<Key2> key) const
977 {
978 return equal_range(key_type(key));
979 }
980
981 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
982 [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(K key) const
983 {
984 return equal_range(key_type(key));
985 }
986
987 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
988 [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(K lower,
989 K upper) const
990 {
991 return equal_range(key_type(lower, upper));
992 }
993
994 [[nodiscard]] iterator lower_bound(key_type key)
995 {
996 typename key_compare::range_t const s_range{key.lower(), key.upper()};
997 return std::lower_bound(begin(), end(), s_range, comp_);
998 }
999
1000 template <typename Key2>
1001 [[nodiscard]] iterator lower_bound(Range<Key2> key)
1002 {
1003 return lower_bound(key_type(key));
1004 }
1005
1006 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1007 [[nodiscard]] iterator lower_bound(K key)
1008 {
1009 return lower_bound(key_type(key));
1010 }
1011
1012 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1013 [[nodiscard]] iterator lower_bound(K lower, K upper)
1014 {
1015 return lower_bound(key_type(lower, upper));
1016 }
1017
1018 [[nodiscard]] const_iterator lower_bound(key_type key) const
1019 {
1020 typename key_compare::range_t const s_range{key.lower(), key.upper()};
1021 return std::lower_bound(begin(), end(), s_range, comp_);
1022 }
1023
1024 template <typename Key2>
1025 [[nodiscard]] const_iterator lower_bound(Range<Key2> key) const
1026 {
1027 return lower_bound(key_type(key));
1028 }
1029
1030 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1031 [[nodiscard]] const_iterator lower_bound(K key) const
1032 {
1033 return lower_bound(key_type(key));
1034 }
1035
1036 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1037 [[nodiscard]] const_iterator lower_bound(K lower, K upper) const
1038 {
1039 return lower_bound(key_type(lower, upper));
1040 }
1041
1042 [[nodiscard]] iterator upper_bound(key_type key)
1043 {
1044 typename key_compare::range_t const s_range{key.lower(), key.upper()};
1045 return std::upper_bound(begin(), end(), s_range, comp_);
1046 }
1047
1048 template <typename Key2>
1049 [[nodiscard]] iterator upper_bound(Range<Key2> key)
1050 {
1051 return upper_bound(key_type(key));
1052 }
1053
1054 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1055 [[nodiscard]] iterator upper_bound(K key)
1056 {
1057 return upper_bound(key_type(key));
1058 }
1059
1060 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1061 [[nodiscard]] iterator upper_bound(K lower, K upper)
1062 {
1063 return upper_bound(key_type(lower, upper));
1064 }
1065
1066 [[nodiscard]] const_iterator upper_bound(key_type key) const
1067 {
1068 typename key_compare::range_t const s_range{key.lower(), key.upper()};
1069 return std::upper_bound(begin(), end(), s_range, comp_);
1070 }
1071
1072 template <typename Key2>
1073 [[nodiscard]] const_iterator upper_bound(Range<Key2> key) const
1074 {
1075 return upper_bound(key_type(key));
1076 }
1077
1078 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1079 [[nodiscard]] const_iterator upper_bound(K value) const
1080 {
1081 return upper_bound(key_type(value));
1082 }
1083
1084 template <typename K, typename = std::enable_if_t<std::is_arithmetic_v<K>>>
1085 [[nodiscard]] const_iterator upper_bound(K lower, K upper) const
1086 {
1087 return upper_bound(key_type(lower, upper));
1088 }
1089
1090 //
1091 // Observers
1092 //
1093
1094 key_compare key_comp() const
1095 {
1096 // FIXME: Implement correct
1097 return key_compare();
1098 }
1099
1100 value_compare value_comp() const { return comp_; }
1101
1102 //
1103 // Friends
1104 //
1105
1106 template <typename K, typename M>
1107 friend bool operator==(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1108 template <typename K, typename M>
1109 friend bool operator!=(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1110 template <typename K, typename M>
1111 friend bool operator<(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1112 template <typename K, typename M>
1113 friend bool operator<=(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1114 template <typename K, typename M>
1115 friend bool operator>(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1116 template <typename K, typename M>
1117 friend bool operator>=(RangeMap<K, M> const& lhs, RangeMap<K, M> const& rhs);
1118
1119 template <typename K, typename M>
1120 friend void swap(RangeMap<K, M>& lhs,
1121 RangeMap<K, M>& rhs) noexcept(noexcept(lhs.swap(rhs)));
1122
1123 template <typename K, typename M, class Pred>
1124 friend size_type erase_if(RangeMap<K, M>& range_set, Pred pred);
1125
1126 template <typename K, typename M>
1127 friend std::ostream& operator<<(std::ostream& os, RangeMap<K, M> const& range_map);
1128
1129 protected:
1130 static constexpr Key increment(Key value)
1131 {
1132 if constexpr (std::is_floating_point_v<Key>) {
1133 return std::nextafter(value, std::numeric_limits<Key>::max());
1134 } else {
1135 return std::numeric_limits<Key>::max() == value ? std::numeric_limits<Key>::max()
1136 : value + 1;
1137 }
1138 }
1139
1140 static constexpr Key decrement(Key value)
1141 {
1142 if constexpr (std::is_floating_point_v<Key>) {
1143 return std::nextafter(value, std::numeric_limits<Key>::lowest());
1144 } else {
1145 return std::numeric_limits<Key>::min() == value ? std::numeric_limits<Key>::min()
1146 : value - 1;
1147 }
1148 }
1149
1150 protected:
1151 std::vector<value_type> ranges_;
1152 value_compare comp_;
1153};
1154
1155template <typename Key, typename T>
1156bool operator==(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1157{
1158 // FIXME: Implement correctly
1159 return lhs.ranges_ == rhs.ranges_;
1160}
1161
1162template <typename Key, typename T>
1163bool operator!=(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1164{
1165 // FIXME: Implement correctly
1166 return lhs.ranges_ != rhs.ranges_;
1167}
1168
1169template <typename Key, typename T>
1170bool operator<(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1171{
1172 // FIXME: Implement correctly
1173 return lhs.ranges_ < rhs.ranges_;
1174}
1175
1176template <typename Key, typename T>
1177bool operator<=(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1178{
1179 // FIXME: Implement correctly
1180 return lhs.ranges_ <= rhs.ranges_;
1181}
1182
1183template <typename Key, typename T>
1184bool operator>(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1185{
1186 // FIXME: Implement correctly
1187 return lhs.ranges_ > rhs.ranges_;
1188}
1189
1190template <typename Key, typename T>
1191bool operator>=(RangeMap<Key, T> const& lhs, RangeMap<Key, T> const& rhs)
1192{
1193 // FIXME: Implement correctly
1194 return lhs.ranges_ >= rhs.ranges_;
1195}
1196
1197template <typename Key, typename T>
1198void swap(RangeMap<Key, T>& lhs, RangeMap<Key, T>& rhs) noexcept(noexcept(lhs.swap(rhs)))
1199{
1200 lhs.swap(rhs);
1201}
1202
1203template <typename Key, typename T, class Pred>
1204typename RangeMap<Key, T>::size_type erase_if(RangeMap<Key, T>& range_map, Pred pred)
1205{
1206 auto old_size = range_map.size();
1207 for (auto it = std::begin(range_map), last = std::end(range_map); it != last;) {
1208 if (pred(*it)) {
1209 it = range_map.erase(it);
1210 } else {
1211 ++it;
1212 }
1213 }
1214 return old_size - range_map.size();
1215}
1216
1217template <typename Key, typename T>
1218std::ostream& operator<<(std::ostream& os, RangeMap<Key, T> const& range_map)
1219{
1220 if (!range_map.empty()) {
1221 // FIXME: Make nicer?
1222 auto it = std::cbegin(range_map);
1223 for (; it != std::prev(std::cend(range_map)); ++it) {
1224 os << it->first << " = " << it->second << ", ";
1225 }
1226 os << it->first << " = " << it->second;
1227 }
1228 return os;
1229}
1230
1231} // namespace ufo
1232
1233#endif // UFO_CONTAINER_RANGE_MAP_HPP
STL namespace.
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
Definition fun.hpp:72
Comparator for interval ordering in associative containers.
Definition range.hpp:106
Represents a closed interval [lower, upper] of a scalar type.
Definition range.hpp:66