UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
semantic_set_map.hpp
1
42#ifndef UFO_MAP_SEMANTIC_SET_MAP_H
43#define UFO_MAP_SEMANTIC_SET_MAP_H
44
45// UFO
46#include <ufo/container/range_map.hpp>
47#include <ufo/map/node.hpp>
48#include <ufo/map/semantic/semantic.hpp>
49#include <ufo/map/semantic/semantic_mapping.hpp>
50#include <ufo/map/semantic_set/semantic_set.hpp>
51#include <ufo/map/semantic_set/semantic_set_block.hpp>
52#include <ufo/map/types.hpp>
53#include <ufo/util/buffer.hpp>
54
55// STL
56#include <cstddef>
57#include <limits>
58#include <memory>
59
60// STL parallel
61#ifdef UFO_TBB
62#include <execution>
63#endif
64
65namespace ufo
66{
67template <class Derived>
68class SemanticSetMap : public SemanticMapping
69{
70 private:
71 using Index = typename Derived::Index;
72 using Node = typename Derived::Node;
73 using Code = typename Derived::Code;
74 using Key = typename Derived::Key;
75 using Point = typename Derived::Point;
76 static constexpr std::size_t const N = Derived::childrenPerParent();
77
78 public:
79 //
80 // Get semantics
81 //
82
83 [[nodiscard]] SemanticSet<1> semantics(Index node) const
84 {
85 assert(semantics_.size() > node.pos && N > node.offset);
86
87 if (semanticsEmpty(node)) {
88 return {};
89 }
90
91 if (derived().isLeaf(node)) {
92 // Return stuff from current node
93 static_assert(N > 1);
94 // TODO: Add function in SemanticSet<N> to retrive a sub
95 return semantics_[node.pos].semantics.subset(node.offset);
96 }
97
98 // Traverse tree and get stuff from leaves
99 std::vector<Semantic> tmp;
100 derived().traverse(node, [this, &tmp, p = node.pos](Index node) -> bool {
101 if (0 == node.offset && p != node.pos) {
102 tmp.insert(std::end(tmp), std::cbegin(semantics_[node.pos].semantics),
103 std::cend(semantics_[node.pos].semantics));
104 }
105 return !semanticsEmpty(node);
106 });
107
108 std::sort(std::begin(tmp), std::end(tmp));
109
110 switch (semanticsPropagationCriteria()) {
111 case PropagationCriteria::MIN: {
112 auto last = std::unique(std::begin(tmp), std::end(tmp),
113 [](auto a, auto b) { return a.label == b.label; });
114 return {std::begin(tmp), last};
115 }
116 case PropagationCriteria::MEAN: {
117 // TODO: Implement
118 }
119 default: {
120 // Default is to return the maximum value for a label
121 auto r_last = std::unique(std::rbegin(tmp), std::rend(tmp),
122 [](auto a, auto b) { return a.label == b.label; });
123 return {r_last.base(), std::end(tmp)};
124 }
125 }
126 }
127
128 [[nodiscard]] SemanticSet<1> semantics(Node node) const
129 {
130 return semantics(derived().index(node));
131 }
132
133 [[nodiscard]] SemanticSet<1> semantics(Code code) const
134 {
135 return semantics(derived().index(code));
136 }
137
138 [[nodiscard]] SemanticSet<1> semantics(Key key) const
139 {
140 return semantics(derived().index(key));
141 }
142
143 [[nodiscard]] SemanticSet<1> semantics(Point coord, depth_t depth = 0) const
144 {
145 return semantics(derived().index(coord, depth));
146 }
147
148#ifdef UFO_TBB
149 template <class ExecutionPolicy,
150 std::enable_if_t<std::is_execution_policy_v<ExecutionPolicy>, bool> = true>
151 [[nodiscard]] SemanticSet<1> semantics(ExecutionPolicy&& policy, Index node) const
152 {
153 assert(semantics_.size() > node.pos && N > node.offset);
154
155 if (semanticsEmpty(node)) {
156 return {};
157 }
158
159 if (derived().isLeaf(node)) {
160 // Return stuff from current node
161 static_assert(N > 1);
162 // TODO: Add function in SemanticSet<N> to retrive a sub
163 return semantics_[node.pos].semantics.subset(node.offset);
164 }
165
166 // Traverse tree and get stuff from leaves
167 std::vector<Semantic> tmp;
168 derived().traverse(node, [this, &tmp, p = node.pos](Index node) -> bool {
169 if (0 == node.offset && p != node.pos) {
170 tmp.insert(std::end(tmp), std::cbegin(semantics_[node.pos].semantics),
171 std::cend(semantics_[node.pos].semantics));
172 }
173 return !semanticsEmpty(node);
174 });
175
176 std::sort(policy, std::begin(tmp), std::end(tmp));
177
178 switch (semanticsPropagationCriteria()) {
179 case PropagationCriteria::MIN: {
180 auto last =
181 std::unique(std::forward<ExecutionPolicy>(policy), std::begin(tmp),
182 std::end(tmp), [](auto a, auto b) { return a.label == b.label; });
183 return {std::begin(tmp), last};
184 }
185 case PropagationCriteria::MEAN: {
186 // TODO: Implement
187 }
188 default: {
189 // Default is to return the maximum value for a label
190 auto r_last = std::unique(std::forward<ExecutionPolicy>(policy), std::rbegin(tmp),
191 std::rend(tmp),
192 [](auto a, auto b) { return a.label == b.label; });
193 return {r_last.base(), std::end(tmp)};
194 }
195 }
196 }
197
198 template <class ExecutionPolicy,
199 std::enable_if_t<std::is_execution_policy_v<ExecutionPolicy>, bool> = true>
200 [[nodiscard]] SemanticSet<1> semantics(ExecutionPolicy&& policy, Node node) const
201 {
202 return semantics(std::forward<ExecutionPolicy>(policy), derived().index(node));
203 }
204
205 template <class ExecutionPolicy,
206 std::enable_if_t<std::is_execution_policy_v<ExecutionPolicy>, bool> = true>
207 [[nodiscard]] SemanticSet<1> semantics(ExecutionPolicy&& policy, Code code) const
208 {
209 return semantics(std::forward<ExecutionPolicy>(policy), derived().index(code));
210 }
211
212 template <class ExecutionPolicy,
213 std::enable_if_t<std::is_execution_policy_v<ExecutionPolicy>, bool> = true>
214 [[nodiscard]] SemanticSet<1> semantics(ExecutionPolicy&& policy, Key key) const
215 {
216 return semantics(std::forward<ExecutionPolicy>(policy), derived().index(key));
217 }
218
219 template <class ExecutionPolicy,
220 std::enable_if_t<std::is_execution_policy_v<ExecutionPolicy>, bool> = true>
221 [[nodiscard]] SemanticSet<1> semantics(ExecutionPolicy&& policy, Point coord,
222 depth_t depth = 0) const
223 {
224 return semantics(std::forward<ExecutionPolicy>(policy),
225 derived().index(coord, depth));
226 }
227#endif
228
229 //
230 // Get semantics summary
231 //
232
233 [[nodiscard]] Semantic semanticsSummary(pos_t block) const
234 {
235 assert(semantics_.size() > block);
236 return semantics_[block].summary;
237 }
238
239 [[nodiscard]] Semantic semanticsSummary(Index node) const
240 {
241 assert(semantics_.size() > node.pos && N > node.offset);
242 return derived().isChild(node) ? semantics_[node.pos].summary(node.offset)
243 : semanticsSummary(derived().children(node));
244 }
245
246 [[nodiscard]] Semantic semanticsSummary(Node node) const
247 {
248 return semanticsSummary(derived().index(node));
249 }
250
251 [[nodiscard]] Semantic semanticsSummary(Code code) const
252 {
253 return semanticsSummary(derived().index(code));
254 }
255
256 [[nodiscard]] Semantic semanticsSummary(Key key) const
257 {
258 return semanticsSummary(derived().index(key));
259 }
260
261 [[nodiscard]] Semantic semanticsSummary(Point coord, depth_t depth = 0) const
262 {
263 return semanticsSummary(derived().index(coord, depth));
264 }
265
266 //
267 // Semantics empty
268 //
269
270 [[nodiscard]] bool semanticsEmpty(Index node) const
271 {
272 assert(semantics_.size() > node.pos && N > node.offset);
273 return semantics_[node.pos].label_summary[node.offset];
274 }
275
276 [[nodiscard]] bool semanticsEmpty(Node node) const
277 {
278 return semanticsEmpty(derived().index(node));
279 }
280
281 [[nodiscard]] bool semanticsEmpty(Code code) const
282 {
283 return semanticsEmpty(derived().index(code));
284 }
285
286 [[nodiscard]] bool semanticsEmpty(Key key) const
287 {
288 return semanticsEmpty(derived().index(key));
289 }
290
291 [[nodiscard]] bool semanticsEmpty(Point coord, depth_t depth = 0) const
292 {
293 return semanticsEmpty(derived().index(coord, depth));
294 }
295
296 //
297 // Semantics size
298 //
299
300 [[nodiscard]] std::size_t semanticsSize(Index node) const
301 {
302 assert(semantics_.size() > node.pos && N > node.offset);
303 // TODO: Implement
304 }
305
306 [[nodiscard]] std::size_t semanticsSize(Node node) const
307 {
308 return semanticsSize(derived().index(node));
309 }
310
311 [[nodiscard]] std::size_t semanticsSize(Code code) const
312 {
313 return semanticsSize(derived().index(code));
314 }
315
316 [[nodiscard]] std::size_t semanticsSize(Key key) const
317 {
318 return semanticsSize(derived().index(key));
319 }
320
321 [[nodiscard]] std::size_t semanticsSize(Point coord, depth_t depth = 0) const
322 {
323 return semanticsSize(derived().index(coord, depth));
324 }
325
326 //
327 // Get semantics count
328 //
329
330 [[nodiscard]] std::size_t semanticsCount(Index node, label_t label) const
331 {
332 assert(semantics_.size() > node.pos && N > node.offset);
333 // TODO: Implement
334 }
335
336 [[nodiscard]] std::size_t semanticsCount(Node node, label_t label) const
337 {
338 return semanticsCount(derived().index(node), label);
339 }
340
341 [[nodiscard]] std::size_t semanticsCount(Code code, label_t label) const
342 {
343 return semanticsCount(derived().index(code), label);
344 }
345
346 [[nodiscard]] std::size_t semanticsCount(Key key, label_t label) const
347 {
348 return semanticsCount(derived().index(key), label);
349 }
350
351 [[nodiscard]] std::size_t semanticsCount(Point coord, label_t label,
352 depth_t depth = 0) const
353 {
354 return semanticsCount(derived().index(coord, depth), label);
355 }
356
357 //
358 // Contains
359 //
360
361 [[nodiscard]] bool semanticsContains(Index node, label_t label) const
362 {
363 assert(semantics_.size() > node.pos && N > node.offset);
364 // TODO: Implement
365 }
366
367 [[nodiscard]] bool semanticsContains(Node node, label_t label) const
368 {
369 return semanticsContains(derived().index(node), label);
370 }
371
372 [[nodiscard]] bool semanticsContains(Code code, label_t label) const
373 {
374 return semanticsContains(derived().index(code), label);
375 }
376
377 [[nodiscard]] bool semanticsContains(Key key, label_t label) const
378 {
379 return semanticsContains(derived().index(key), label);
380 }
381
382 [[nodiscard]] bool semanticsContains(Point coord, label_t label,
383 depth_t depth = 0) const
384 {
385 return semanticsContains(derived().index(coord, depth), label);
386 }
387
388 //
389 // Contains class
390 //
391
392 [[nodiscard]] bool semanticsContainsClass(Index node, std::string tag) const
393 {
394 // TODO: Implement
395 }
396
397 // TODO: What type is class?
398 [[nodiscard]] bool semanticsContainsClass(Index node, label_t tag) const
399 {
400 // TODO: Implement
401 }
402
403 //
404 // Contains all
405 //
406
407 [[nodiscard]] bool semanticsContainsAll(Index node, std::string tag) const
408 {
409 // TODO: Implement
410 }
411
412 [[nodiscard]] bool semanticsContainsAll(Index node, SemanticRange range) const
413 {
414 assert(semantics_.size() > node.pos && N > node.offset);
415 // TODO: Implement
416 }
417
418 [[nodiscard]] bool semanticsContainsAll(Index node,
419 SemanticRangeSet const& ranges) const
420 {
421 assert(semantics_.size() > node.pos && N > node.offset);
422 // TODO: Implement
423 }
424
425 [[nodiscard]] bool semanticsContainsAll(Node node, SemanticRange range) const
426 {
427 return semanticsContainsAll(derived().index(node), range);
428 }
429
430 [[nodiscard]] bool semanticsContainsAll(Code code, SemanticRange range) const
431 {
432 return semanticsContainsAll(derived().index(code), range);
433 }
434
435 [[nodiscard]] bool semanticsContainsAll(Key key, SemanticRange range) const
436 {
437 return semanticsContainsAll(derived().index(key), range);
438 }
439
440 [[nodiscard]] bool semanticsContainsAll(Point coord, SemanticRange range,
441 depth_t depth = 0) const
442 {
443 return semanticsContainsAll(derived().index(coord, depth), range);
444 }
445
446 //
447 // Contains any
448 //
449
450 [[nodiscard]] bool semanticsContainsAny(Index node, SemanticRange range) const
451 {
452 assert(semantics_.size() > node.pos && N > node.offset);
453 // TODO: Implement
454 }
455
456 [[nodiscard]] bool semanticsContainsAny(Node node, SemanticRange range) const
457 {
458 return semanticsContainsAny(derived().index(node), range);
459 }
460
461 [[nodiscard]] bool semanticsContainsAny(Code code, SemanticRange range) const
462 {
463 return semanticsContainsAny(derived().index(code), range);
464 }
465
466 [[nodiscard]] bool semanticsContainsAny(Key key, SemanticRange range) const
467 {
468 return semanticsContainsAny(derived().index(key), range);
469 }
470
471 [[nodiscard]] bool semanticsContainsAny(Point coord, SemanticRange range,
472 depth_t depth = 0) const
473 {
474 return semanticsContainsAny(derived().index(coord, depth), range);
475 }
476
477 //
478 // Contains none
479 //
480
481 [[nodiscard]] bool semanticsContainsNone(Index node, SemanticRange range) const
482 {
483 assert(semantics_.size() > node.pos && N > node.offset);
484 // TODO: Implement
485 }
486
487 [[nodiscard]] bool semanticsContainsNone(Node node, SemanticRange range) const
488 {
489 return semanticsContainsNone(derived().index(node), range);
490 }
491
492 [[nodiscard]] bool semanticsContainsNone(Code code, SemanticRange range) const
493 {
494 return semanticsContainsNone(derived().index(code), range);
495 }
496
497 [[nodiscard]] bool semanticsContainsNone(Key key, SemanticRange range) const
498 {
499 return semanticsContainsNone(derived().index(key), range);
500 }
501
502 [[nodiscard]] bool semanticsContainsNone(Point coord, SemanticRange range,
503 depth_t depth = 0) const
504 {
505 return semanticsContainsNone(derived().index(coord, depth), range);
506 }
507
508 //
509 // Contains some
510 //
511
512 [[nodiscard]] bool semanticsContainsSome(Index node, SemanticRange range) const
513 {
514 assert(semantics_.size() > node.pos && N > node.offset);
515 // TODO: Implement
516 }
517
518 [[nodiscard]] bool semanticsContainsSome(Node node, SemanticRange range) const
519 {
520 return semanticsContainsSome(derived().index(node), range);
521 }
522
523 [[nodiscard]] bool semanticsContainsSome(Code code, SemanticRange range) const
524 {
525 return semanticsContainsSome(derived().index(code), range);
526 }
527
528 [[nodiscard]] bool semanticsContainsSome(Key key, SemanticRange range) const
529 {
530 return semanticsContainsSome(derived().index(key), range);
531 }
532
533 [[nodiscard]] bool semanticsContainsSome(Point coord, SemanticRange range,
534 depth_t depth = 0) const
535 {
536 return semanticsContainsSome(derived().index(coord, depth), range);
537 }
538
539 //
540 // Set semantics
541 //
542
543 void semanticsSet(Index node, SemanticSet<1> const& semantics)
544 {
545 derived().apply(
546 node,
547 [this, &semantics](Index node) {
548 // TODO: Update summary
549 semantics_[node.pos].semantics.set(node.offset, semantics);
550 },
551 [this, &semantics](pos_t block) {
552 // TODO: Update summary
553 semantics_[block].semantics.set(semantics);
554 });
555 }
556
557 Node semanticsSet(Node node, SemanticSet<1> const& semantics, bool propagate = true)
558 {
559 return derived().apply(
560 node,
561 [this, &semantics](Index node) {
562 // TODO: Update summary
563 semantics_[node.pos].semantics.set(node.offset, semantics);
564 },
565 [this, &semantics](pos_t block) {
566 // TODO: Update summary
567 semantics_[block].semantics.set(semantics);
568 },
569 propagate);
570 }
571
572 Node semanticsSet(Code code, SemanticSet<1> const& semantics, bool propagate = true)
573 {
574 return derived().apply(
575 code,
576 [this, &semantics](Index node) {
577 // TODO: Update summary
578 semantics_[node.pos].semantics.set(node.offset, semantics);
579 },
580 [this, &semantics](pos_t block) {
581 // TODO: Update summary
582 semantics_[block].semantics.set(semantics);
583 },
584 propagate);
585 }
586
587 Node semanticsSet(Key key, SemanticSet<1> const& semantics, bool propagate = true)
588 {
589 return semanticsSet(derived().toCode(key), semantics, propagate);
590 }
591
592 Node semanticsSet(Point coord, SemanticSet<1> const& semantics, bool propagate = true,
593 depth_t depth = 0)
594 {
595 return semanticsSet(derived().toCode(coord, depth), semantics, propagate);
596 }
597
598 //
599 // Insert semantics
600 //
601
602 void semanticsInsert(Index node, Semantic sem)
603 {
604 return derived().apply(
605 node,
606 [this, sem](Index node) {
607 // TODO: Update summary
608 semantics_[node.pos].semantics.insert(node.offset, sem);
609 },
610 [this, sem](pos_t block) {
611 // TODO: Update summary
612 semantics_[block].semantics.insert(sem);
613 });
614 }
615
616 void semanticsInsert(Index node, label_t label, value_t value)
617 {
618 return semanticsInsert(node, Semantic(label, value));
619 }
620
621 template <class InputIt>
622 void semanticsInsert(Index node, InputIt first, InputIt last)
623 {
624 // TODO: Implement
625 }
626
627 template <class SemanticRange>
628 void semanticsInsert(Index node, SemanticRange const& sems)
629 {
630 semanticsInsert(node, std::cbegin(sems), std::cend(sems));
631 }
632
633 void semanticsInsert(Index node, std::initializer_list<Semantic> ilist)
634 {
635 semanticsInsert(node, std::cbegin(ilist), std::cend(ilist));
636 }
637
638 Node semanticsInsert(Node node, Semantic sem, bool propagate = true)
639 {
640 return derived().apply(
641 node,
642 [this, sem](Index node) {
643 // TODO: Update summary
644 semantics_[node.pos].semantics.insert(node.offset, sem);
645 },
646 [this, sem](pos_t block) {
647 // TODO: Update summary
648 semantics_[block].semantics.insert(sem);
649 },
650 propagate);
651 }
652
653 Node semanticsInsert(Node node, label_t label, value_t value, bool propagate = true)
654 {
655 return semanticsInsert(node, Semantic(label, value), propagate);
656 }
657
658 Node semanticsInsert(Code code, Semantic sem, bool propagate = true)
659 {
660 return derived().apply(
661 code,
662 [this, sem](Index node) {
663 // TODO: Update summary
664 semantics_[node.pos].semantics.insert(node.offset, sem);
665 },
666 [this, sem](pos_t block) {
667 // TODO: Update summary
668 semantics_[block].semantics.insert(sem);
669 },
670 propagate);
671 }
672
673 Node semanticsInsert(Code code, label_t label, value_t value, bool propagate = true)
674 {
675 return semanticsInsert(code, Semantic(label, value), propagate);
676 }
677
678 Node semanticsInsert(Key key, Semantic value, bool propagate = true)
679 {
680 return semanticsInsert(derived().toCode(key), value, propagate);
681 }
682
683 Node semanticsInsert(Key key, label_t label, value_t value, bool propagate = true)
684 {
685 return semanticsInsert(key, Semantic(label, value), propagate);
686 }
687
688 Node semanticsInsert(Point coord, Semantic value, bool propagate = true,
689 depth_t depth = 0)
690 {
691 return semanticsInsert(derived().toCode(coord, depth), value, propagate);
692 }
693
694 Node semanticsInsert(Point coord, label_t label, value_t value, bool propagate = true,
695 depth_t depth = 0)
696 {
697 return semanticsInsert(coord, Semantic(label, value), propagate, depth);
698 }
699
700 //
701 // Insert or assign
702 //
703
704 void semanticsInsertOrAssign(Index node, Semantic sem)
705 {
706 // TODO: Implement
707 }
708
709 void semanticsInsertOrAssign(Index node, label_t label, value_t value)
710 {
711 semanticsInsertOrAssign(node, Semantic(label, value));
712 }
713
714 template <class InputIt>
715 void semanticsInsertOrAssign(Index node, InputIt first, InputIt last)
716 {
717 // TODO: Implement
718 }
719
720 template <class SemanticRange>
721 void semanticsInsertOrAssign(Index node, SemanticRange const& sems)
722 {
723 semanticsInsertOrAssign(node, std::cbegin(sems), std::cend(sems));
724 }
725
726 void semanticsInsertOrAssign(Index node, std::initializer_list<Semantic> ilist)
727 {
728 semanticsInsert(node, std::cbegin(ilist), std::cend(ilist));
729 }
730
731 //
732 // Insert or update
733 //
734
735 template <
736 class UnaryFun,
737 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
738 void semanticsInsertOrUpdate(Index node, Semantic sem, UnaryFun f)
739 {
740 // TODO: Implement
741 }
742
743 template <
744 class UnaryFun,
745 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
746 void semanticsInsertOrUpdate(Index node, label_t label, value_t value, UnaryFun f)
747 {
748 semanticsInsertOrUpdate(node, Semantic(label, value), f);
749 }
750
751 template <
752 class InputIt, class UnaryFun,
753 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
754 void semanticsInsertOrUpdate(Index node, InputIt first, InputIt last, UnaryFun f)
755 {
756 // TODO: Implement
757 }
758
759 template <
760 class SemanticRange, class UnaryFun,
761 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
762 void semanticsInsertOrUpdate(Index node, SemanticRange const& sems, UnaryFun f)
763 {
764 semanticsInsertOrUpdate(node, std::cbegin(sems), std::cend(sems), f);
765 }
766
767 template <
768 class UnaryFun,
769 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
770 void semanticsInsertOrUpdate(Index node, std::initializer_list<Semantic> ilist,
771 UnaryFun f)
772 {
773 semanticsInsertOrUpdate(node, std::cbegin(ilist), std::cend(ilist), f);
774 }
775
776 //
777 // Assign
778 //
779
780 void semanticsAssign(Index node, value_t value)
781 {
782 // TODO: Implement
783 }
784
785 void semanticsAssign(Index node, std::string const& tag, value_t value)
786 {
787 // TODO: Implement
788 }
789
790 void semanticsAssign(Index node, SemanticRange range, value_t value)
791 {
792 // TODO: Implement
793 }
794
795 void semanticsAssign(Index node, SemanticRangeSet const& ranges, value_t value)
796 {
797 // TODO: Implement
798 }
799
800 //
801 // Update
802 //
803
804 template <
805 class UnaryFun,
806 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
807 void semanticsUpdate(Index node, UnaryFun f)
808 {
809 // TODO: Implement
810 }
811
812 template <
813 class UnaryFun,
814 std::enable_if_t<std::is_invocable_r_v<value_t, UnaryFun, Semantic>, bool> = true>
815 void semanticsUpdate(Index node, std::string const& tag, UnaryFun f)
816 {
817 // TODO: Implement
818 }
819
820 //
821 // Erase
822 //
823
824 // TODO: Implement
825
826 //
827 // Erase if
828 //
829
830 // TODO: Implement
831
832 //
833 // Clear
834 //
835
836 // TODO: Implement
837
838 void semanticsClear(bool propagate = true)
839 {
840 semanticsClear(derived().rootCode(), propagate);
841 }
842
843 void semanticsClear(Index node)
844 {
845 // TODO: Implement
846 }
847
848 Node semanticsClear(Node node, bool propagate = true)
849 {
850 // TODO: Implement
851 }
852
853 Node semanticsClear(Code code, bool propagate = true)
854 {
855 // TODO: Implement
856 }
857
858 Node semanticsClear(Key key, bool propagate = true)
859 {
860 return semanticsClear(derived().toCode(key), propagate);
861 }
862
863 Node semanticsClear(Point coord, bool propagate = true, depth_t depth = 0)
864 {
865 return semanticsClear(derived().toCode(coord, depth), propagate);
866 }
867
868 //
869 // Change label
870 //
871
872 //
873 // Integration
874 //
875
876 template <class InputIt>
877 void insertPoints(Index node, InputIt first, InputIt last)
878 {
879 for (auto it = first; it != last; ++it) {
880 insertSemantics(node, it->label, it->value);
881 }
882 }
883
884 //
885 // Contains
886 //
887
888 [[nodiscard]] bool containsSemantics(Index node, label_t label) const
889 {
890 switch (semanticsPropagationCriteria()) {
891 case PropagationCriteria::MIN:
892 case PropagationCriteria::MAX:
893 return semantics_[node.pos].semantic_set.contains(node.offset, label);
894 case PropagationCriteria::NONE:
895 case PropagationCriteria::S_MIN:
896 case PropagationCriteria::S_MAX: {
897 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
898 // check content
899 return semantics_[node.pos].semantic_set.contains(node.offset, label);
900 } else {
901 // traverse tree
902 for (offset_t i = 0; i != N; ++i) {
903 auto child = derived().child(node, i);
904 if (containsSemantics(child, label)) {
905 return true;
906 }
907 }
908 return false;
909 }
910 }
911 }
912 return true;
913 }
914
915 //
916 // All
917 //
918
919 // inputIt to tags (string)
920 template <class InputIt>
921 [[nodiscard]] bool allSemantics(Index node, InputIt first, InputIt last) const
922 {
923 SemanticRangeSet ranges;
924 for (auto it = first; it != last; ++it) {
925 ranges.insert(labels(*it));
926 }
927 return allSemantics(node, ranges);
928 }
929
930 [[nodiscard]] bool allSemantics(Index node, SemanticRangeSet ranges) const
931 {
932 switch (semanticsPropagationCriteria()) {
933 case PropagationCriteria::MIN:
934 case PropagationCriteria::MAX:
935 return semantics_[node.pos].semantic_set.all(node.offset, ranges);
936
937 case PropagationCriteria::NONE:
938 case PropagationCriteria::S_MIN:
939 case PropagationCriteria::S_MAX: {
940 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
941 // check content
942 return semantics_[node.pos].semantic_set.all(node.offset, ranges);
943 } else {
944 // traverse tree
945 for (offset_t i = 0; i != N; ++i) {
946 auto child = derived().child(node, i);
947 if (allSemantics(child, ranges)) {
948 return true;
949 }
950 }
951 return false;
952 }
953 }
954 }
955 return true;
956 }
957
958 //
959 // Any
960 //
961
962 // inputIt to tags (string)
963 template <class InputIt>
964 [[nodiscard]] bool anySemantics(Index node, InputIt first, InputIt last) const
965 {
966 SemanticRangeSet ranges;
967 for (auto it = first; it != last; ++it) {
968 auto ls = labels(*it);
969 ranges.insert(ls.begin(), ls.end());
970 }
971 return anySemantics(node, ranges);
972 }
973
974 [[nodiscard]] bool anySemantics(Index node, SemanticRangeSet ranges) const
975 {
976 switch (semanticsPropagationCriteria()) {
977 case PropagationCriteria::MIN:
978 case PropagationCriteria::MAX:
979 return semantics_[node.pos].semantic_set.any(node.offset, ranges);
980
981 case PropagationCriteria::NONE:
982 case PropagationCriteria::S_MIN:
983 case PropagationCriteria::S_MAX: {
984 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
985 // check content
986 return semantics_[node.pos].semantic_set.any(node.offset, ranges);
987 } else {
988 // traverse tree
989 for (offset_t i = 0; i != N; ++i) {
990 auto child = derived().child(node, i);
991 if (anySemantics(child, ranges)) {
992 return true;
993 }
994 }
995 return false;
996 }
997 }
998 }
999 return true;
1000 }
1001
1002 //
1003 // None
1004 //
1005
1006 // inputIt to tags (string)
1007 template <class InputIt>
1008 [[nodiscard]] bool noneSemantics(Index node, InputIt first, InputIt last) const
1009 {
1010 SemanticRangeSet ranges;
1011 for (auto it = first; it != last; ++it) {
1012 ranges.insert(labels(*it));
1013 }
1014 return noneSemantics(node, ranges);
1015 }
1016
1017 [[nodiscard]] bool noneSemantics(Index node, SemanticRangeSet ranges) const
1018 {
1019 switch (semanticsPropagationCriteria()) {
1020 case PropagationCriteria::MIN:
1021 case PropagationCriteria::MAX:
1022 return semantics_[node.pos].semantic_set.none(node.offset, ranges);
1023
1024 case PropagationCriteria::NONE:
1025 case PropagationCriteria::S_MIN:
1026 case PropagationCriteria::S_MAX: {
1027 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1028 // check content
1029 return semantics_[node.pos].semantic_set.none(node.offset, ranges);
1030 } else {
1031 // traverse tree
1032 for (offset_t i = 0; i != N; ++i) {
1033 auto child = derived().child(node, i);
1034 if (!noneSemantics(child, ranges)) {
1035 return false;
1036 }
1037 }
1038 return true;
1039 }
1040 }
1041 }
1042 return true;
1043 }
1044
1045 //
1046 // Insert semantics
1047 //
1048
1049 void insertSemantics(Index node, label_t label, value_t value)
1050 {
1051 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1052 derived().apply(
1053 node,
1054 [this, label, value](Index node) {
1055 semantics_[node.pos].semantic_set.insert(node.offset, label, value);
1056 },
1057 [this, label, value](pos_t pos) {
1058 semantics_[pos].semantic_set.insert(label, value);
1059 });
1060 } else {
1061 for (offset_t i{}; i != N; ++i) {
1062 insertSemantics(derived().child(node, i), label, value);
1063 }
1064 }
1065 }
1066
1067 Node insertSemantics(Node node, label_t label, value_t value, bool propagate = true)
1068 {
1069 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1070 return derived().apply(
1071 node,
1072 [this, label, value](Index node) {
1073 semantics_[node.pos].semantic_set.insert(node.offset, label, value);
1074 },
1075 [this, label, value](pos_t pos) {
1076 semantics_[pos].semantic_set.insert(label, value);
1077 },
1078 propagate);
1079 } else {
1080 for (offset_t i{}; i != N; ++i) {
1081 insertSemantics(derived().child(node, i), label, value, propagate);
1082 }
1083 return node;
1084 }
1085 }
1086
1087 Node insertSemantics(Code code, label_t label, value_t value, bool propagate = true)
1088 {
1089 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1090 return derived().apply(
1091 code,
1092 [this, label, value](Index node) {
1093 semantics_[node.pos].semantic_set.insert(node.offset, label, value);
1094 },
1095 [this, label, value](pos_t pos) {
1096 semantics_[pos].semantic_set.insert(label, value);
1097 },
1098 propagate);
1099 } else {
1100 for (offset_t i{}; i != N; ++i) {
1101 insertSemantics(code.child(i), label, value, propagate);
1102 }
1103 return derived()(code);
1104 }
1105 }
1106
1107 Node insertSemantics(Key key, label_t label, value_t value, bool propagate = true)
1108 {
1109 return insertSemantics(derived().toCode(key), label, value, propagate);
1110 }
1111
1112 Node insertSemantics(Point coord, label_t label, value_t value, bool propagate = true,
1113 depth_t depth = 0)
1114 {
1115 return insertSemantics(derived().toCode(coord, depth), label, value, propagate);
1116 }
1117
1118 Node insertSemantics(Node node, Semantic semantic, bool propagate = true)
1119 {
1120 return insertSemantics(node, semantic.label, semantic.value, propagate);
1121 }
1122
1123 Node insertSemantics(Code code, Semantic semantic, bool propagate = true)
1124 {
1125 return insertSemantics(code, semantic.label, semantic.value, propagate);
1126 }
1127
1128 Node insertSemantics(Key key, Semantic semantic, bool propagate = true)
1129 {
1130 return insertSemantics(derived().toCode(key), semantic, propagate);
1131 }
1132
1133 Node insertSemantics(Point coord, Semantic semantic, bool propagate = true,
1134 depth_t depth = 0)
1135 {
1136 return insertSemantics(derived().toCode(coord, depth), semantic, propagate);
1137 }
1138
1139 template <class InputIt,
1140 typename = std::enable_if_t<std::is_base_of_v<
1141 std::input_iterator_tag,
1142 typename std::iterator_traits<InputIt>::iterator_category>>>
1143 void insertSemantics(Index node, InputIt first, InputIt last)
1144 {
1145 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1146 derived().apply(
1147 node,
1148 [this, first, last](Index node) {
1149 semantics_[node.pos].semantic_set.insert(node.offset, first, last);
1150 },
1151 [this, first, last](pos_t pos) {
1152 semantics_[pos].semantic_set.insert(first, last);
1153 });
1154 } else {
1155 for (offset_t i{}; i != N; ++i) {
1156 insertSemantics(derived().child(node, i), first, last);
1157 }
1158 }
1159 }
1160
1161 template <class InputIt,
1162 typename = std::enable_if_t<std::is_base_of_v<
1163 std::input_iterator_tag,
1164 typename std::iterator_traits<InputIt>::iterator_category>>>
1165 Node insertSemantics(Node node, InputIt first, InputIt last, bool propagate = true)
1166 {
1167 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1168 return derived().apply(
1169 node,
1170 [this, first, last](Index node) {
1171 semantics_[node.pos].semantic_set.insert(node.offset, first, last);
1172 },
1173 [this, first, last](pos_t pos) {
1174 semantics_[pos].semantic_set.insert(first, last);
1175 },
1176 propagate);
1177 } else {
1178 for (offset_t i{}; i != N; ++i) {
1179 insertSemantics(derived().child(node, i), first, last, propagate);
1180 }
1181 return node;
1182 }
1183 }
1184
1185 template <class InputIt,
1186 typename = std::enable_if_t<std::is_base_of_v<
1187 std::input_iterator_tag,
1188 typename std::iterator_traits<InputIt>::iterator_category>>>
1189 Node insertSemantics(Code code, InputIt first, InputIt last, bool propagate = true)
1190 {
1191 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1192 return derived().apply(
1193 code,
1194 [this, first, last](Index node) {
1195 semantics_[node.pos].semantic_set.insert(node.offset, first, last);
1196 },
1197 [this, first, last](pos_t pos) {
1198 semantics_[pos].semantic_set.insert(first, last);
1199 },
1200 propagate);
1201 } else {
1202 for (offset_t i{}; i != N; ++i) {
1203 insertSemantics(code.child(i), first, last, propagate);
1204 }
1205 return derived()(code);
1206 }
1207 }
1208
1209 template <class InputIt,
1210 typename = std::enable_if_t<std::is_base_of_v<
1211 std::input_iterator_tag,
1212 typename std::iterator_traits<InputIt>::iterator_category>>>
1213 Node insertSemantics(Key key, InputIt first, InputIt last, bool propagate = true)
1214 {
1215 return insertSemantics(derived().toCode(key), first, last, propagate);
1216 }
1217
1218 template <class InputIt,
1219 typename = std::enable_if_t<std::is_base_of_v<
1220 std::input_iterator_tag,
1221 typename std::iterator_traits<InputIt>::iterator_category>>>
1222 Node insertSemantics(Point coord, InputIt first, InputIt last, bool propagate = true,
1223 depth_t depth = 0)
1224 {
1225 return insertSemantics(derived().toCode(coord, depth), first, last, propagate);
1226 }
1227
1228 Node insertSemantics(Node node, std::initializer_list<Semantic> ilist,
1229 bool propagate = true)
1230 {
1231 return insertSemantics(node, std::cbegin(ilist), std::cend(ilist), propagate);
1232 }
1233
1234 Node insertSemantics(Code code, std::initializer_list<Semantic> ilist,
1235 bool propagate = true)
1236 {
1237 return insertSemantics(code, std::cbegin(ilist), std::cend(ilist), propagate);
1238 }
1239
1240 Node insertSemantics(Key key, std::initializer_list<Semantic> ilist,
1241 bool propagate = true)
1242 {
1243 return insertSemantics(derived().toCode(key), ilist, propagate);
1244 }
1245
1246 Node insertSemantics(Point coord, std::initializer_list<Semantic> ilist,
1247 bool propagate = true, depth_t depth = 0)
1248 {
1249 return insertSemantics(derived().toCode(coord, depth), ilist, propagate);
1250 }
1251
1252 //
1253 // Insert or assign semantics
1254 //
1255 void insertOrAssignSemantics(Index node, label_t label, value_t value)
1256 {
1257 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1258 derived().apply(
1259 node,
1260 [this, label, value](Index node) {
1261 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label, value);
1262 },
1263 [this, label, value](pos_t pos) {
1264 semantics_[pos].semantic_set.insertOrAssign(label, value);
1265 });
1266 } else {
1267 for (offset_t i{}; i != N; ++i) {
1268 insertOrAssignSemantics(derived().child(node, i), label, value);
1269 }
1270 }
1271 }
1272
1273 Node insertOrAssignSemantics(Node node, label_t label, value_t value,
1274 bool propagate = true)
1275 {
1276 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1277 return derived().apply(
1278 node,
1279 [this, label, value](Index node) {
1280 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label,
1281 value);
1282 },
1283 [this, label, value](pos_t pos) {
1284 semantics_[pos].semantic_set.insertOrAssign(label, value);
1285 }),
1286 propagate;
1287 } else {
1288 for (offset_t i{}; i != N; ++i) {
1289 insertOrAssignSemantics(derived().child(node, i), label, value, propagate);
1290 }
1291 return node;
1292 }
1293 }
1294
1295 Node insertOrAssignSemantics(Code code, label_t label, value_t value,
1296 bool propagate = true)
1297 {
1298 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1299 return derived().apply(
1300 code,
1301 [this, label, value](Index node) {
1302 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label, value);
1303 },
1304 [this, label, value](pos_t pos) {
1305 semantics_[pos].semantic_set.insertOrAssign(label, value);
1306 },
1307 propagate);
1308 } else {
1309 for (offset_t i{}; i != N; ++i) {
1310 insertOrAssignSemantics(code.child(i), label, value, propagate);
1311 }
1312 return derived()(code);
1313 }
1314 }
1315
1316 Node insertOrAssignSemantics(Key key, label_t label, value_t value,
1317 bool propagate = true)
1318 {
1319 return insertOrAssignSemantics(derived().toCode(key), label, value, propagate);
1320 }
1321
1322 Node insertOrAssignSemantics(Point coord, label_t label, value_t value,
1323 bool propagate = true, depth_t depth = 0)
1324 {
1325 return insertOrAssignSemantics(derived().toCode(coord, depth), label, value,
1326 propagate);
1327 }
1328
1329 Node insertOrAssignSemantics(Node node, Semantic semantic, bool propagate = true)
1330 {
1331 return insertOrAssignSemantics(node, semantic.label, semantic.value, propagate);
1332 }
1333
1334 Node insertOrAssignSemantics(Code code, Semantic semantic, bool propagate = true)
1335 {
1336 return insertOrAssignSemantics(code, semantic.label, semantic.value, propagate);
1337 }
1338
1339 Node insertOrAssignSemantics(Key key, Semantic semantic, bool propagate = true)
1340 {
1341 return insertOrAssignSemantics(derived().toCode(key), semantic, propagate);
1342 }
1343
1344 Node insertOrAssignSemantics(Point coord, Semantic semantic, bool propagate = true,
1345 depth_t depth = 0)
1346 {
1347 return insertOrAssignSemantics(derived().toCode(coord, depth), semantic, propagate);
1348 }
1349
1350 template <class InputIt,
1351 typename = std::enable_if_t<std::is_base_of_v<
1352 std::input_iterator_tag,
1353 typename std::iterator_traits<InputIt>::iterator_category>>>
1354 void insertOrAssignSemantics(Index node, InputIt first, InputIt last)
1355 {
1356 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1357 derived().apply(
1358 node,
1359 [this, first, last](Index node) {
1360 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last);
1361 },
1362 [this, first, last](pos_t pos) {
1363 semantics_[pos].semantic_set.insertOrAssign(first, last);
1364 });
1365 } else {
1366 for (offset_t i{}; i != N; ++i) {
1367 insertOrAssignSemantics(derived().child(node, i), first, last);
1368 }
1369 }
1370 }
1371
1372 template <class InputIt,
1373 typename = std::enable_if_t<std::is_base_of_v<
1374 std::input_iterator_tag,
1375 typename std::iterator_traits<InputIt>::iterator_category>>>
1376 Node insertOrAssignSemantics(Node node, InputIt first, InputIt last,
1377 bool propagate = true)
1378 {
1379 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1380 return derived().apply(
1381 node,
1382 [this, first, last](Index node) {
1383 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last);
1384 },
1385 [this, first, last](pos_t pos) {
1386 semantics_[pos].semantic_set.insertOrAssign(first, last);
1387 },
1388 propagate);
1389 } else {
1390 for (offset_t i{}; i != N; ++i) {
1391 insertOrAssignSemantics(derived().child(node, i), first, last, propagate);
1392 }
1393 return node;
1394 }
1395 }
1396
1397 template <class InputIt,
1398 typename = std::enable_if_t<std::is_base_of_v<
1399 std::input_iterator_tag,
1400 typename std::iterator_traits<InputIt>::iterator_category>>>
1401 Node insertOrAssignSemantics(Code code, InputIt first, InputIt last,
1402 bool propagate = true)
1403 {
1404 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1405 return derived().apply(
1406 code,
1407 [this, first, last](Index node) {
1408 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last);
1409 },
1410 [this, first, last](pos_t pos) {
1411 semantics_[pos].semantic_set.insertOrAssign(first, last);
1412 },
1413 propagate);
1414 } else {
1415 for (offset_t i{}; i != N; ++i) {
1416 insertOrAssignSemantics(code.child(i), first, last, propagate);
1417 }
1418 return derived()(code);
1419 }
1420 }
1421
1422 template <class InputIt,
1423 typename = std::enable_if_t<std::is_base_of_v<
1424 std::input_iterator_tag,
1425 typename std::iterator_traits<InputIt>::iterator_category>>>
1426 Node insertOrAssignSemantics(Key key, InputIt first, InputIt last,
1427 bool propagate = true)
1428 {
1429 return insertOrAssignSemantics(derived().toCode(key), first, last, propagate);
1430 }
1431
1432 template <class InputIt,
1433 typename = std::enable_if_t<std::is_base_of_v<
1434 std::input_iterator_tag,
1435 typename std::iterator_traits<InputIt>::iterator_category>>>
1436 Node insertOrAssignSemantics(Point coord, InputIt first, InputIt last,
1437 bool propagate = true, depth_t depth = 0)
1438 {
1439 return insertOrAssignSemantics(derived().toCode(coord, depth), first, last,
1440 propagate);
1441 }
1442
1443 Node insertOrAssignSemantics(Node node, std::initializer_list<Semantic> ilist,
1444 bool propagate = true)
1445 {
1446 return insertOrAssignSemantics(node, std::begin(ilist), std::end(ilist), propagate);
1447 }
1448
1449 Node insertOrAssignSemantics(Code code, std::initializer_list<Semantic> ilist,
1450 bool propagate = true)
1451 {
1452 return insertOrAssignSemantics(code, std::begin(ilist), std::end(ilist), propagate);
1453 }
1454
1455 Node insertOrAssignSemantics(Key key, std::initializer_list<Semantic> ilist,
1456 bool propagate = true)
1457 {
1458 return insertOrAssignSemantics(derived().toCode(key), std::begin(ilist),
1459 std::end(ilist), propagate);
1460 }
1461
1462 Node insertOrAssignSemantics(Point coord, std::initializer_list<Semantic> ilist,
1463 bool propagate = true, depth_t depth = 0)
1464 {
1465 return insertOrAssignSemantics(derived().toCode(coord, depth), std::begin(ilist),
1466 std::end(ilist), propagate);
1467 }
1468
1469 template <class UnaryFunction,
1470 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1471 void insertOrAssignSemantics(Index node, label_t label, UnaryFunction f)
1472 {
1473 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1474 derived().apply(
1475 node,
1476 [this, label, f](Index node) {
1477 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label, f);
1478 },
1479 [this, label, f](pos_t pos) {
1480 semantics_[pos].semantic_set.insertOrAssign(label, f);
1481 });
1482 } else {
1483 for (offset_t i{}; i != N; ++i) {
1484 insertOrAssignSemantics(derived().child(node, i), label, f);
1485 }
1486 }
1487 }
1488
1489 template <class UnaryFunction,
1490 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1491 Node insertOrAssignSemantics(Node node, label_t label, UnaryFunction f,
1492 bool propagate = true)
1493 {
1494 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1495 return derived().apply(
1496 node,
1497 [this, label, f](Index node) {
1498 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label, f);
1499 },
1500 [this, label, f](pos_t pos) {
1501 semantics_[pos].semantic_set.insertOrAssign(label, f);
1502 },
1503 propagate);
1504 } else {
1505 for (offset_t i{}; i != N; ++i) {
1506 insertOrAssignSemantics(derived().child(node, i), label, f, propagate);
1507 }
1508 return node;
1509 }
1510 }
1511
1512 template <class UnaryFunction,
1513 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1514 Node insertOrAssignSemantics(Code code, label_t label, UnaryFunction f,
1515 bool propagate = true)
1516 {
1517 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1518 return derived().apply(
1519 code,
1520 [this, label, f](Index node) {
1521 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, label, f);
1522 },
1523 [this, label, f](pos_t pos) {
1524 semantics_[pos].semantic_set.insertOrAssign(label, f);
1525 },
1526 propagate);
1527 } else {
1528 for (offset_t i{}; i != N; ++i) {
1529 insertOrAssignSemantics(code.child(i), label, f, propagate);
1530 }
1531 return derived()(code);
1532 }
1533 }
1534
1535 template <class UnaryFunction,
1536 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1537 Node insertOrAssignSemantics(Key key, label_t label, UnaryFunction f,
1538 bool propagate = true)
1539 {
1540 return insertOrAssignSemantics(derived().toCode(key), label, f, propagate);
1541 }
1542
1543 template <class UnaryFunction,
1544 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1545 Node insertOrAssignSemantics(Point coord, label_t label, UnaryFunction f,
1546 bool propagate = true, depth_t depth = 0)
1547 {
1548 return insertOrAssignSemantics(derived().toCode(coord, depth), label, f, propagate);
1549 }
1550
1551 template <class InputIt, class UnaryFunction,
1552 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1553 typename = std::enable_if_t<std::is_base_of_v<
1554 std::input_iterator_tag,
1555 typename std::iterator_traits<InputIt>::iterator_category>>>
1556 void insertOrAssignSemantics(Index node, InputIt first, InputIt last, UnaryFunction f)
1557 {
1558 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1559 derived().apply(
1560 node,
1561 [this, first, last, f](Index node) {
1562 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last, f);
1563 },
1564 [this, first, last, f](pos_t pos) {
1565 semantics_[pos].semantic_set.insertOrAssign(first, last, f);
1566 });
1567 } else {
1568 for (offset_t i{}; i != N; ++i) {
1569 insertOrAssignSemantics(derived().child(node, i), first, last, f);
1570 }
1571 }
1572 }
1573
1574 template <class InputIt, class UnaryFunction,
1575 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1576 typename = std::enable_if_t<std::is_base_of_v<
1577 std::input_iterator_tag,
1578 typename std::iterator_traits<InputIt>::iterator_category>>>
1579 Node insertOrAssignSemantics(Node node, InputIt first, InputIt last, UnaryFunction f,
1580 bool propagate = true)
1581 {
1582 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1583 return derived().apply(
1584 node,
1585 [this, first, last, f](Index node) {
1586 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last, f);
1587 },
1588 [this, first, last, f](pos_t pos) {
1589 semantics_[pos].semantic_set.insertOrAssign(first, last, f);
1590 },
1591 propagate);
1592 } else {
1593 for (offset_t i{}; i != N; ++i) {
1594 insertOrAssignSemantics(derived().child(node, i), first, last, f, propagate);
1595 }
1596 return node;
1597 }
1598 }
1599
1600 template <class InputIt, class UnaryFunction,
1601 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1602 typename = std::enable_if_t<std::is_base_of_v<
1603 std::input_iterator_tag,
1604 typename std::iterator_traits<InputIt>::iterator_category>>>
1605 Node insertOrAssignSemantics(Code code, InputIt first, InputIt last, UnaryFunction f,
1606 bool propagate = true)
1607 {
1608 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1609 return derived().apply(
1610 code,
1611 [this, first, last, f](Index node) {
1612 semantics_[node.pos].semantic_set.insertOrAssign(node.offset, first, last, f);
1613 },
1614 [this, first, last, f](pos_t pos) {
1615 semantics_[pos].semantic_set.insertOrAssign(first, last, f);
1616 },
1617 propagate);
1618 } else {
1619 for (offset_t i{}; i != N; ++i) {
1620 insertOrAssignSemantics(code.child(i), first, last, f, propagate);
1621 }
1622 return derived()(code);
1623 }
1624 }
1625
1626 template <class InputIt, class UnaryFunction,
1627 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1628 typename = std::enable_if_t<std::is_base_of_v<
1629 std::input_iterator_tag,
1630 typename std::iterator_traits<InputIt>::iterator_category>>>
1631 Node insertOrAssignSemantics(Key key, InputIt first, InputIt last, UnaryFunction f,
1632 bool propagate = true)
1633 {
1634 return insertOrAssignSemantics(derived().toCode(key), first, last, f, propagate);
1635 }
1636
1637 template <class InputIt, class UnaryFunction,
1638 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1639 typename = std::enable_if_t<std::is_base_of_v<
1640 std::input_iterator_tag,
1641 typename std::iterator_traits<InputIt>::iterator_category>>>
1642 Node insertOrAssignSemantics(Point coord, InputIt first, InputIt last, UnaryFunction f,
1643 bool propagate = true, depth_t depth = 0)
1644 {
1645 return insertOrAssignSemantics(derived().toCode(coord, depth), first, last, f,
1646 propagate);
1647 }
1648
1649 template <class UnaryFunction,
1650 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1651 Node insertOrAssignSemantics(Node node, std::initializer_list<label_t> ilist,
1652 UnaryFunction f, bool propagate = true)
1653 {
1654 return insertOrAssignSemantics(node, std::begin(ilist), std::end(ilist), f,
1655 propagate);
1656 }
1657
1658 template <class UnaryFunction,
1659 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1660 Node insertOrAssignSemantics(Code code, std::initializer_list<label_t> ilist,
1661 UnaryFunction f, bool propagate = true)
1662 {
1663 return insertOrAssignSemantics(code, std::begin(ilist), std::end(ilist), f,
1664 propagate);
1665 }
1666
1667 template <class UnaryFunction,
1668 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1669 Node insertOrAssignSemantics(Key key, std::initializer_list<label_t> ilist,
1670 UnaryFunction f, bool propagate = true)
1671 {
1672 return insertOrAssignSemantics(derived().toCode(key), std::begin(ilist),
1673 std::end(ilist), f, propagate);
1674 }
1675
1676 template <class UnaryFunction,
1677 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1678 Node insertOrAssignSemantics(Point coord, std::initializer_list<label_t> ilist,
1679 UnaryFunction f, bool propagate = true, depth_t depth = 0)
1680 {
1681 return insertOrAssignSemantics(derived().toCode(coord, depth), std::begin(ilist),
1682 std::end(ilist), f, propagate);
1683 }
1684
1685 //
1686 // Assign
1687 //
1688 void assignSemantics(Index node, std::string const& tag, value_t value)
1689 {
1690 assignSemantics(node, labels(tag), value);
1691 }
1692
1693 Node assignSemantics(Node node, std::string const& tag, value_t value,
1694 bool propagate = true)
1695 {
1696 return assignSemantics(node, labels(tag), value);
1697 }
1698
1699 Node assignSemantics(Code code, std::string const& tag, value_t value,
1700 bool propagate = true)
1701 {
1702 return assignSemantics(code, labels(tag), value);
1703 }
1704
1705 Node assignSemantics(Key key, std::string const& tag, value_t value,
1706 bool propagate = true)
1707 {
1708 return assignSemantics(derived().toCode(key), tag, value, propagate);
1709 }
1710
1711 Node assignSemantics(Point coord, std::string const& tag, value_t value,
1712 bool propagate = true, depth_t depth = 0)
1713 {
1714 return assignSemantics(derived().toCode(coord, depth), tag, value, propagate);
1715 }
1716
1717 template <class UnaryFunction,
1718 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1719 void assignSemantics(Index node, std::string const& tag, UnaryFunction f)
1720 {
1721 assignSemantics(node, labels(tag), f);
1722 }
1723
1724 template <class UnaryFunction,
1725 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1726 Node assignSemantics(Node node, std::string const& tag, UnaryFunction f,
1727 bool propagate = true)
1728 {
1729 return assignSemantics(node, labels(tag), f);
1730 }
1731
1732 template <class UnaryFunction,
1733 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1734 Node assignSemantics(Code code, std::string const& tag, UnaryFunction f,
1735 bool propagate = true)
1736 {
1737 return assignSemantics(code, labels(tag), f);
1738 }
1739
1740 template <class UnaryFunction,
1741 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1742 Node assignSemantics(Key key, std::string const& tag, UnaryFunction f,
1743 bool propagate = true)
1744 {
1745 return assignSemantics(derived().toCode(key), tag, f, propagate);
1746 }
1747
1748 template <class UnaryFunction,
1749 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1750 Node assignSemantics(Point coord, std::string const& tag, UnaryFunction f,
1751 bool propagate = true, depth_t depth = 0)
1752 {
1753 return assignSemantics(derived().toCode(coord, depth), tag, f, propagate);
1754 }
1755
1756 Node assignSemantics(Node node, SemanticRange range, value_t value,
1757 bool propagate = true)
1758 {
1759 return assignSemantics(node, SemanticRangeSet(range), value, propagate);
1760 }
1761
1762 Node assignSemantics(Code code, SemanticRange range, value_t value,
1763 bool propagate = true)
1764 {
1765 return assignSemantics(code, SemanticRangeSet(range), value, propagate);
1766 }
1767
1768 Node assignSemantics(Key key, SemanticRange range, value_t value, bool propagate = true)
1769 {
1770 return assignSemantics(derived().toCode(key), range, value, propagate);
1771 }
1772
1773 Node assignSemantics(Point coord, SemanticRange range, value_t value,
1774 bool propagate = true, depth_t depth = 0)
1775 {
1776 return assignSemantics(derived().toCode(coord, depth), range, value, propagate);
1777 }
1778
1779 void assignSemantics(Index node, SemanticRangeSet const& ranges, value_t value)
1780 {
1781 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1782 derived().apply(
1783 node,
1784 [this, ranges, value](Index node) {
1785 semantics_[node.pos].semantic_set.assign(node.offset, ranges, value);
1786 },
1787 [this, ranges, value](pos_t pos) {
1788 semantics_[pos].semantic_set.insertOrAssign(ranges, value);
1789 });
1790 } else {
1791 for (offset_t i{}; i != N; ++i) {
1792 assignSemantics(derived().child(node, i), ranges, value);
1793 }
1794 }
1795 }
1796
1797 Node assignSemantics(Node node, SemanticRangeSet const& ranges, value_t value,
1798 bool propagate = true)
1799 {
1800 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1801 return derived().apply(
1802 node,
1803 [this, ranges, value](Index node) {
1804 semantics_[node.pos].semantic_set.assign(node.offset, ranges, value);
1805 },
1806 [this, ranges, value](pos_t pos) {
1807 semantics_[pos].semantic_set.insertOrAssign(ranges, value);
1808 }),
1809 propagate;
1810 } else {
1811 for (offset_t i{}; i != N; ++i) {
1812 assignSemantics(derived().child(node, i), ranges, value, propagate);
1813 }
1814 return node;
1815 }
1816 }
1817
1818 Node assignSemantics(Code code, SemanticRangeSet const& ranges, value_t value,
1819 bool propagate = true)
1820 {
1821 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1822 return derived().apply(
1823 code,
1824 [this, ranges, value](Index node) {
1825 semantics_[node.pos].semantic_set.assign(node.offset, ranges, value);
1826 },
1827 [this, ranges, value](pos_t pos) {
1828 semantics_[pos].semantic_set.assign(ranges, value);
1829 },
1830 propagate);
1831 } else {
1832 for (offset_t i{}; i != N; ++i) {
1833 assignSemantics(code.child(i), ranges, value, propagate);
1834 }
1835 return derived()(code);
1836 }
1837 }
1838
1839 Node assignSemantics(Key key, SemanticRangeSet const& ranges, value_t value,
1840 bool propagate = true)
1841 {
1842 return assignSemantics(derived().toCode(key), ranges, value, propagate);
1843 }
1844
1845 Node assignSemantics(Point coord, SemanticRangeSet const& ranges, value_t value,
1846 bool propagate = true, depth_t depth = 0)
1847 {
1848 return assignSemantics(derived().toCode(coord, depth), ranges, value, propagate);
1849 }
1850
1851 template <class UnaryFunction,
1852 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1853 Node assignSemantics(Node node, SemanticRange range, UnaryFunction f,
1854 bool propagate = true)
1855 {
1856 return assignSemantics(node, SemanticRangeSet(range), f, propagate);
1857 }
1858
1859 template <class UnaryFunction,
1860 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1861 Node assignSemantics(Code code, SemanticRange range, UnaryFunction f,
1862 bool propagate = true)
1863 {
1864 return assignSemantics(code, SemanticRangeSet(range), f, propagate);
1865 }
1866
1867 template <class UnaryFunction,
1868 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1869 Node assignSemantics(Key key, SemanticRange range, UnaryFunction f,
1870 bool propagate = true)
1871 {
1872 return assignSemantics(derived().toCode(key), range, f, propagate);
1873 }
1874
1875 template <class UnaryFunction,
1876 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1877 Node assignSemantics(Point coord, SemanticRange range, UnaryFunction f,
1878 bool propagate = true, depth_t depth = 0)
1879 {
1880 return assignSemantics(derived().toCode(coord, depth), range, f, propagate);
1881 }
1882
1883 template <class UnaryFunction,
1884 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1885 void assignSemantics(Index node, SemanticRangeSet const& ranges, UnaryFunction f)
1886 {
1887 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1888 derived().apply(
1889 node,
1890 [this, ranges, f](Index node) {
1891 semantics_[node.pos].semantic_set.assign(node.offset, ranges, f);
1892 },
1893 [this, ranges, f](pos_t pos) {
1894 semantics_[pos].semantic_set.insertOrAssign(ranges, f);
1895 });
1896 } else {
1897 for (offset_t i{}; i != N; ++i) {
1898 assignSemantics(derived().child(node, i), ranges, f);
1899 }
1900 }
1901 }
1902
1903 template <class UnaryFunction,
1904 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1905 Node assignSemantics(Node node, SemanticRangeSet const& ranges, UnaryFunction f,
1906 bool propagate = true)
1907 {
1908 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1909 return derived().apply(
1910 node,
1911 [this, ranges, f](Index node) {
1912 semantics_[node.pos].semantic_set.assign(node.offset, ranges, f);
1913 },
1914 [this, ranges, f](pos_t pos) {
1915 semantics_[pos].semantic_set.assign(ranges, f);
1916 },
1917 propagate);
1918 } else {
1919 for (offset_t i{}; i != N; ++i) {
1920 assignSemantics(derived().child(node, i), ranges, f, propagate);
1921 }
1922 return node;
1923 }
1924 }
1925
1926 template <class UnaryFunction,
1927 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1928 Node assignSemantics(Code code, SemanticRangeSet const& ranges, UnaryFunction f,
1929 bool propagate = true)
1930 {
1931 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
1932 return derived().apply(
1933 code,
1934 [this, ranges, f](Index node) {
1935 semantics_[node.pos].semantic_set.assign(node.offset, ranges, f);
1936 },
1937 [this, ranges, f](pos_t pos) {
1938 semantics_[pos].semantic_set.assign(ranges, f);
1939 },
1940 propagate);
1941 } else {
1942 for (offset_t i{}; i != N; ++i) {
1943 assignSemantics(code.child(i), ranges, f, propagate);
1944 }
1945 return derived()(code);
1946 }
1947 }
1948
1949 template <class UnaryFunction,
1950 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1951 Node assignSemantics(Key key, SemanticRangeSet const& ranges, UnaryFunction f,
1952 bool propagate = true)
1953 {
1954 return assignSemantics(derived().toCode(key), ranges, f, propagate);
1955 }
1956
1957 template <class UnaryFunction,
1958 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1959 Node assignSemantics(Point coord, SemanticRangeSet const& ranges, UnaryFunction f,
1960 bool propagate = true, depth_t depth = 0)
1961 {
1962 return assignSemantics(derived().toCode(coord, depth), ranges, f, propagate);
1963 }
1964
1965 //
1966 // Erase
1967 //
1968
1969 Node eraseSemantics(label_t label, bool propagate = true)
1970 {
1971 return eraseSemantics(derived().rootCode(), label, propagate);
1972 }
1973
1974 void eraseSemantics(Index node, label_t label)
1975 {
1976 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1977 derived().apply(
1978 node,
1979 [this, label](Index node) {
1980 semantics_[node.pos].semantic_set.erase(node.offset, label);
1981 },
1982 [this, label](pos_t pos) { semantics_[pos].semantic_set.erase(label); });
1983 } else {
1984 for (offset_t i{}; i != N; ++i) {
1985 eraseSemantics(derived().child(node, i), label);
1986 }
1987 }
1988 }
1989
1990 Node eraseSemantics(Node node, label_t label, bool propagate = true)
1991 {
1992 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
1993 return derived().apply(
1994 node,
1995 [this, label](Index node) {
1996 semantics_[node.pos].semantic_set.erase(node.offset, label);
1997 },
1998 [this, label](pos_t pos) { semantics_[pos].semantic_set.erase(label); },
1999 propagate);
2000 } else {
2001 for (offset_t i{}; i != N; ++i) {
2002 eraseSemantics(derived().child(node, i), label, propagate);
2003 }
2004 return node;
2005 }
2006 }
2007
2008 Node eraseSemantics(Code code, label_t label, bool propagate = true)
2009 {
2010 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2011 return derived().apply(
2012 code,
2013 [this, label](Index node) {
2014 semantics_[node.pos].semantic_set.erase(node.offset, label);
2015 },
2016 [this, label](pos_t pos) { semantics_[pos].semantic_set.erase(label); },
2017 propagate);
2018 } else {
2019 for (offset_t i{}; i != N; ++i) {
2020 eraseSemantics(code.child(i), label, propagate);
2021 }
2022 return derived()(code);
2023 }
2024 }
2025
2026 Node eraseSemantics(Key key, label_t label, bool propagate = true)
2027 {
2028 return eraseSemantics(derived().toCode(key), label, propagate);
2029 }
2030
2031 Node eraseSemantics(Point coord, label_t label, bool propagate = true,
2032 depth_t depth = 0)
2033 {
2034 return eraseSemantics(derived().toCode(coord, depth), label, propagate);
2035 }
2036
2037 template <class InputIt,
2038 typename = std::enable_if_t<std::is_base_of_v<
2039 std::input_iterator_tag,
2040 typename std::iterator_traits<InputIt>::iterator_category>>>
2041 Node eraseSemantics(InputIt first, InputIt last, bool propagate = true)
2042 {
2043 return eraseSemantics(derived().rootCode(), first, last, propagate);
2044 }
2045
2046 template <class InputIt,
2047 typename = std::enable_if_t<std::is_base_of_v<
2048 std::input_iterator_tag,
2049 typename std::iterator_traits<InputIt>::iterator_category>>>
2050 Node eraseSemantics(Index node, InputIt first, InputIt last)
2051 {
2052 return eraseSemantics(node, SemanticRangeSet(first, last));
2053 }
2054
2055 template <class InputIt,
2056 typename = std::enable_if_t<std::is_base_of_v<
2057 std::input_iterator_tag,
2058 typename std::iterator_traits<InputIt>::iterator_category>>>
2059 Node eraseSemantics(Node node, InputIt first, InputIt last, bool propagate = true)
2060 {
2061 return eraseSemantics(node, SemanticRangeSet(first, last));
2062 }
2063
2064 template <class InputIt,
2065 typename = std::enable_if_t<std::is_base_of_v<
2066 std::input_iterator_tag,
2067 typename std::iterator_traits<InputIt>::iterator_category>>>
2068 Node eraseSemantics(Code code, InputIt first, InputIt last, bool propagate = true)
2069 {
2070 return eraseSemantics(code, SemanticRangeSet(first, last));
2071 }
2072
2073 template <class InputIt,
2074 typename = std::enable_if_t<std::is_base_of_v<
2075 std::input_iterator_tag,
2076 typename std::iterator_traits<InputIt>::iterator_category>>>
2077 Node eraseSemantics(Key key, InputIt first, InputIt last, bool propagate = true)
2078 {
2079 return eraseSemantics(derived().toCode(key), first, last, propagate);
2080 }
2081
2082 template <class InputIt,
2083 typename = std::enable_if_t<std::is_base_of_v<
2084 std::input_iterator_tag,
2085 typename std::iterator_traits<InputIt>::iterator_category>>>
2086 Node eraseSemantics(Point coord, InputIt first, InputIt last, bool propagate = true,
2087 depth_t depth = 0)
2088 {
2089 return eraseSemantics(derived().toCode(coord, depth), first, last, propagate);
2090 }
2091
2092 Node eraseSemantics(std::initializer_list<label_t> ilist, bool propagate = true)
2093 {
2094 return eraseSemantics(derived().rootCode(), ilist, propagate);
2095 }
2096
2097 void eraseSemantics(Index node, std::initializer_list<label_t> ilist)
2098 {
2099 eraseSemantics(node, std::begin(ilist), std::end(ilist));
2100 }
2101
2102 Node eraseSemantics(Node node, std::initializer_list<label_t> ilist,
2103 bool propagate = true)
2104 {
2105 return eraseSemantics(node, std::begin(ilist), std::end(ilist), propagate);
2106 }
2107
2108 Node eraseSemantics(Code code, std::initializer_list<label_t> ilist,
2109 bool propagate = true)
2110 {
2111 return eraseSemantics(code, std::begin(ilist), std::end(ilist), propagate);
2112 }
2113
2114 Node eraseSemantics(Key key, std::initializer_list<label_t> ilist,
2115 bool propagate = true)
2116 {
2117 return eraseSemantics(derived().toCode(key), ilist, propagate);
2118 }
2119
2120 Node eraseSemantics(Point coord, std::initializer_list<label_t> ilist,
2121 bool propagate = true, depth_t depth = 0)
2122 {
2123 return eraseSemantics(derived().toCode(coord, depth), ilist, propagate);
2124 }
2125
2126 Node eraseSemantics(SemanticRange range, bool propagate = true)
2127 {
2128 return eraseSemantics(derived().rootCode(), range, propagate);
2129 }
2130
2131 void eraseSemantics(Index node, SemanticRange range)
2132 {
2133 eraseSemantics(node, SemanticRangeSet(range));
2134 }
2135
2136 Node eraseSemantics(Node node, SemanticRange range, bool propagate = true)
2137 {
2138 return eraseSemantics(node, SemanticRangeSet(range), propagate);
2139 }
2140
2141 Node eraseSemantics(Code code, SemanticRange range, bool propagate = true)
2142 {
2143 return eraseSemantics(code, SemanticRangeSet(range), propagate);
2144 }
2145
2146 Node eraseSemantics(Key key, SemanticRange range, bool propagate = true)
2147 {
2148 return eraseSemantics(derived().toCode(key), range, propagate);
2149 }
2150
2151 Node eraseSemantics(Point coord, SemanticRange range, bool propagate = true,
2152 depth_t depth = 0)
2153 {
2154 return eraseSemantics(derived().toCode(coord, depth), range, propagate);
2155 }
2156
2157 Node eraseSemantics(SemanticRangeSet const& ranges, bool propagate = true)
2158 {
2159 return eraseSemantics(derived().rootCode(), ranges, propagate);
2160 }
2161
2162 void eraseSemantics(Index node, SemanticRangeSet const& ranges)
2163 {
2164 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2165 derived().apply(
2166 node,
2167 [this, ranges](Index node) {
2168 semantics_[node.pos].semantic_set.erase(node.offset, ranges);
2169 },
2170 [this, ranges](pos_t pos) { semantics_[pos].semantic_set.erase(ranges); });
2171 } else {
2172 for (offset_t i{}; i != N; ++i) {
2173 eraseSemantics(derived().child(node, i), ranges);
2174 }
2175 }
2176 }
2177
2178 Node eraseSemantics(Node node, SemanticRangeSet const& ranges, bool propagate = true)
2179 {
2180 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2181 return derived().apply(
2182 node,
2183 [this, ranges](Index node) {
2184 semantics_[node.pos].semantic_set.erase(node.offset, ranges);
2185 },
2186 [this, ranges](pos_t pos) { semantics_[pos].semantic_set.erase(ranges); },
2187 propagate);
2188 } else {
2189 for (offset_t i{}; i != N; ++i) {
2190 eraseSemantics(derived().child(node, i), ranges, propagate);
2191 }
2192 return node;
2193 }
2194 }
2195
2196 Node eraseSemantics(Code code, SemanticRangeSet const& ranges, bool propagate = true)
2197 {
2198 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2199 return derived().apply(
2200 code,
2201 [this, ranges](Index node) {
2202 semantics_[node.pos].semantic_set.erase(node.offset, ranges);
2203 },
2204 [this, ranges](pos_t pos) { semantics_[pos].semantic_set.erase(ranges); },
2205 propagate);
2206 } else {
2207 for (offset_t i{}; i != N; ++i) {
2208 eraseSemantics(code.child(i), ranges, propagate);
2209 }
2210 return derived()(code);
2211 }
2212 }
2213
2214 Node eraseSemantics(Key key, SemanticRangeSet const& ranges, bool propagate = true)
2215 {
2216 return eraseSemantics(derived().toCode(key), ranges, propagate);
2217 }
2218
2219 Node eraseSemantics(Point coord, SemanticRangeSet const& ranges, bool propagate = true,
2220 depth_t depth = 0)
2221 {
2222 return eraseSemantics(derived().toCode(coord, depth), ranges, propagate);
2223 }
2224
2225 Node eraseSemantics(std::string const& tag, bool propagate = true)
2226 {
2227 return eraseSemantics(derived().rootCode(), tag, propagate);
2228 }
2229
2230 void eraseSemantics(Index node, std::string const& tag)
2231 {
2232 eraseSemantics(node, labels(tag));
2233 }
2234
2235 Node eraseSemantics(Node node, std::string const& tag, bool propagate = true)
2236 {
2237 return eraseSemantics(node, labels(tag));
2238 }
2239
2240 Node eraseSemantics(Code code, std::string const& tag, bool propagate = true)
2241 {
2242 return eraseSemantics(code, labels(tag));
2243 }
2244
2245 Node eraseSemantics(Key key, std::string const& tag, bool propagate = true)
2246 {
2247 return eraseSemantics(derived().toCode(key), tag, propagate);
2248 }
2249
2250 Node eraseSemantics(Point coord, std::string const& tag, bool propagate = true,
2251 depth_t depth = 0)
2252 {
2253 return eraseSemantics(derived().toCode(coord, depth), tag, propagate);
2254 }
2255
2256 //
2257 // Erase if
2258 //
2259
2260 template <class UnaryPredicate,
2261 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2262 Node eraseIfSemantics(UnaryPredicate p, bool propagate = true)
2263 {
2264 return eraseIfSemantics(derived().rootCode(), p, propagate);
2265 }
2266
2267 template <class UnaryPredicate,
2268 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2269 void eraseIfSemantics(Index node, UnaryPredicate p)
2270 {
2271 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2272 derived().apply(
2273 node,
2274 [this, p](Index node) {
2275 semantics_[node.pos].semantic_set.eraseIf(node.offset, p);
2276 },
2277 [this, p](pos_t pos) { semantics_[pos].semantic_set.eraseIf(p); });
2278 } else {
2279 for (offset_t i{}; i != N; ++i) {
2280 eraseIfSemantics(derived().child(node, i), p);
2281 }
2282 }
2283 }
2284
2285 template <class UnaryPredicate,
2286 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2287 Node eraseIfSemantics(Node node, UnaryPredicate p, bool propagate = true)
2288 {
2289 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2290 return derived().apply(
2291 node,
2292 [this, p](Index node) {
2293 semantics_[node.pos].semantic_set.eraseIf(node.offset, p);
2294 },
2295 [this, p](pos_t pos) { semantics_[pos].semantic_set.eraseIf(p); }, propagate);
2296 } else {
2297 for (offset_t i{}; i != N; ++i) {
2298 eraseIfSemantics(derived().child(node, i), p, propagate);
2299 }
2300 return node;
2301 }
2302 }
2303
2304 template <class UnaryPredicate,
2305 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2306 Node eraseIfSemantics(Code code, UnaryPredicate p, bool propagate = true)
2307 {
2308 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2309 return derived().apply(
2310 code,
2311 [this, p](Index node) {
2312 semantics_[node.pos].semantic_set.eraseIf(node.offset, p);
2313 },
2314 [this, p](pos_t pos) { semantics_[pos].semantic_set.eraseIf(p); }, propagate);
2315 } else {
2316 for (offset_t i{}; i != N; ++i) {
2317 eraseIfSemantics(code.child(i), p, propagate);
2318 }
2319 return derived()(code);
2320 }
2321 }
2322
2323 template <class UnaryPredicate,
2324 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2325 Node eraseIfSemantics(Key key, UnaryPredicate p, bool propagate = true)
2326 {
2327 return eraseIfSemantics(derived().toCode(key), p, propagate);
2328 }
2329
2330 template <class UnaryPredicate,
2331 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2332 Node eraseIfSemantics(Point coord, UnaryPredicate p, bool propagate = true,
2333 depth_t depth = 0)
2334 {
2335 return eraseIfSemantics(derived().toCode(coord, depth), p, propagate);
2336 }
2337
2338 template <class UnaryPredicate,
2339 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2340 Node eraseIfSemantics(std::string const& tag, UnaryPredicate p, bool propagate = true)
2341 {
2342 return eraseIfSemantics(derived().rootCode(), tag, p, propagate);
2343 }
2344
2345 template <class UnaryPredicate,
2346 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2347 void eraseIfSemantics(Index node, std::string const& tag, UnaryPredicate p)
2348 {
2349 eraseIfSemantics(node, labels(tag), p);
2350 }
2351
2352 template <class UnaryPredicate,
2353 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2354 Node eraseIfSemantics(Node node, std::string const& tag, UnaryPredicate p,
2355 bool propagate = true)
2356 {
2357 return eraseIfSemantics(node, labels(tag), p);
2358 }
2359
2360 template <class UnaryPredicate,
2361 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2362 Node eraseIfSemantics(Code code, std::string const& tag, UnaryPredicate p,
2363 bool propagate = true)
2364 {
2365 return eraseIfSemantics(code, labels(tag), p);
2366 }
2367
2368 template <class UnaryPredicate,
2369 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2370 Node eraseIfSemantics(Key key, std::string const& tag, UnaryPredicate p,
2371 bool propagate = true)
2372 {
2373 return eraseIfSemantics(derived().toCode(key), tag, p, propagate);
2374 }
2375
2376 template <class UnaryPredicate,
2377 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2378 Node eraseIfSemantics(Point coord, std::string const& tag, UnaryPredicate p,
2379 bool propagate = true, depth_t depth = 0)
2380 {
2381 return eraseIfSemantics(derived().toCode(coord, depth), tag, p, propagate);
2382 }
2383
2384 template <class UnaryPredicate,
2385 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2386 Node eraseIfSemantics(SemanticRange range, UnaryPredicate p, bool propagate = true)
2387 {
2388 return eraseIfSemantics(derived().rootCode(), range, p, propagate);
2389 }
2390
2391 template <class UnaryPredicate,
2392 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2393 void eraseIfSemantics(Index node, SemanticRange range, UnaryPredicate p)
2394 {
2395 eraseIfSemantics(node, SemanticRangeSet(range), p);
2396 }
2397
2398 template <class UnaryPredicate,
2399 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2400 Node eraseIfSemantics(Node node, SemanticRange range, UnaryPredicate p,
2401 bool propagate = true)
2402 {
2403 return eraseIfSemantics(node, SemanticRangeSet(range), p, propagate);
2404 }
2405
2406 template <class UnaryPredicate,
2407 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2408 Node eraseIfSemantics(Code code, SemanticRange range, UnaryPredicate p,
2409 bool propagate = true)
2410 {
2411 return eraseIfSemantics(code, SemanticRangeSet(range), p, propagate);
2412 }
2413
2414 template <class UnaryPredicate,
2415 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2416 Node eraseIfSemantics(Key key, SemanticRange range, UnaryPredicate p,
2417 bool propagate = true)
2418 {
2419 return eraseIfSemantics(derived().toCode(key), range, p, propagate);
2420 }
2421
2422 template <class UnaryPredicate,
2423 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2424 Node eraseIfSemantics(Point coord, SemanticRange range, UnaryPredicate p,
2425 bool propagate = true, depth_t depth = 0)
2426 {
2427 return eraseIfSemantics(derived().toCode(coord, depth), range, p, propagate);
2428 }
2429
2430 template <class UnaryPredicate,
2431 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2432 Node eraseIfSemantics(SemanticRangeSet const& ranges, UnaryPredicate p,
2433 bool propagate = true)
2434 {
2435 return eraseIfSemantics(derived().rootCode(), ranges, p, propagate);
2436 }
2437
2438 template <class UnaryPredicate,
2439 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2440 void eraseIfSemantics(Index node, SemanticRangeSet const& ranges, UnaryPredicate p)
2441 {
2442 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2443 derived().apply(
2444 node,
2445 [this, ranges, p](Index node) {
2446 semantics_[node.pos].semantic_set.eraseIf(node.offset, ranges, p);
2447 },
2448 [this, ranges, p](pos_t pos) {
2449 semantics_[pos].semantic_set.eraseIf(ranges, p);
2450 });
2451 } else {
2452 for (offset_t i{}; i != N; ++i) {
2453 eraseIfSemantics(derived().child(node, i), ranges, p);
2454 }
2455 }
2456 }
2457
2458 template <class UnaryPredicate,
2459 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2460 Node eraseIfSemantics(Node node, SemanticRangeSet const& ranges, UnaryPredicate p,
2461 bool propagate = true)
2462 {
2463 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2464 return derived().apply(
2465 node,
2466 [this, ranges, p](Index node) {
2467 semantics_[node.pos].semantic_set.eraseIf(node.offset, ranges, p);
2468 },
2469 [this, ranges, p](pos_t pos) {
2470 semantics_[pos].semantic_set.eraseIf(ranges, p);
2471 },
2472 propagate);
2473 } else {
2474 for (offset_t i{}; i != N; ++i) {
2475 eraseIfSemantics(derived().child(node, i), ranges, p, propagate);
2476 }
2477 return node;
2478 }
2479 }
2480
2481 template <class UnaryPredicate,
2482 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2483 Node eraseIfSemantics(Code code, SemanticRangeSet const& ranges, UnaryPredicate p,
2484 bool propagate = true)
2485 {
2486 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2487 return derived().apply(
2488 code,
2489 [this, ranges, p](Index node) {
2490 semantics_[node.pos].semantic_set.eraseIf(node.offset, ranges, p);
2491 },
2492 [this, ranges, p](pos_t pos) {
2493 semantics_[pos].semantic_set.eraseIf(ranges, p);
2494 },
2495 propagate);
2496 } else {
2497 for (offset_t i{}; i != N; ++i) {
2498 eraseIfSemantics(code.child(i), ranges, p, propagate);
2499 }
2500 return derived()(code);
2501 }
2502 }
2503
2504 template <class UnaryPredicate,
2505 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2506 Node eraseIfSemantics(Key key, SemanticRangeSet const& ranges, UnaryPredicate p,
2507 bool propagate = true)
2508 {
2509 return eraseIfSemantics(derived().toCode(key), ranges, p, propagate);
2510 }
2511
2512 template <class UnaryPredicate,
2513 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
2514 Node eraseIfSemantics(Point coord, SemanticRangeSet const& ranges, UnaryPredicate p,
2515 bool propagate = true, depth_t depth = 0)
2516 {
2517 return eraseIfSemantics(derived().toCode(coord, depth), ranges, p, propagate);
2518 }
2519
2520 //
2521 // Clear
2522 //
2523
2524 void clearImpl()
2525 {
2526 semantics_.resize(1);
2527 semantics_.assign(1, Data());
2528 }
2529
2530 void clearImpl(pos_t block)
2531 {
2532 semantics_[block].semantic_set.clear();
2533 semantics_[block].summary = Semantic();
2534 }
2535
2536 void clearSemantics(bool propagate = true)
2537 {
2538 clearSemantics(derived().rootCode(), propagate);
2539 }
2540
2541 void clearSemantics(Index node)
2542 {
2543 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2544 derived().apply(
2545 node,
2546 [this](Index node) {
2547 if (derived().isPureLeaf(node)) {
2548 semantics_[node.pos].semantic_set.clear(node.offset);
2549 }
2550 },
2551 [this](pos_t block) { clearImpl(block); });
2552 } else {
2553 for (offset_t i{}; i != N; ++i) {
2554 clearSemantics(derived().child(node, i));
2555 }
2556 }
2557 }
2558
2559 void clearSemantics(Node node, bool propagate = true)
2560 {
2561 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2562 derived().apply(
2563 node,
2564 [this](Index node) {
2565 if (derived().isPureLeaf(node)) {
2566 semantics_[node.pos].semantic_set.clear(node.offset);
2567 }
2568 },
2569 [this](pos_t block) { clearImpl(block); }, propagate);
2570 } else {
2571 for (offset_t i{}; i != N; ++i) {
2572 clearSemantics(derived().child(node, i), propagate);
2573 }
2574 }
2575 }
2576
2577 void clearSemantics(Code code, bool propagate = true)
2578 {
2579 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2580 derived().apply(
2581 code,
2582 [this](Index node) {
2583 if (derived().isPureLeaf(node)) {
2584 semantics_[node.pos].semantic_set.clear(node.offset);
2585 }
2586 },
2587 [this](pos_t block) { clearImpl(block); }, propagate);
2588 } else {
2589 for (offset_t i{}; i != N; ++i) {
2590 clearSemantics(code.child(i), propagate);
2591 }
2592 }
2593 }
2594
2595 void clearSemantics(Key key, bool propagate = true)
2596 {
2597 clearSemantics(derived().toCode(key), propagate);
2598 }
2599
2600 void clearSemantics(Point coord, bool propagate = true, depth_t depth = 0)
2601 {
2602 clearSemantics(derived().toCode(coord, depth), propagate);
2603 }
2604
2605 //
2606 // Change semantic label
2607 //
2608
2609 void changeSemantics(label_t old_label, label_t new_label, bool propagate = true)
2610 {
2611 changeLabel(derived().rootCode(), old_label, new_label, propagate);
2612 }
2613
2614 void changeSemantics(Node node, label_t old_label, label_t new_label)
2615 {
2616 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2617 derived().apply(
2618 node,
2619 [this, old_label, new_label](Index node) {
2620 semantics_[node.pos].semantic_set.changeLabel(node.offset, old_label,
2621 new_label);
2622 },
2623 [this, old_label, new_label](pos_t pos) {
2624 semantics_[pos].semantic_set.changeLabel(old_label, new_label);
2625 });
2626 } else {
2627 for (offset_t i{}; i != N; ++i) {
2628 changeSemantics(derived().child(node, i), old_label, new_label);
2629 }
2630 }
2631 }
2632
2633 void changeSemantics(Node node, label_t old_label, label_t new_label,
2634 bool propagate = true)
2635 {
2636 if (derived().isLeaf(node) || derived().isPureLeaf(node)) {
2637 derived().apply(
2638 node,
2639 [this, old_label, new_label](Index node) {
2640 semantics_[node.pos].semantic_set.changeLabel(node.offset, old_label,
2641 new_label);
2642 },
2643 [this, old_label, new_label](pos_t pos) {
2644 semantics_[pos].semantic_set.changeLabel(old_label, new_label);
2645 },
2646 propagate);
2647 } else {
2648 for (offset_t i{}; i != N; ++i) {
2649 changeSemantics(derived().child(node, i), old_label, new_label, propagate);
2650 }
2651 }
2652 }
2653
2654 void changeSemantics(Code code, label_t old_label, label_t new_label,
2655 bool propagate = true)
2656 {
2657 if (derived().isLeaf(code) || derived().isPureLeaf(code)) {
2658 derived().apply(
2659 code,
2660 [this, old_label, new_label](Index node) {
2661 semantics_[node.pos].semantic_set.changeLabel(node.offset, old_label,
2662 new_label);
2663 },
2664 [this, old_label, new_label](pos_t pos) {
2665 semantics_[pos].semantic_set.changeLabel(old_label, new_label);
2666 },
2667 propagate);
2668 } else {
2669 for (offset_t i{}; i != N; ++i) {
2670 changeSemantics(code.child(i), old_label, new_label, propagate);
2671 }
2672 }
2673 }
2674
2675 void changeSemantics(Key key, label_t old_label, label_t new_label,
2676 bool propagate = true)
2677 {
2678 changeSemantics(derived().toCode(key), old_label, new_label, propagate);
2679 }
2680
2681 void changeSemantics(Point coord, label_t old_label, label_t new_label,
2682 bool propagate = true, depth_t depth = 0)
2683 {
2684 changeSemantics(derived().toCode(coord, depth), old_label, new_label, propagate);
2685 }
2686
2687 //
2688 // Propagation criteria
2689 //
2690
2691 [[nodiscard]] constexpr PropagationCriteria semanticsPropagationCriteria()
2692 const noexcept
2693 {
2694 return prop_criteria_;
2695 }
2696
2697 void setSemanticsPropagationCriteria(PropagationCriteria prop_criteria,
2698 bool propagate = true)
2699 {
2700 if (prop_criteria_ == prop_criteria) {
2701 return;
2702 }
2703
2704 prop_criteria_ = prop_criteria;
2705
2706 derived().setModified();
2707
2708 if (propagate) {
2709 derived().propagateModified();
2710 }
2711 }
2712
2713 protected:
2714 //
2715 // Constructors
2716 //
2717
2718 SemanticSetMap()
2719 {
2720 // semantics_.reserve(10);
2721 semantics_.emplace_back();
2722 };
2723
2724 SemanticSetMap(SemanticSetMap const& other) = default;
2725
2726 SemanticSetMap(SemanticSetMap&& other) = default;
2727
2728 // template <class Derived2>
2729 // SemanticSetMap(SemanticSetMap<Derived2> const& other) : Derived2 // TODO: Fill in
2730 // {
2731 // }
2732
2733 //
2734 // Destructor
2735 //
2736
2737 ~SemanticSetMap() {}
2738
2739 //
2740 // Assignment operator
2741 //
2742
2743 SemanticSetMap& operator=(SemanticSetMap const& rhs) = default;
2744
2745 SemanticSetMap& operator=(SemanticSetMap&& rhs) = default;
2746
2747 template <class Derived2, size_t N2>
2748 SemanticSetMap& operator=(SemanticSetMap<Derived22> const& rhs)
2749 {
2750 // TODO: Fill in
2751 return *this;
2752 }
2753
2754 //
2755 // Swap
2756 //
2757
2758 void swap(SemanticSetMap& other) noexcept
2759 {
2760 std::swap(semantics_, other.semantics_);
2761 std::swap(mapping_, other.mapping_);
2762 std::swap(prop_criteria_, other.prop_criteria_);
2763 }
2764
2765 //
2766 // Derived
2767 //
2768
2769 [[nodiscard]] constexpr Derived& derived() { return *static_cast<Derived*>(this); }
2770
2771 [[nodiscard]] constexpr Derived const& derived() const
2772 {
2773 return *static_cast<Derived const*>(this);
2774 }
2775
2776 //
2777 // Create node block
2778 //
2779
2780 void createBlock(Index node)
2781 {
2782 // TODO: Implement
2783 value_t value_summary{};
2784 switch (...) {
2785 for (auto s : ...) {
2786 value_summary;
2787 }
2788 }
2789 semantics_.emplace_back(semantics_[node.pos].semantics.subset(node.offset),
2790 semantics_[node.pos].label_summary[node.offset],
2791 value_summary);
2792
2793 // TODO: Should the semantics in the parent be removed?
2794 semanticsClear(node);
2795 }
2796
2797 //
2798 // Fill
2799 //
2800
2801 void fill(Index node, pos_t children)
2802 {
2803 // TODO: Implement
2804
2805 switch (semanticsPropagationCriteria()) {
2806 case PropagationCriteria::MIN:
2807 case PropagationCriteria::MAX:
2808 semantics_[children].semantic_set.fill(semantics_[node.pos].semantic_set,
2809 node.offset);
2810 break;
2811 case PropagationCriteria::NONE:
2812 case PropagationCriteria::S_MIN:
2813 case PropagationCriteria::S_MAX:
2814 if (derived().allPureLeaf(children) || derived().allLeaf(children)) {
2815 // transfer semantics to all children
2816 semantics_[children].semantic_set.fill(semantics_[node.pos].semantic_set,
2817 node.offset);
2818 semantics_[children].summary = semantics_[node.pos].summary;
2819 // remove semantics from node since it is now a inner node without semantic set
2820 // can keep the summary
2821 semantics_[node.pos].semantic_set.clear(node.offset);
2822 } else {
2823 // TODO: is fill only called when all children are not parents already?
2824 // can it happen that one of the children is not a leaf?
2825 assert(false);
2826 }
2827 }
2828
2829 // TODO: Should the semantics in the parent be removed?
2830 semanticsClear(node);
2831 }
2832
2833 //
2834 // Resize
2835 //
2836
2837 void resize(std::size_t count) { semantics_.resize(count); }
2838
2839 //
2840 // Reserve
2841 //
2842
2843 void reserveImpl(std::size_t new_cap) { semantics_.reserve(new_cap); }
2844
2845 //
2846 // Initilize root
2847 //
2848
2849 void initRoot()
2850 {
2851 // semanticNode(derived().root()).clear();
2852 // auto node = derived().rootIndex();
2853 // semantics_[node.pos].clear();
2854 clearImpl();
2855 }
2856
2857 //
2858 // Update block
2859 //
2860
2861 void updateBlock(pos_t block, std::array<bool, N> modified_parent)
2862 {
2863 // TODO: Can we have this here?
2864 if (derived().noneParent(block)) {
2865 return;
2866 }
2867
2868 for (offset_t i{}; N != i; ++i) {
2869 Index node{block, i};
2870 if (modified_parent[i]) {
2871 updateNode(node, derived().children(node));
2872 }
2873 }
2874
2875 auto children = derived().children(block);
2876 // TODO constexpr 1 == N
2877 switch (semanticsPropagationCriteria()) {
2878 case PropagationCriteria::NONE: {
2879 break;
2880 }
2881 case PropagationCriteria::S_MAX: {
2882 // if nodes is leaf or pure leaf -> no offset has children
2883 // update its summary: or all semantics in each offset of nodes and put it into
2884 // summary of nodes
2885
2886 // if nodes is inner node -> some offset might be a parent, some might be a Leaf
2887 // or pure leaf or summary of all children that are not NULLPOS (offset is parent,
2888 // we can use summary of child) and put it into summary of nodes if NULLPOS
2889 // (offset is not a parent, no summary we can use here) we need to look at
2890 // semantics, take care of max
2891
2892 // TODO: possible improvement, check if all pure leaf or leaf, can treat all
2893 // semantics at the same time
2894
2895 label_t summary_label = 0;
2896 value_t summary_value = std::numeric_limits<value_t>::min();
2897
2898 for (offset_t i{}; i != N; ++i) {
2899 pos_t child = children[i];
2900 if (child == NULL_POS) {
2901 // i is not a parent, look at semantics of i
2902 std::vector vec(semantics_[block].semantic_set.begin(i),
2903 semantics_[block].semantic_set.end(i));
2904 if (!vec.empty()) {
2905 // keep max value of all semantics
2906 std::sort(std::begin(vec), std::end(vec),
2907 [](auto a, auto b) { return a.value > b.value; });
2908 summary_value = std::max(summary_value, vec.front().value);
2909
2910 // make the summary or
2911 auto last = std::unique(std::begin(vec), std::end(vec),
2912 [](auto a, auto b) { return a.label == b.label; });
2913
2914 label_t label = 0;
2915 for (auto it = vec.begin(); it != last; ++it) {
2916 label |= it->label;
2917 }
2918 summary_label |= label;
2919 }
2920 } else {
2921 // i is parent, look at summary of child
2922 summary_label |= semantics_[child].summary.label;
2923 summary_value = std::max(summary_value, semantics_[child].summary.value);
2924 }
2925 }
2926
2927 semantics_[block].summary.label = summary_label;
2928 semantics_[block].summary.value = summary_value;
2929
2930 break;
2931 }
2932 case PropagationCriteria::S_MIN: {
2933 label_t summary_label = 0;
2934 value_t summary_value = std::numeric_limits<value_t>::max();
2935
2936 for (offset_t i{}; i != N; ++i) {
2937 pos_t child = children[i];
2938 if (child == NULL_POS) {
2939 // i is not a parent, look at semantics of i
2940 std::vector vec(semantics_[block].semantic_set.begin(i),
2941 semantics_[block].semantic_set.end(i));
2942
2943 if (!vec.empty()) {
2944 // keep min value of all semantics
2945 std::sort(std::begin(vec), std::end(vec),
2946 [](auto a, auto b) { return a.value < b.value; });
2947 summary_value = std::min(summary_value, vec.front().value);
2948
2949 // make the summary or
2950 auto last = std::unique(std::begin(vec), std::end(vec),
2951 [](auto a, auto b) { return a.label == b.label; });
2952
2953 label_t label = 0;
2954 for (auto it = vec.begin(); it != last; ++it) {
2955 label |= it->label;
2956 }
2957 summary_label |= label;
2958 }
2959 } else {
2960 // i is parent, look at summary of child
2961 summary_label |= semantics_[child].summary.label;
2962 summary_value = std::min(summary_value, semantics_[child].summary.value);
2963 }
2964 }
2965
2966 semantics_[block].summary.label = summary_label;
2967 semantics_[block].summary.value = summary_value;
2968
2969 break;
2970 }
2971 case PropagationCriteria::MIN: {
2972 // label_t summary_label = 0;
2973 // value_t summary_value = std::numeric_limits<value_t>::max();
2974
2975 for (offset_t i{}; i != N; ++i) {
2976 pos_t child = children[i];
2977 if (child == NULL_POS) {
2978 continue;
2979 }
2980
2981 std::vector vec(semantics_[child].semantic_set.begin(),
2982 semantics_[child].semantic_set.end());
2983 std::sort(std::begin(vec), std::end(vec), [](auto a, auto b) {
2984 return a.label < b.label || (a.label == b.label && a.value < b.value);
2985 });
2986 // summary_value = std::min(summary_value, vec.front().value);
2987
2988 auto r_last = std::unique(std::begin(vec), std::end(vec),
2989 [](auto a, auto b) { return a.label == b.label; });
2990 // auto first = r_last.base();
2991 // auto last = std::end(vec);
2992 semantics_[block].semantic_set.set(i, std::begin(vec), r_last);
2993
2994 // // summary
2995 // label_t label = 0;
2996 // for (auto it = vec.begin(); it != last; ++it) {
2997 // label |= it->label;
2998 // }
2999 // summary_label |= label;
3000 }
3001
3002 // semantics_[nodes].summary.label = summary_label;
3003 // semantics_[nodes].summary.value = summary_value;
3004 break;
3005 }
3006 case PropagationCriteria::MAX: {
3007 // label_t summary_label = 0;
3008 // value_t summary_value = std::numeric_limits<value_t>::min();
3009
3010 for (offset_t i{}; i != N; ++i) {
3011 pos_t child = children[i];
3012 if (child == NULL_POS) {
3013 continue;
3014 }
3015
3016 std::vector vec(semantics_[child].semantic_set.begin(),
3017 semantics_[child].semantic_set.end());
3018 std::sort(std::begin(vec), std::end(vec), [](auto a, auto b) {
3019 return a.label < b.label || (a.label == b.label && a.value > b.value);
3020 });
3021 // summary_value = std::max(summary_value, vec.front().value);
3022
3023 auto r_last = std::unique(std::begin(vec), std::end(vec),
3024 [](auto a, auto b) { return a.label == b.label; });
3025 // auto first = r_last.base();
3026 // auto last = std::end(vec);
3027 // semantics_[nodes].semantic_set.set(i, first, last);
3028 semantics_[block].semantic_set.set(i, std::begin(vec), r_last);
3029
3030 // // summary
3031 // label_t label = 0;
3032 // for (auto it = vec.begin(); it != last; ++it) {
3033 // label |= it->label;
3034 // }
3035 // summary_label |= label;
3036 }
3037
3038 // semantics_[nodes].summary.label = summary_label;
3039 // semantics_[nodes].summary.value = summary_value;
3040 break;
3041 }
3042 }
3043 }
3044
3045 //
3046 // Is prunable
3047 //
3048
3049 [[nodiscard]] bool isPrunable(pos_t block) const
3050 {
3051 for (offset_t i{1}; N != i; ++i) {
3052 if (!std::equal(
3053 semantics_[block].semantics.begin(0), semantics_[block].semantics.end(0),
3054 semantics_[block].semantics.begin(i), semantics_[block].semantics.end(i))) {
3055 return false;
3056 }
3057 }
3058 return true;
3059 }
3060
3061 void preparePrune(Index node)
3062 {
3063 auto children = derived().children(node);
3064
3065 // move content of children to node, node will be a leaf afterwards and needs the
3066 // actual data
3067 // all children have the same data by definition, so we can just take the first
3068 semantics_[node.pos].semantic_set.set(node.offset,
3069 semantics_[children].semantic_set.begin(0),
3070 semantics_[children].semantic_set.end(0));
3071 }
3072
3073 //
3074 // Memory
3075 //
3076
3077 [[nodiscard]] std::size_t sizeofNodeTimesN(Index node) const
3078 {
3079 // TODO: Implement
3080 }
3081
3082 [[nodiscard]] std::size_t sizeofBlock(pos_t block) const
3083 {
3084 // TODO: Implement
3085 }
3086
3087 [[nodiscard]] static constexpr std::size_t sizeofBlockLowerBound() noexcept
3088 {
3089 return sizeof(typename decltype(semantics_)::value_type);
3090 }
3091
3092 [[nodiscard]] static constexpr std::size_t sizeofMap() noexcept
3093 {
3094 return sizeof(semantics_) + sizeof(mapping_) + sizeof(prop_criteria_);
3095 }
3096
3097 //
3098 // Input/output (read/write)
3099 //
3100
3101 [[nodiscard]] static constexpr MapType mapType() noexcept
3102 {
3103 return MapType::SEMANTIC_SET;
3104 }
3105
3106 template <class Container>
3107 constexpr std::size_t serializedSize(Container const& c) const
3108 {
3109 std::size_t s{};
3110 for (auto const [block, inner_offsets, value_offsets] : c) {
3111 if (value_offsets.none()) {
3112 continue;
3113 }
3114 s += sizeof(std::uint8_t);
3115 if (derived().allLeaf(block)) {
3116 s += semantics_[block].semantics.serializedSize();
3117 } else {
3118 for (offset_t i{}; N != i; ++i) {
3119 if (!value_offsets[i]) {
3120 continue;
3121 }
3122
3123 // This should be correct in both cases
3124 s += semantics_[block].semantics.serializedSize(i);
3125 }
3126 }
3127 }
3128 return s;
3129 }
3130
3131 template <class Container>
3132 void readNodes(ReadBuffer& in, Container const& c)
3133 {
3134 for (auto const [block, inner_offsets, value_offsets] : c) {
3135 if (value_offsets.none()) {
3136 return;
3137 }
3138
3139 std::uint8_t mode;
3140 in.read(&mode, sizeof(mode));
3141 if (0 == mode) {
3142 // All are serialized together
3143 semantics_[block].semantics.read(in, value_offsets);
3144 } else {
3145 // Each serialized seperate
3146
3147 // TODO: Optimize
3148 SemanticSet<1> s;
3149 for (offset_t i{}; N != i; ++i) {
3150 if (!value_offsets[i]) {
3151 continue;
3152 }
3153
3154 s.read(in);
3155 semantics_[block].semantics.set(i, s);
3156 }
3157 }
3158 }
3159 }
3160
3161 template <class BlockRange>
3162 void writeBlocks(WriteBuffer& out, BlockRange const& blocks) const
3163 {
3164 for (auto block : blocks) {
3165 if (value_offsets.none()) {
3166 continue;
3167 }
3168
3169 if (derived().allLeaf(block)) {
3170 std::uint8_t mode = 0; // All serialized together
3171 out.write(&mode, sizeof(mode));
3172 semantics_[block].semantics.write(out);
3173 } else {
3174 std::uint8_t mode = 1; // Each serialized seperate
3175 out.write(&mode, sizeof(mode));
3176
3177 for (offset_t i{}; N != i; ++i) {
3178 if (!value_offsets[i]) {
3179 continue;
3180 }
3181
3182 Index node(block, i);
3183 if (derived().isLeaf(node)) {
3184 semantics_[block].semantics.write(out, i);
3185 } else {
3186 semantics(node).write(out);
3187 }
3188 }
3189 }
3190 }
3191 }
3192
3193 //
3194 // Dot file info
3195 //
3196
3197 void dotFileInfo(std::ostream& out, Index node) const
3198 {
3199 if (derived().isLeaf(node)) {
3200 out << "Semantics: " << semantics(node);
3201 } else {
3202 out << "Semantic Summary: " << semanticsSummary(node);
3203 }
3204 }
3205
3206 protected:
3207 Container<SemanticSetBlock<N>> semantics_;
3208
3209 // Propagation
3210 PropagationCriteria prop_criteria_ = PropagationCriteria::MAX;
3211
3212 template <class Derived2, std::size_t N2>
3213 friend class SemanticSetMap;
3214};
3215} // namespace ufo
3216
3217namespace ufo
3218{
3219//
3220// Type traits
3221//
3222
3223template <class Map>
3225 : std::conditional_t<is_map_type_v<Map, MapType::SEMANTIC_SET>, std::true_type,
3226 std::false_type> {
3227};
3228template <class Map>
3229constexpr inline bool is_semantic_set_map_v = is_semantic_set_map<Map>::value;
3230} // namespace ufo
3231#endif // UFO_MAP_SEMANTIC_MAP_H
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310