Visual Computing Library  devel
Loading...
Searching...
No Matches
check_pointers.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_ALGORITHMS_MESH_CHECK_POINTERS_H
24#define VCL_ALGORITHMS_MESH_CHECK_POINTERS_H
25
26#include <vclib/mesh.h>
27
28namespace vcl {
29
30namespace detail {
31
34template<uint ELEM_ID, MeshConcept MeshType>
35bool checkParentMeshPointers(const MeshType& mesh)
36{
37 for (const auto& el : mesh.template elements<ELEM_ID>()) {
38 if (el.parentMesh() != &mesh) {
39 throw InconsistentMeshException(
40 "The " + elementEnumString<ELEM_ID>() + " n. " +
41 toString(el.index()) + " has a wrong Parent Mesh.\n" +
42 "Expected: " + toString(&mesh) + "; " +
43 "Found: " + toString(el.parentMesh()));
44 return false;
45 }
46 }
47 return true;
48}
49
50template<MeshConcept MeshType, typename... Containers>
51bool checkParentMeshPointers(const MeshType& mesh, TypeWrapper<Containers...>)
52{
53 return (
54 checkParentMeshPointers<Containers::ElementType::ELEMENT_ID>(mesh) &&
55 ...);
56}
57
60template<uint ELEM_ID, typename Comp, MeshConcept MeshType, typename ElemType>
61bool checkElementPointersInElementContainerOnComponent(
62 const MeshType& mesh,
63 const ElemType* first,
64 const ElemType* last)
65{
66 // actual check:
67 // We now need to check, for the component Comp of each element ELEM_ID,
68 // if it has pointers to ElemType, and if so, if they are in the range
69 // [first, last).
70
71 // if Comp has pointers to ElemType
72 if constexpr (comp::HasPointersOfType<Comp, ElemType>) {
73 // we create a lambda to loop over the elements of the mesh
74 // to avoid code duplication
75
76 auto pointersLoop = [&]() {
77 // for each element of type ELEM_ID in the mesh
78 for (const auto& el : mesh.template elements<ELEM_ID>()) {
79 // take its Comp component - we know that Comp is a component
80 // that has pointers to ElemType
81 const Comp& comp = static_cast<const Comp&>(el);
82
83 // take the pointers in the component and look at them
84 for (const ElemType* ptr : comp.template pointers<ElemType>()) {
85 if (ptr != nullptr) {
86 if (ptr < first || ptr >= last) {
87 throw InconsistentMeshException(
88 "The " + elementEnumString<ELEM_ID>() + " n. " +
89 toString(el.index()) +
90 " has a wrong pointer in " +
91 componentEnumString<Comp::COMPONENT_ID>() +
92 " component.\n" + "The pointer " +
93 toString(ptr) + " is out of range [" +
94 toString(first) + ", " + toString(last) + ")");
95 return false;
96 }
97 }
98 }
99 }
100 return true;
101 };
102
103 // if Comp is optional, we first need to check if it is enabled
104 if constexpr (comp::HasOptionalPointersOfType<Comp, ElemType>) {
105 if (mesh.template isPerElementComponentEnabled<
106 ELEM_ID,
107 Comp::COMPONENT_ID>()) {
108 return pointersLoop();
109 }
110 return true;
111 }
112 else {
113 return pointersLoop();
114 }
115 }
116
117 // if Comp has indices to ElemType
118 if constexpr (comp::HasIndicesOfType<Comp, ElemType>) {
119 // we create a lambda to loop over the elements of the mesh
120 // to avoid code duplication
121
122 auto indicesLoop = [&]() {
123 // for each element of type ELEM_ID in the mesh
124 for (const auto& el : mesh.template elements<ELEM_ID>()) {
125 // take its Comp component - we know that Comp is a component
126 // that has indices to ElemType
127 const Comp& comp = static_cast<const Comp&>(el);
128
129 // take the pointers in the component and look at them
130 for (uint i : comp.template indices<ElemType>()) {
131 if (i != UINT_NULL) {
132 if (i >= last - first) {
133 throw InconsistentMeshException(
134 "The " + elementEnumString<ELEM_ID>() + " n. " +
135 toString(el.index()) +
136 " has a wrong index in " +
137 componentEnumString<Comp::COMPONENT_ID>() +
138 " component.\n" + "The index " + toString(i) +
139 " is out of range [ 0, " +
140 toString(last - first) + ")");
141 return false;
142 }
143 }
144 }
145 }
146 return true;
147 };
148
149 // if Comp is optional, we first need to check if it is enabled
150 if constexpr (comp::HasOptionalIndicesOfType<Comp, ElemType>) {
151 if (mesh.template isPerElementComponentEnabled<
152 ELEM_ID,
153 Comp::COMPONENT_ID>()) {
154 return indicesLoop();
155 }
156 return true;
157 }
158 else {
159 return indicesLoop();
160 }
161 }
162
163 return true;
164}
165
166template<
167 uint ELEM_ID,
168 MeshConcept MeshType,
169 typename ElemType,
170 typename... Comps>
171bool checkElementPointersInElementContainerOnComponents(
172 const MeshType& mesh,
173 const ElemType* first,
174 const ElemType* last,
175 TypeWrapper<Comps...>)
176{
177 // this function calls the checker for each component of ELEM_ID element
178
179 return (
180 checkElementPointersInElementContainerOnComponent<ELEM_ID, Comps>(
181 mesh, first, last) &&
182 ...);
183}
184
185template<uint ELEM_ID, MeshConcept MeshType, typename ElemType>
186bool checkElementPointersInElementContainer(
187 const MeshType& mesh,
188 const ElemType* first,
189 const ElemType* last)
190{
191 using ThisElemType = MeshType::template ElementType<ELEM_ID>;
192 using ThisElemComponents = ThisElemType::Components;
193
194 // for the ELEM_ID container, check the pointers of the ElemType
195 // on each component of ELEM_ID
196
197 // loop into the components of ELEM_ID element
198 return checkElementPointersInElementContainerOnComponents<ELEM_ID>(
199 mesh, first, last, ThisElemComponents());
200}
201
202template<uint ELEM_ID, MeshConcept MeshType, typename... Containers>
203bool checkElementPointers(const MeshType& mesh, TypeWrapper<Containers...>)
204{
205 using ElemType = MeshType::template ElementType<ELEM_ID>;
206
207 const ElemType* first = &mesh.template element<ELEM_ID>(0);
208 uint size = mesh.template containerSize<ELEM_ID>();
209 const ElemType* last = first + size;
210
211 // now, for each Container, I need to check whether the pointers to
212 // ElemType* are in the right range
213 return (
214 checkElementPointersInElementContainer<
215 Containers::ElementType::ELEMENT_ID>(mesh, first, last) &&
216 ...);
217}
218
219template<MeshConcept MeshType, typename... Containers>
220bool checkMeshPointers(const MeshType& mesh, TypeWrapper<Containers...>)
221{
222 return (
223 checkElementPointers<Containers::ElementType::ELEMENT_ID>(
224 mesh, TypeWrapper<Containers...>()) &&
225 ...);
226}
227
228} // namespace detail
229
230template<MeshConcept MeshType>
231bool checkMeshPointers(const MeshType& mesh)
232{
233 bool res =
234 detail::checkParentMeshPointers(mesh, typename MeshType::Containers());
235
236 res =
237 res && detail::checkMeshPointers(mesh, typename MeshType::Containers());
238 return res;
239}
240
241} // namespace vcl
242
243#endif // VCL_ALGORITHMS_MESH_CHECK_POINTERS_H
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