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