Visual Computing Library  devel
Loading...
Searching...
No Matches
element_container.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_MESH_CONTAINERS_BASE_ELEMENT_CONTAINER_H
24#define VCL_MESH_CONTAINERS_BASE_ELEMENT_CONTAINER_H
25
26#include "base.h"
27#include "custom_component_vector_handle.h"
28
29#include "../detail/custom_components_vector_map.h"
30#include "../detail/vertical_components_vector_tuple.h"
31
32#include <vclib/mesh/components/base/component.h>
33#include <vclib/mesh/components/custom_components.h>
34#include <vclib/mesh/elements/base/element.h>
35#include <vclib/mesh/iterators/element_container_iterator.h>
36
37#include <vclib/base.h>
38
39#include <vector>
40
41namespace vcl::mesh {
42
44template<ElementConcept T>
45class ElementContainer : public ElementContainerTriggerer
46{
47 template<ElementConcept U>
48 friend class ElementContainer;
49
50 using ElementContainerType = ElementContainer<T>;
51
52 // filter components of elements, taking only vertical ones
53 using VertComps = FilterTypesByCondition<
54 comp::IsVerticalComponentPred,
55 typename T::Components>::type;
56
57public:
58 using ElementType = T;
59 using ParentMeshType = T::ParentMeshType;
60
61protected:
62 ParentMeshType* mParentMesh = nullptr;
63
69 uint mElemNumber = 0;
70
76 std::vector<T> mElemVec;
77
83 detail::VerticalComponentsVectorTuple<VertComps> mVerticalCompVecTuple;
84
89 detail::CustomComponentsVectorMap<comp::HasCustomComponents<T>>
90 mCustomCompVecMap;
91
92public:
93 static const uint ELEMENT_ID = T::ELEMENT_ID;
94
98 ElementContainer() = default;
99
100protected:
101 /* Members that are directly inherited by Containers (just renaming them) */
102 using ElementIterator = ElementContainerIterator<std::vector, T>;
103 using ConstElementIterator = ConstElementContainerIterator<std::vector, T>;
104
116 const T& element(uint i) const
117 {
118 assert(i < mElemVec.size());
119 return mElemVec[i];
120 }
121
133 T& element(uint i)
134 {
135 assert(i < mElemVec.size());
136 return mElemVec[i];
137 }
138
148 uint elementNumber() const { return mElemNumber; }
149
159 uint elementContainerSize() const { return mElemVec.size(); }
160
167 uint deletedElementNumber() const
168 {
169 return elementContainerSize() - elementNumber();
170 }
171
172 uint addElement()
173 {
174 mVerticalCompVecTuple.resize(mElemVec.size() + 1);
175 if constexpr (comp::HasCustomComponents<T>)
176 mCustomCompVecMap.resize(mElemVec.size() + 1);
177
178 T* oldB = mElemVec.data();
179 mElemVec.emplace_back();
180 T* newB = mElemVec.data();
181 mElemNumber++;
182
183 mElemVec.back().setParentMesh(mParentMesh);
184 mElemVec.back().initVerticalComponents();
185
186 if (oldB != newB) {
187 setParentMeshPointers(mParentMesh);
188 mParentMesh->updateAllReferences(oldB);
189 }
190
191 return mElemVec.size() - 1;
192 }
193
202 uint addElements(uint size)
203 {
204 mVerticalCompVecTuple.resize(mElemVec.size() + size);
205 if constexpr (comp::HasCustomComponents<T>)
206 mCustomCompVecMap.resize(mElemVec.size() + size);
207
208 uint baseId = mElemVec.size();
209 T* oldB = mElemVec.data();
210 mElemVec.resize(mElemVec.size() + size);
211 T* newB = mElemVec.data();
212 mElemNumber += size;
213
214 for (uint i = baseId; i < mElemVec.size(); ++i) {
215 mElemVec[i].setParentMesh(mParentMesh);
216 mElemVec[i].initVerticalComponents();
217 }
218
219 if (oldB != newB) {
220 setParentMeshPointers(mParentMesh);
221 mParentMesh->updateAllReferences(oldB);
222 }
223
224 return baseId;
225 }
226
227 void clearElements()
228 {
229 mElemVec.clear();
230 mElemNumber = 0;
231
232 // clear vertical and custom components
233
234 mVerticalCompVecTuple.clear();
235 if constexpr (comp::HasCustomComponents<T>)
236 mCustomCompVecMap.clear();
237 }
238
267 void resizeElements(uint size)
268 {
269 if (size > mElemNumber) {
270 addElements(size - mElemNumber);
271 }
272 else if (size < mElemNumber) {
273 uint nToDelete = mElemNumber - size;
274 for (uint i = mElemVec.size() - 1; nToDelete > 0; --i) {
275 if (!mElemVec[i].deleted()) {
276 deleteElement(i);
277 }
278 }
279 }
280 }
281
282 void reserveElements(uint size)
283 {
284 T* oldB = mElemVec.data();
285 mElemVec.reserve(size);
286 T* newB = mElemVec.data();
287
288 mVerticalCompVecTuple.reserve(size);
289 if constexpr (comp::HasCustomComponents<T>)
290 mCustomCompVecMap.reserve(size);
291
292 if (oldB != newB) {
293 setParentMeshPointers(mParentMesh);
294 mParentMesh->updateAllReferences(oldB);
295 }
296 }
297
305 std::vector<uint> compactElements()
306 {
307 std::vector<uint> newIndices = elementCompactIndices();
308 if (elementNumber() != elementContainerSize()) {
309 compactVector(mElemVec, newIndices);
310
311 mVerticalCompVecTuple.compact(newIndices);
312 if constexpr (comp::HasCustomComponents<T>)
313 mCustomCompVecMap.compact(newIndices);
314
315 updateElementReferences(newIndices);
316 }
317 return newIndices;
318 }
319
335 void deleteElement(uint i)
336 {
337 assert(i < mElemVec.size());
338 mElemVec[i].deletedBit() = true;
339 --mElemNumber;
340 }
341
358 void deleteElement(const T* e) { deleteElement(index(e)); }
359
373 uint elementIndexIfCompact(uint i) const
374 {
375 assert(i < mElemVec.size());
376 if (mElemVec.size() == mElemNumber)
377 return i;
378 else {
379 uint cnt = 0;
380 for (uint ii = 0; ii < i; ii++) {
381 if (!mElemVec[ii].deleted())
382 ++cnt;
383 }
384 return cnt;
385 }
386 }
387
399 std::vector<uint> elementCompactIndices() const
400 {
401 std::vector<uint> newIndices(mElemVec.size());
402 uint k = 0;
403 for (uint i = 0; i < mElemVec.size(); ++i) {
404 if (!mElemVec[i].deleted()) {
405 newIndices[i] = k;
406 k++;
407 }
408 else {
409 newIndices[i] = UINT_NULL;
410 }
411 }
412 return newIndices;
413 }
414
429 void append(const ElementContainer<T>& other)
430 {
431 using Comps = T::Components;
432
433 uint on = other.elementContainerSize();
434 uint n = elementContainerSize();
435 addElements(on);
436 for (uint i = 0; i < on; ++i) {
437 // copy everything from the other elements, also the (not updated)
438 // pointers:
439 if (other.element(i).deleted()) {
440 deleteElement(n + i);
441 }
442 element(n + i) = other.element(i);
443 element(n + i).setParentMesh(mParentMesh);
444 }
445 // importing also optional, vertical and custom components:
446 appendVerticalComponents(other, VertComps());
447 appendCustomComponents(other);
448 }
449
460 void serializeOptionalComponentsAndElementsNumber(std::ostream& out) const
461 {
462 constexpr uint N_VERT_COMPS = VertComps::size();
463 std::array<bool, N_VERT_COMPS> enabledComps;
464 uint i = 0;
465
466 auto forEachVertComp = [&]<typename Comp>() {
467 enabledComps[i] =
468 mVerticalCompVecTuple.template isComponentEnabled<Comp>();
469 ++i;
470 };
471
472 ForEachType<VertComps>::apply(forEachVertComp);
473
474 vcl::serialize(out, elementContainerSize());
475 vcl::serialize(out, enabledComps);
476 }
477
486 void serializeElements(std::ostream& out) const
487 {
488 for (const auto& e : mElemVec) {
489 e.serialize(out);
490 }
491 }
492
503 void deserializeOptionalComponentsAndElementsNumber(std::istream& in)
504 {
505 constexpr uint N_VERT_COMPS = VertComps::size();
506 std::array<bool, N_VERT_COMPS> enabledComps;
507 uint size = 0;
508
509 vcl::deserialize(in, size);
510 vcl::deserialize(in, enabledComps);
511
512 resizeElements(size);
513
514 uint i = 0;
515 auto forEachVertComp = [&]<typename Comp>() {
516 if (enabledComps[i])
517 mVerticalCompVecTuple.template enableComponent<Comp>();
518 else
519 mVerticalCompVecTuple.template disableComponent<Comp>();
520 ++i;
521 };
522
523 ForEachType<VertComps>::apply(forEachVertComp);
524 }
525
534 void deserializeElements(std::istream& in)
535 {
536 for (auto& e : mElemVec) {
537 e.deserialize(in);
538 }
539 }
540
552 ElementIterator elementBegin(bool jumpDeleted = true)
553 {
554 return ElementIterator(
555 mElemVec.begin(),
556 mElemVec,
557 jumpDeleted && mElemVec.size() != mElemNumber);
558 }
559
564 ElementIterator elementEnd()
565 {
566 return ElementIterator(mElemVec.end(), mElemVec);
567 }
568
580 ConstElementIterator elementBegin(bool jumpDeleted = true) const
581 {
582 return ConstElementIterator(
583 mElemVec.begin(),
584 mElemVec,
585 jumpDeleted && mElemVec.size() != mElemNumber);
586 }
587
592 ConstElementIterator elementEnd() const
593 {
594 return ConstElementIterator(mElemVec.end(), mElemVec);
595 }
596
619 View<ElementIterator> elements(bool jumpDeleted = true)
620 {
621 return View(
622 elementBegin(jumpDeleted && mElemVec.size() != mElemNumber),
623 elementEnd());
624 }
625
650 View<ElementIterator> elements(uint begin, uint end = UINT_NULL)
651 {
652 assert(begin <= elementContainerSize());
653 if (end == UINT_NULL || end > elementContainerSize())
654 end = elementContainerSize();
655 assert(begin <= end);
656 return View(elementBegin(false) + begin, elementBegin(false) + end);
657 }
658
681 View<ConstElementIterator> elements(bool jumpDeleted = true) const
682 {
683 return View(
684 elementBegin(jumpDeleted && mElemVec.size() != mElemNumber),
685 elementEnd());
686 }
687
712 View<ConstElementIterator> elements(uint begin, uint end = UINT_NULL) const
713 {
714 assert(begin <= elementContainerSize());
715 if (end == UINT_NULL || end > elementContainerSize())
716 end = elementContainerSize();
717 assert(begin <= end);
718 return View(elementBegin(false) + begin, elementBegin(false) + end);
719 }
720
721 void enableAllOptionalComponents()
722 {
723 mVerticalCompVecTuple.enableAllOptionalComponents();
724 }
725
726 void disableAllOptionalComponents()
727 {
728 mVerticalCompVecTuple.disableAllOptionalComponents();
729 }
730
731 template<typename C>
732 bool isComponentAvailable() const
733 {
734 if constexpr (comp::HasComponentOfType<T, C::COMPONENT_ID>) {
735 if constexpr (comp::
736 HasOptionalComponentOfType<T, C::COMPONENT_ID>) {
737 return mVerticalCompVecTuple.template isComponentEnabled<C>();
738 }
739 else {
740 return true;
741 }
742 }
743 else {
744 return false;
745 }
746 }
747
748 template<uint COMP_ID>
749 bool isComponentAvailable() const
750 {
751 if constexpr (comp::HasComponentOfType<T, COMP_ID>) {
752 if constexpr (comp::HasOptionalComponentOfType<T, COMP_ID>) {
753 return mVerticalCompVecTuple
754 .template isComponentEnabled<COMP_ID>();
755 }
756 else {
757 return true;
758 }
759 }
760 else {
761 return false;
762 }
763 }
764
765 template<typename C>
766 bool isOptionalComponentEnabled() const
767 {
768 return mVerticalCompVecTuple.template isComponentEnabled<C>();
769 }
770
771 template<uint COMP_ID>
772 bool isOptionalComponentEnabled() const
773 {
774 return mVerticalCompVecTuple.template isComponentEnabled<COMP_ID>();
775 }
776
777 template<typename C>
778 void enableOptionalComponent()
779 {
780 if (!isOptionalComponentEnabled<C>()) {
781 mVerticalCompVecTuple.template enableComponent<C>();
782 // first call init on all the just enabled components
783 if constexpr (comp::HasInitMemberFunction<C>) {
784 for (auto& e : elements()) {
785 e.C::init();
786 }
787 }
788 // then resize the component containers with tied size to vertex
789 // number
790 if constexpr (comp::IsTiedToVertexNumber<C>) {
791 static const int N = T::VERTEX_NUMBER;
792 if constexpr (N < 0) {
793 for (auto& e : elements()) {
794 e.C::resize(e.vertexNumber());
795 }
796 }
797 }
798 }
799 }
800
801 template<uint COMP_ID>
802 void enableOptionalComponent()
803 {
804 using C = comp::ComponentOfType<COMP_ID, typename T::Components>;
805 enableOptionalComponent<C>();
806 }
807
808 template<typename C>
809 void disableOptionalComponent()
810 {
811 mVerticalCompVecTuple.template disableComponent<C>();
812 }
813
814 template<uint COMP_ID>
815 void disableOptionalComponent()
816 {
817 mVerticalCompVecTuple.template disableComponent<COMP_ID>();
818 }
819
820 // Custom Components
821
822 bool hasElemCustomComponent(const std::string& name) const
823 requires comp::HasCustomComponents<T>
824 {
825 return mCustomCompVecMap.componentExists(name);
826 }
827
828 std::vector<std::string> elemCustomComponentNames() const
829 requires comp::HasCustomComponents<T>
830 {
831 return mCustomCompVecMap.allComponentNames();
832 }
833
834 template<typename K>
835 bool isElemCustomComponentOfType(const std::string& name) const
836 requires comp::HasCustomComponents<T>
837 {
838 return mCustomCompVecMap.template isComponentOfType<K>(name);
839 }
840
841 std::type_index elemComponentType(const std::string& name) const
842 requires comp::HasCustomComponents<T>
843 {
844 return mCustomCompVecMap.componentType(name);
845 }
846
847 template<typename K>
848 std::vector<std::string> elemCustomComponentNamesOfType() const
849 requires comp::HasCustomComponents<T>
850 {
851 return mCustomCompVecMap.template allComponentNamesOfType<K>();
852 }
853
854 template<typename K>
855 void addElemCustomComponent(const std::string& name)
856 requires comp::HasCustomComponents<T>
857 {
858 mCustomCompVecMap.template addNewComponent<K>(
859 name, elementContainerSize());
860 }
861
862 void deleteElemCustomComponent(const std::string& name)
863 requires comp::HasCustomComponents<T>
864 {
865 mCustomCompVecMap.deleteComponent(name);
866 }
867
868 template<typename K>
869 CustomComponentVectorHandle<K> customComponentVectorHandle(
870 const std::string& name) requires comp::HasCustomComponents<T>
871 {
872 std::vector<std::any>& cc =
873 mCustomCompVecMap.template componentVector<K>(name);
874 CustomComponentVectorHandle<K> v(cc);
875 return v;
876 }
877
878 template<typename K>
879 ConstCustomComponentVectorHandle<K> customComponentVectorHandle(
880 const std::string& name) const requires comp::HasCustomComponents<T>
881 {
882 const std::vector<std::any>& cc =
883 mCustomCompVecMap.template componentVector<K>(name);
884 ConstCustomComponentVectorHandle<K> v(cc);
885 return cc;
886 }
887
888 template<typename K>
889 void serializePerElementCustomComponentsOfType(std::ostream& os) const
890 requires comp::HasCustomComponents<T>
891 {
892 mCustomCompVecMap.template serializeCustomComponentsOfType<K>(os);
893 }
894
895 template<typename K>
896 void deserializePerElementCustomComponentsOfType(std::istream& is)
897 requires comp::HasCustomComponents<T>
898 {
899 mCustomCompVecMap.template deserializeCustomComponentsOfType<K>(is);
900 }
901
902 uint index(const T* e) const
903 {
904 assert(
905 !mElemVec.empty() && e >= mElemVec.data() && e <= &mElemVec.back());
906 return e - mElemVec.data();
907 }
908
909 void setParentMeshPointers(void* pm)
910 {
911 mParentMesh = static_cast<ParentMeshType*>(pm);
912 for (auto& e : elements(false)) {
913 e.setParentMesh(pm);
914 }
915 }
916
917 template<typename Element>
918 void updateReferences(
919 const Element* oldBase,
920 uint firstElementToProcess = 0,
921 uint offset = 0)
922 {
923 using Comps = T::Components;
924
925 updateReferencesOnComponents(
926 oldBase, Comps(), firstElementToProcess, offset);
927 }
928
929 template<typename Element>
930 void updateReferences(const std::vector<uint>& newIndices)
931 {
932 using Comps = T::Components;
933
934 updateReferencesOnComponents<Element>(newIndices, Comps());
935 }
936
968 void updateElementReferences(const std::vector<uint>& newIndices)
969 {
970 mParentMesh->template updateAllReferences<T>(newIndices);
971 }
972
973 template<typename OtherMesh>
974 void enableOptionalComponentsOf(const OtherMesh& m)
975 {
976 if constexpr (OtherMesh::template hasContainerOf<T>()) {
977 // get the container type of the other mesh for T - used to upcast
978 // othMesh
979 using OContainer = OtherMesh::template ContainerOf<T>::type;
980
981 const OContainer& c = static_cast<const OContainer&>(m);
982
983 enableSameOptionalComponents(typename T::Components(), c);
984 }
985 }
986
987 template<typename OtherMesh>
988 void importFrom(const OtherMesh& m)
989 {
990 if constexpr (OtherMesh::template hasContainerOf<T>()) {
991 // get the container type of the other mesh for T - used to upcast
992 // othMesh
993 using Container = OtherMesh::template ContainerOf<T>::type;
994
995 const Container& c = (const Container&) m;
996
997 clearElements();
998
999 // recreate a container having the same number of elements as the
1000 // other mesh. this call will also update the parentMesh pointers
1001 // and sets the vertical components vectors in vcVecTuple
1002 addElements(c.elementContainerSize());
1003 unsigned int eid = 0;
1004 for (const typename Container::ElementType& e : c.elements(false)) {
1005 // import the components of the e, when they are available.
1006 // note that will set also the deleted flag of e, therefore if e
1007 // is deleted, then also element(eid) will be deleted.
1008 element(eid).importFrom(e);
1009 ++eid;
1010 }
1011 // set the number of elements (different from the container size)
1012 mElemNumber = c.mElemNumber;
1013 if constexpr (
1014 comp::HasCustomComponents<T> &&
1015 comp::HasCustomComponents<typename Container::ElementType>) {
1016 mCustomCompVecMap = c.mCustomCompVecMap;
1017 }
1018 }
1019 }
1020
1021 void swapVerticalComponents(uint e1, uint e2)
1022 {
1023 mVerticalCompVecTuple.swapComponents(e1, e2);
1024 if constexpr (comp::HasCustomComponents<T>)
1025 mCustomCompVecMap.swapCustomComponents(e1, e2);
1026 }
1027
1028private:
1029 template<typename ElPtr, typename... Comps>
1030 void updateReferencesOnComponents(
1031 const ElPtr* oldBase,
1032 TypeWrapper<Comps...>,
1033 uint firstElementToProcess = 0,
1034 uint offset = 0)
1035 {
1036 (updateReferencesOnComponent<Comps>(
1037 oldBase, firstElementToProcess, offset),
1038 ...);
1039 }
1040
1041 template<typename ElPtr, typename... Comps>
1042 void updateReferencesOnComponents(
1043 const std::vector<uint>& newIndices,
1044 TypeWrapper<Comps...>)
1045 {
1046 (updateReferencesOnComponent<Comps, ElPtr>(newIndices), ...);
1047 }
1048
1049 /*
1050 * This function is called for each component of the element.
1051 *
1052 * Only if a component has references of the type ElPtr, then the
1053 * updateReferences on each element will be executed.
1054 *
1055 * firstElementToProcess and offset are used only when an append operation
1056 * has been executed. In this case, the firstElementToProcess is the index
1057 * of the first element that has been appended, and offset is the number of
1058 * ElPtr elements that have been appended (the offset that must be added
1059 * to the newBase w.r.t. the oldBase that was the other container from which
1060 * the elements have been copied).
1061 */
1062 template<typename Comp, typename ElPtr>
1063 void updateReferencesOnComponent(
1064 const ElPtr* oldBase,
1065 uint firstElementToProcess = 0,
1066 uint offset = 0)
1067 {
1068 if constexpr (comp::HasReferencesOfType<Comp, ElPtr>) {
1069 // lambda to avoid code duplication
1070 auto loop = [&]() {
1071 for (uint i = firstElementToProcess; i < elementContainerSize();
1072 i++) {
1073 T& e = element(i);
1074 if (!e.deleted()) {
1075 e.Comp::updateReferences(oldBase, offset);
1076 }
1077 }
1078 };
1079
1080 if constexpr (comp::HasOptionalReferencesOfType<Comp, ElPtr>) {
1081 if (isOptionalComponentEnabled<Comp>()) {
1082 loop();
1083 }
1084 }
1085 else {
1086 loop();
1087 }
1088 }
1089 }
1090
1091 template<typename Comp, typename ElPtr>
1092 void updateReferencesOnComponent(const std::vector<uint>& newIndices)
1093 {
1094 if constexpr (comp::HasReferencesOfType<Comp, ElPtr>) {
1095 if constexpr (comp::HasOptionalReferencesOfType<Comp, ElPtr>) {
1096 if (isOptionalComponentEnabled<Comp>()) {
1097 for (T& e : elements()) {
1098 e.Comp::updateReferences(newIndices);
1099 }
1100 }
1101 }
1102 else {
1103 for (T& e : elements()) {
1104 e.Comp::updateReferences(newIndices);
1105 }
1106 }
1107 }
1108 }
1109
1110 template<typename... Comps>
1111 void appendVerticalComponents(
1112 const ElementContainer<T>& other,
1113 TypeWrapper<Comps...>)
1114 {
1115 (appendVerticalComponent<Comps>(other), ...);
1116 }
1117
1118 template<typename Comp>
1119 void appendVerticalComponent(const ElementContainer<T>& other)
1120 {
1121 uint on = other.elementContainerSize();
1122 uint n = elementContainerSize() - on;
1123
1124 if (mVerticalCompVecTuple.template isComponentEnabled<Comp>() &&
1125 other.mVerticalCompVecTuple.template isComponentEnabled<Comp>()) {
1126 auto& vc = mVerticalCompVecTuple.template vector<Comp>();
1127 const auto& ovc =
1128 other.mVerticalCompVecTuple.template vector<Comp>();
1129
1130 for (uint i = 0; i < on; ++i) {
1131 vc[n + i] = ovc[i];
1132 }
1133 }
1134 }
1135
1136 void appendCustomComponents(const ElementContainer<T>& other)
1137 {
1138 if constexpr (comp::HasCustomComponents<T>) {
1139 uint on = other.elementContainerSize();
1140 uint n = elementContainerSize() - on;
1141
1142 std::vector<std::string> ccNames =
1143 mCustomCompVecMap.allComponentNames();
1144
1145 for (const std::string& name : ccNames) {
1146 for (uint i = 0; i < on; ++i) {
1147 mCustomCompVecMap.importSameCustomComponentFrom(
1148 n + i, i, name, other.mCustomCompVecMap);
1149 }
1150 }
1151 }
1152 }
1153
1154 template<typename Cont2, typename... Comps>
1155 void enableSameOptionalComponents(TypeWrapper<Comps...>, const Cont2& c2)
1156 {
1157 // for each Component in Comps, will call enableSameOptionalComponent
1158 (enableSameOptionalComponent<Comps>(c2), ...);
1159 }
1160
1165 template<typename Comp, typename Cont2>
1166 void enableSameOptionalComponent(const Cont2& c2)
1167 {
1168 // if Comp is an optional component in This container
1169 if constexpr (comp::IsOptionalComponent<Comp>) {
1170 // if Comp is available in Cont2
1171 if constexpr (comp::HasComponentOfType<
1172 typename Cont2::ElementType,
1173 Comp::COMPONENT_ID>) {
1174 // if Comp is optional in Cont2
1175 if constexpr (comp::HasOptionalComponentOfType<
1176 typename Cont2::ElementType,
1177 Comp::COMPONENT_ID>) {
1178 // if Comp is enabled in Cont2, we enable it in this
1179 // container
1180 if (c2.template isOptionalComponentEnabled<
1181 Comp::COMPONENT_ID>()) {
1182 enableOptionalComponent<Comp::COMPONENT_ID>();
1183 }
1184 }
1185 // if Comp is not optional (but is available), we enable it in
1186 // this container
1187 else {
1188 enableOptionalComponent<Comp::COMPONENT_ID>();
1189 }
1190 }
1191 }
1192 }
1193};
1194
1207template<typename T>
1208concept ElementContainerConcept =
1209 std::derived_from< // same type or derived type
1210 std::remove_cvref_t<T>,
1211 ElementContainer<typename RemoveRef<T>::ElementType>>;
1212
1214
1215} // namespace vcl::mesh
1216
1217#endif // VCL_MESH_CONTAINERS_BASE_ELEMENT_CONTAINER_H
PointT size() const
Computes the size of the box.
Definition box.h:267
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48