GCC Code Coverage Report


Directory: ./
File: Geometry/Tools/locator.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 99 148 66.9%
Branches: 76 196 38.8%

Line Branch Exec Source
1 // ______ ______ _ _ _____ ______
2 // | ____| ____| | (_)/ ____| | ____|
3 // | |__ | |__ | | _| (___ ___| |__
4 // | __| | __| | | | |\___ \ / __| __|
5 // | | | |____| |____| |____) | (__| |____
6 // |_| |______|______|_|_____/ \___|______|
7 // Finite Elements for Life Sciences and Engineering
8 //
9 // License: LGL2.1 License
10 // FELiScE default license: LICENSE in root folder
11 //
12 // Main authors:
13 //
14
15 // System includes
16 #include <numeric>
17
18 // External includes
19
20 // Project includes
21 #include "Geometry/Tools/locator.hpp"
22 #include "Geometry/geo_utilities.hpp"
23
24 namespace felisce
25 {
26
27 17 Locator::Locator(GeometricMeshRegion* mesh, const bool allowProjection, const double tolRescaling, const int verbose):
28 17 m_allowProjection(allowProjection), m_verbose(verbose)
29 {
30 // Set tolerance
31 17 m_tol = GeoUtilities::GEO_TOL * tolRescaling;
32
33 // Set mesh pointer
34 17 m_mesh = mesh;
35
36 // Allocate and Initialize array m_markElement
37
2/2
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 17 times.
442 for (std::size_t i_eltyp = 0; i_eltyp < m_markElement.size(); ++i_eltyp)
38 425 m_markElement[i_eltyp] = nullptr;
39
40 ElementType eltType;
41
2/2
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 17 times.
34 for (std::size_t i = 0; i < m_mesh->bagElementTypeDomain().size(); ++i) {
42 17 eltType = m_mesh->bagElementTypeDomain()[i];
43
44
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
17 m_markElement[eltType] = new std::size_t[m_mesh->numElements(eltType)];
45
2/2
✓ Branch 1 taken 7884 times.
✓ Branch 2 taken 17 times.
7901 for (felInt k = 0; k < m_mesh->numElements(eltType); ++k)
46 7884 m_markElement[eltType][k] = 0;
47 }
48 17 m_mark = 0;
49
50 // Build edges or faces
51
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 7 times.
17 if ( m_mesh->domainDim() == 2 ) {
52
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 if ( !m_mesh->statusEdges() )
53
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 m_mesh->buildEdges();
54
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 } else if ( m_mesh->domainDim() == 3 ) {
55
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if ( !m_mesh->statusFaces() )
56
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 m_mesh->buildFaces();
57 }
58
59 // Build bounding box
60
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 m_bbox = felisce::make_shared<BoundingBox>(*m_mesh);
61
1/2
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
17 m_bbox->computeDelta(mesh->numCoor());
62
63 // If default hashtab size < numPoints reduce it
64
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 2 times.
17 if ( static_cast<std::size_t>(m_mesh->numPoints()) < HashTable::HASHSIZE )
65
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 m_hash = felisce::make_shared<HashTable>(m_mesh, static_cast<std::size_t>(m_mesh->numPoints()), m_bbox.get());
66 else
67
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 m_hash = felisce::make_shared<HashTable>(m_mesh, HashTable::HASHSIZE, m_bbox.get());
68 17 }
69
70 /***********************************************************************************/
71 /***********************************************************************************/
72
73 17 Locator::~Locator()
74 {
75
2/2
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 17 times.
442 for (std::size_t i_eltyp = 0; i_eltyp < m_markElement.size(); ++i_eltyp) {
76
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 408 times.
425 if( m_markElement[i_eltyp] != nullptr ) {
77
78
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 delete [] m_markElement[i_eltyp];
79 17 m_markElement[i_eltyp] = nullptr;
80 }
81 }
82 17 }
83
84 /***********************************************************************************/
85 /***********************************************************************************/
86
87 13 void Locator::findListPointsInMesh(std::vector<felInt>& indElt, std::vector<ElementType>& typElt, const std::vector<Point>& lstPoints)
88 {
89 13 std::vector<seedElement> elt;
90
91
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 findListPointsInMesh(elt, lstPoints);
92
93
2/2
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 13 times.
54 for (std::size_t i = 0; i < lstPoints.size(); ++i) {
94 41 typElt[i] = elt[i].first;
95 41 indElt[i] = elt[i].second;
96 }
97 13 }
98
99 /***********************************************************************************/
100 /***********************************************************************************/
101
102 13 void Locator::findListPointsInMesh(std::vector<seedElement>& elt, const std::vector<Point>& lstPoints)
103 {
104
1/2
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
13 elt.assign(lstPoints.size(), seedElement(GeometricMeshRegion::ELEMENT_TYPE_COUNTER, -1) );
105
106 // This method requires the hashtable
107
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if ( !m_hash ) FEL_ERROR("Localization: hashtable not allocated");
108
109 // For each point of the structure mesh
110
2/2
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 13 times.
54 for (std::size_t k = 0; k < lstPoints.size(); ++k) {
111
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if ( m_verbose > 3 )
113 std::cout << "Localization: Processing point " << k << " = " << lstPoints[k] <<std::endl;
114
115 // Point has not been localised yet
116
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
41 if( elt[k].second == -1 ) {
117
118 // Locate the point and even project it if necessary - when it is inside the box but not inside the mesh
119
2/2
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 31 times.
41 if ( !(findPointInMesh(elt[k], lstPoints[k])) ) {
120 // Failure
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if ( m_allowProjection )
122 FEL_ERROR( "Localization: point " + std::to_string(k) + " has not been localized even with the projection on the mesh!" );
123
124
4/8
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
10 std::cout << "Localization: point " + std::to_string(k) + " has not been localized!" << std::endl;
125 }
126 }
127 }
128
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if ( m_verbose > 3 )
130 std::cout << "Localization: all points in the list have been analysed!" << std::endl;
131 13 }
132
133 /***********************************************************************************/
134 /***********************************************************************************/
135
136 1805 bool Locator::findPointInMesh(seedElement& elt, const Point& point)
137 {
138 ElementType eltType;
139 1805 seedElement tmpSeed;
140 Point pointInRefElm;
141 1805 std::size_t mark = ++getMark();
142
143 // If the point is in the bounding box of the mesh
144
2/2
✓ Branch 3 taken 1788 times.
✓ Branch 4 taken 17 times.
1805 if( m_bbox->isInBBox(m_mesh->numCoor(), point, m_tol) ) {
145
146 // Try to locate the point in an optimized way with the hashtable
147
1/2
✓ Branch 3 taken 1788 times.
✗ Branch 4 not taken.
1788 tmpSeed = m_hash->findSeed(point);
148
1/2
✓ Branch 1 taken 1788 times.
✗ Branch 2 not taken.
1788 tmpSeed = localizePoint(tmpSeed, point, pointInRefElm, mark);
149
150 // If succeeded, return True
151
2/4
✓ Branch 0 taken 1788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1788 times.
✗ Branch 3 not taken.
1788 if ( tmpSeed.first != GeometricMeshRegion::ELEMENT_TYPE_COUNTER && tmpSeed.second > -1 ) {
152
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1788 times.
1788 if ( m_verbose > 3 )
154 std::cout << "Localization: success, point located using the hash table!" << std::endl;
155
156 // Copy information from the hashtable
157 1788 elt = tmpSeed;
158
159 1788 return true;
160 }
161
162 // If failure,
163 if ( m_verbose > 3 )
164 std::cout << "Localization: failure, point cannot be located using the hash table!" << std::endl;
165
166 // Go through all type of elements of mesh
167 mark = ++getMark();
168 for (std::size_t l = 0; l < m_mesh->bagElementTypeDomain().size(); ++l) {
169 eltType = m_mesh->bagElementTypeDomain()[l];
170
171 const int nbrPnt = GeometricMeshRegion::m_numPointsPerElt[eltType];
172 std::vector<felInt> veridxOfElt( nbrPnt, 0);
173 std::vector<Point*> pointsOfElt( nbrPnt, nullptr);
174
175 // Go through all elements of this type
176 for (felInt jel = 0; jel < m_mesh->numElements(eltType); ++jel) {
177 tmpSeed.first = eltType;
178 tmpSeed.second = jel;
179
180 // Skip already visited elements
181 if ( markElement(eltType, jel) == mark )
182 continue;
183
184 // Check bounding box
185 m_mesh->getOneElement(eltType, jel, veridxOfElt, pointsOfElt, 0);
186 BoundingBox box(m_mesh->numCoor(), pointsOfElt);
187
188 if ( !box.isInBBox(m_mesh->numCoor(), point, m_tol) )
189 continue;
190
191 // Check if point inside current element
192 if ( m_mesh->findLocalCoord(tmpSeed.first, tmpSeed.second, point, pointInRefElm) ) {
193
194 if ( m_verbose > 3 )
195 std::cout << "Localization: success, the point has been located in one of the element of the mesh!" << std::endl;
196
197 // Copy information from the hashtable
198 elt = tmpSeed;
199
200 return true;
201 }
202 }
203
204 // If failure
205 if ( m_verbose > 3 )
206 std::cout << "Localization: failure, point cannot be found into the mesh, projection needed!" << std::endl;
207 }
208 }
209
210 // If the point is outside the bounding box or it needs to be projected
211
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
17 if ( m_allowProjection ) {
212
213 // If the projection is successful
214
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 if( projectPointOnMesh(elt, point) ) {
215
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if ( m_verbose > 3 )
217 std::cout << "Localization: success, the projection has been located in one of the element of the mesh!" << std::endl;
218
219 7 return true;
220 }
221 }
222
223 // If failure
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if ( m_verbose > 3 )
225 std::cout << "Localization: failure, the point (as well as its projection if enable) has not been localised into the mesh!" << std::endl;
226
227 10 return false;
228 }
229
230 /***********************************************************************************/
231 /***********************************************************************************/
232
233 3179 Locator::seedElement Locator::localizePoint(seedElement seed, const Point& point, Point& pointInRefElm, std::size_t mark)
234 {
235
236 // Localize point in mesh
237 while (1) {
238
239 // Boundary reached
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3179 times.
3179 if ( seed.second < 0 ) {
241 seed.first = GeometricMeshRegion::ELEMENT_TYPE_COUNTER;
242 seed.second = -1;
243
244 return seed;
245 }
246
247 // Element already marked -> looping
248
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3179 times.
3179 if ( markElement(seed.first, seed.second) == mark ) {
249 seed.first = GeometricMeshRegion::ELEMENT_TYPE_COUNTER;
250 seed.second = -1;
251
252 return seed;
253 }
254
255 // Mark current element
256 3179 markElement(seed.first, seed.second) = mark;
257
258 // If point inside element, seed fuond. Otherwise go to next element
259
2/2
✓ Branch 1 taken 1788 times.
✓ Branch 2 taken 1391 times.
3179 if ( m_mesh->findLocalCoord(seed.first, seed.second, point, pointInRefElm) )
260 1788 return seed;
261 }
262
263 FEL_ERROR("Localization: this point should never be reached seed found, or stuck on boundary or cycle");
264
265 return seed;
266 }
267
268 /***********************************************************************************/
269 /***********************************************************************************/
270
271 7 bool Locator::projectPointOnMesh(seedElement& seed, const Point& pntIn)
272 {
273 bool isProjectionInMesh, isProjectionFound;
274 int numPointPerElt;
275 double distProjPlane;
276 double distToElt, minDistToElt;
277 Point projection_tmp, projection;
278
279 7 std::vector<felInt> veridxOfElt;
280 7 std::vector<Point*> pointsOfElt;
281
282 ElementType eltTypeBD;
283
284 7 minDistToElt = std::numeric_limits<double>::max();
285
286 // Go through all the boundary elements of the mesh
287 7 isProjectionFound = false;
288 7 const std::vector<ElementType>& bagElementTypeBoundary = m_mesh->bagElementTypeDomainBoundary();
289
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
14 for (std::size_t i = 0; i < bagElementTypeBoundary.size(); ++i) {
290 7 eltTypeBD = bagElementTypeBoundary[i];
291
292 // Resize vectors
293 7 numPointPerElt = GeometricMeshRegion::m_numPointsPerElt[eltTypeBD];
294
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 veridxOfElt.assign(numPointPerElt, 0);
295
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 pointsOfElt.assign(numPointPerElt, nullptr);
296
297
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 7 times.
59 for (felInt ii = 0; ii < m_mesh->numElements(eltTypeBD); ++ii) {
298
299 // Get vertices of the current element
300
1/2
✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
52 m_mesh->getOneElement(eltTypeBD, ii, veridxOfElt, pointsOfElt, 0);
301
302 // We compute the element normal
303
1/2
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
52 GeoUtilities::projectOnGeomEntity( static_cast<felInt>(m_mesh->domainDim()), pointsOfElt, pntIn, projection_tmp);
304
305 // Compute the distance from the point to its projection on the plane
306 52 distProjPlane = projection_tmp.dist(pntIn);
307
308 // If the new projected point is closer than the previous ones
309
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 21 times.
52 if ( distProjPlane < minDistToElt ) {
310
311 // Get closest projection
312
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 GeoUtilities::getClosestProjectionOnElement(eltTypeBD, pointsOfElt, projection_tmp, projection_tmp, m_tol);
313
314 // Compute total distance from the point and its projection in the current considered element
315 31 distToElt = projection_tmp.dist(pntIn);
316
317 // Looking for the minimal total distance
318
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 21 times.
31 if ( distToElt < minDistToElt ) {
319
320 // Update minimal distance
321 10 minDistToElt = distToElt;
322
323 // Save coordinates of the point which minimizes the total distance
324 10 projection = projection_tmp;
325
326 // Projection found
327 10 isProjectionFound = true;
328 }
329 }
330 }
331 }
332
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if ( !isProjectionFound ) {
334
335 if ( m_verbose > 3 )
336 std::cout << "Localization: failure, no valid projection could be found!" << std::endl;
337
338 seed.first = GeometricMeshRegion::ELEMENT_TYPE_COUNTER;
339 seed.second = -1;
340
341 return false;
342 }
343
344
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if ( m_verbose > 3 )
346 std::cout << "Localization: Projected point is " << projection << std::endl;
347
348 // Turn off projection to avoid infinity loop
349 7 m_allowProjection = false;
350
351 // Try to localize the projected point
352
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 isProjectionInMesh = findPointInMesh(seed, projection);
353
354 // Turn on projection
355 7 m_allowProjection = true;
356
357 7 return isProjectionInMesh;
358 7 }
359
360 /***********************************************************************************/
361 /***********************************************************************************/
362
363 void Locator::resetMarkElement()
364 {
365 // Reset m_markElement
366 ElementType eltType;
367 for (std::size_t i = 0; i < m_mesh->bagElementTypeDomain().size(); ++i) {
368 eltType = m_mesh->bagElementTypeDomain()[i];
369
370 if ( m_markElement[eltType] ) {
371
372 // Reset arrays
373 for (felInt k = 0; k < m_mesh->numElements(eltType); ++k)
374 m_markElement[eltType][k] = 0;
375 }
376 }
377
378 m_mark = 0;
379 }
380
381 }
382