Directory: | ./ |
---|---|
File: | Geometry/Tools/intersector.cpp |
Date: | 2024-04-14 07:32:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 251 | 429 | 58.5% |
Branches: | 177 | 803 | 22.0% |
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 | |||
17 | // External includes | ||
18 | |||
19 | // Project includes | ||
20 | #include "Geometry/geometricEdges.hpp" | ||
21 | #include "Geometry/geometricFaces.hpp" | ||
22 | #include "Geometry/neighFacesOfEdges.hpp" | ||
23 | #include "Geometry/neighVolumesOfFaces.hpp" | ||
24 | #include "Geometry/Tools/intersector.hpp" | ||
25 | |||
26 | namespace felisce | ||
27 | { | ||
28 | |||
29 | 4 | Intersector::Intersector(GeometricMeshRegion* volMesh, GeometricMeshRegion* strMesh, const double tolRescaling, const int verbose): | |
30 | 4 | m_volMesh(volMesh), m_strMesh(strMesh), m_verbose(verbose) | |
31 | { | ||
32 | // Set tolerance | ||
33 | 4 | m_tol = GeoUtilities::GEO_TOL * tolRescaling; | |
34 | |||
35 |
4/14✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
4 | FEL_CHECK( m_volMesh->domainDim() == 2 || m_volMesh->domainDim() == 3,"Intersector: cannot be called for a mesh with domainDim = " + std::to_string(m_volMesh->domainDim()) + " different from 2 or 3!\n" ); |
36 |
5/8✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
|
4 | FEL_CHECK( m_volMesh->bagElementTypeDomain().size() == 1 && |
37 | (m_volMesh->bagElementTypeDomain()[0] == GeometricMeshRegion::Tria3 || | ||
38 | m_volMesh->bagElementTypeDomain()[0] == GeometricMeshRegion::Tetra4 ), "Intersector: volume mesh must contain only Tria3 or Tetra4!\n"); | ||
39 |
5/8✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
|
4 | FEL_CHECK( m_strMesh->bagElementTypeDomain().size() == 1 && |
40 | (m_strMesh->bagElementTypeDomain()[0] == GeometricMeshRegion::Seg2 || | ||
41 | m_strMesh->bagElementTypeDomain()[0] == GeometricMeshRegion::Tria3 ), "Intersector: interface mesh must contain only Seg2 or Tria3!\n"); | ||
42 | 4 | } | |
43 | |||
44 | /***********************************************************************************/ | ||
45 | /***********************************************************************************/ | ||
46 | |||
47 | 52 | void Intersector::intersectMeshes(const std::vector<felInt>& listVerToElt, std::vector<felInt>& listOfIntElt) const | |
48 | { | ||
49 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
|
52 | FEL_ASSERT ( m_strMesh->numPoints() == static_cast<int>(listVerToElt.size()) ); |
50 | |||
51 |
2/2✓ Branch 1 taken 51 times.
✓ Branch 2 taken 1 times.
|
52 | if ( m_volMesh->domainDim() == 2 ) |
52 | 51 | findIntersectedElements2D(listVerToElt, listOfIntElt); | |
53 | else /*if ( m_volMesh->domainDim() == 3 )*/ | ||
54 | 1 | findIntersectedElements3D(listVerToElt, listOfIntElt); | |
55 | 52 | } | |
56 | |||
57 | /***********************************************************************************/ | ||
58 | /***********************************************************************************/ | ||
59 | |||
60 | 51 | void Intersector::findIntersectedElements2D(const std::vector<felInt>& listVerToElt, std::vector<felInt>& listOfIntElt) const | |
61 | { | ||
62 |
1/2✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
|
51 | std::vector<Point*> pntOfTria(3, nullptr); |
63 |
1/2✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
|
51 | std::vector<felInt> verOfTria(3, 0); |
64 |
1/2✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
|
51 | std::vector<Point> pntOfEdge(2); |
65 |
1/2✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
|
51 | std::vector<felInt> verOfEdge(2, -1); |
66 |
1/2✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
|
51 | std::vector<Point> intPoint(2); |
67 | 51 | std::array<Location,2> intLocation; | |
68 | std::array<double, 3> bary; | ||
69 | bool isInside0, isInside1; | ||
70 | 51 | felInt idxOfPreElt, idxOfNxtElt, idxOfElt = -1; | |
71 | |||
72 | // Set of intersected elements | ||
73 | 51 | std::set<felInt> setOfIntElt; | |
74 | |||
75 | // Build the edges of the volume mesh | ||
76 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
|
51 | if ( !m_volMesh->statusEdges() ) |
77 | ✗ | m_volMesh->buildEdges(); | |
78 | |||
79 | // For each edge of the structure mesh | ||
80 |
3/4✓ Branch 1 taken 1304 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1253 times.
✓ Branch 4 taken 51 times.
|
1304 | for (felInt i = 0; i < m_strMesh->getNumElement1D(); ++i) { |
81 | |||
82 | // Get nodes of the current structure edge | ||
83 |
1/2✓ Branch 1 taken 1253 times.
✗ Branch 2 not taken.
|
1253 | m_strMesh->getOneElement(GeometricMeshRegion::Seg2, i, verOfEdge, 0); |
84 | 1253 | pntOfEdge[0] = m_strMesh->listPoints()[verOfEdge[0]]; | |
85 | 1253 | pntOfEdge[1] = m_strMesh->listPoints()[verOfEdge[1]]; | |
86 | |||
87 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1253 times.
|
1253 | if ( m_verbose > 3 ) |
88 | ✗ | std::cout << "Intersector: Processing edge " << i << " = " << verOfEdge[0] << " " << verOfEdge[1] << std::endl; | |
89 | |||
90 | // Find volume element to start the intersection | ||
91 |
1/2✓ Branch 2 taken 1253 times.
✗ Branch 3 not taken.
|
1253 | if ( listVerToElt[ verOfEdge[0] ] != -1 ) { |
92 | 1253 | idxOfElt = listVerToElt[ verOfEdge[0] ]; | |
93 | } | ||
94 | ✗ | else if ( listVerToElt[ verOfEdge[1] ] != -1 ) { | |
95 | ✗ | idxOfElt = listVerToElt[ verOfEdge[1] ]; | |
96 | |||
97 | ✗ | std::swap(verOfEdge[0], verOfEdge[1]); | |
98 | ✗ | std::swap(pntOfEdge[0], pntOfEdge[1]); | |
99 | } | ||
100 | else { | ||
101 | ✗ | idxOfElt = getGermElement2D(verOfEdge); | |
102 | } | ||
103 | |||
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1253 times.
|
1253 | if ( m_verbose > 3 ) |
105 | ✗ | std::cout << "Interface edge " << i << " = " << verOfEdge[0] << " " << verOfEdge[1] << ", vertex " << verOfEdge[0] << " is in volume element " << idxOfElt << std::endl; | |
106 | |||
107 | // Reset previous intersected element to -1 | ||
108 | 1253 | idxOfPreElt = -1; | |
109 | |||
110 | // Look for intersection until pntOfEdge[1] is inside idxOfElt | ||
111 | do { | ||
112 | |||
113 | // Get nodes and coordinates of the current triangle | ||
114 |
1/2✓ Branch 1 taken 2304 times.
✗ Branch 2 not taken.
|
2304 | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, idxOfElt, verOfTria, pntOfTria, 0); |
115 | |||
116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2304 times.
|
2304 | if ( m_verbose > 9 ) |
117 | ✗ | std::cout << "Volume element " << idxOfElt << " = " << verOfTria[0] << " " << verOfTria[1] << " " << verOfTria[2] << "." << std::endl; | |
118 | |||
119 | // Check the position of pntOfEdge[0] wrt to the current element | ||
120 |
1/2✓ Branch 3 taken 2304 times.
✗ Branch 4 not taken.
|
2304 | isInside0 = GeoUtilities::isPointInTri(pntOfTria, pntOfEdge[0], bary, intLocation[0], m_tol); |
121 | |||
122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2304 times.
|
2304 | if ( !isInside0 ){ |
123 | ✗ | FEL_ERROR("Intersector::findIntersectedElements2D : pntOfEdge[0] must be inside idxOfElt !") | |
124 | } | ||
125 | |||
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2304 times.
|
2304 | if ( m_verbose > 9 ) |
127 | ✗ | std::cout << "Point0 " << pntOfEdge[0] << " is in element " << idxOfElt << " with case = " << static_cast<std::underlying_type_t<Position>>(intLocation[0].first) << " and position = " << static_cast<std::underlying_type_t<Position>>(intLocation[0].second) << "." << std::endl; | |
128 | |||
129 | // Add the intersected elements in the list | ||
130 |
1/2✓ Branch 2 taken 2304 times.
✗ Branch 3 not taken.
|
2304 | addIntersetedEltToList2D(idxOfElt, intLocation[0], setOfIntElt); |
131 | |||
132 | // Check the position of pntOfEdge[0] wrt to the current element | ||
133 |
1/2✓ Branch 3 taken 2304 times.
✗ Branch 4 not taken.
|
2304 | isInside1 = GeoUtilities::isPointInTri( pntOfTria, pntOfEdge[1], bary, intLocation[1], m_tol); |
134 | |||
135 | // If pntOfEdge[1] is inside the current element, add the intersected elements to the list | ||
136 |
2/2✓ Branch 0 taken 202 times.
✓ Branch 1 taken 2102 times.
|
2304 | if ( isInside1 ) { |
137 | |||
138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
|
202 | if ( m_verbose > 9 ) |
139 | ✗ | std::cout << "Point1 " << pntOfEdge[1] << " is in element " << idxOfElt << " with case = " << static_cast<std::underlying_type_t<Position>>(intLocation[1].first) << " and position = " << static_cast<std::underlying_type_t<Position>>(intLocation[1].second) << "." << std::endl; | |
140 | |||
141 | // Add the intersected elements in the list | ||
142 |
1/2✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
|
202 | addIntersetedEltToList2D(idxOfElt, intLocation[1], setOfIntElt); |
143 | } | ||
144 | // If pntOfEdge[1] is outside the current element, we must detect the intersections | ||
145 | else { | ||
146 | |||
147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2102 times.
|
2102 | if ( m_verbose > 9 ) |
148 | ✗ | std::cout << "Point1 " << pntOfEdge[1] << " is not in the volume element " << idxOfElt << " so there is an intersection to detect." << std::endl; | |
149 | |||
150 | 2102 | bool intFnd = false; | |
151 | // If verOfEdge[0] on a vertex | ||
152 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2102 times.
|
2102 | if ( intLocation[0].first == Position::OnVertex ) |
153 | ✗ | intFnd = computeIntersectionVertex2D(idxOfElt, verOfTria[intLocation[0].second], idxOfPreElt, idxOfNxtElt, pntOfEdge, intPoint, isInside1); | |
154 | // If verOfEdge[0] on an edge | ||
155 |
2/2✓ Branch 1 taken 1052 times.
✓ Branch 2 taken 1050 times.
|
2102 | else if ( intLocation[0].first == Position::OnEdge ) { |
156 |
1/2✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
|
1052 | intFnd = computeIntersectionEdge2D(idxOfElt, intLocation[0].second, idxOfPreElt, idxOfNxtElt, pntOfEdge, intPoint, isInside1); |
157 | } | ||
158 | else { // if ( intLocation[0].first == Position::Inside ) { | ||
159 |
1/2✓ Branch 1 taken 1050 times.
✗ Branch 2 not taken.
|
1050 | intFnd = computeIntersectionInside2D(idxOfElt, idxOfNxtElt, pntOfEdge, intPoint); |
160 | } | ||
161 | |||
162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2102 times.
|
2102 | if ( !intFnd ) |
163 | ✗ | FEL_ERROR("Intersector::findIntersectedElements2D : there must be at least one intersection point !"); | |
164 | |||
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2102 times.
|
2102 | if ( m_verbose > 9 ) |
166 | ✗ | std::cout << "Intersection detected " << intPoint[0] << "." << std::endl; | |
167 | |||
168 | // Update pntOfEdge | ||
169 | 2102 | pntOfEdge[0] = intPoint[0]; // TODO is it possible to have two intPoints??? | |
170 | |||
171 | // Update previous intersected element | ||
172 | 2102 | idxOfPreElt = idxOfElt; | |
173 | |||
174 | // Update triangle for new intersections | ||
175 | 2102 | idxOfElt = idxOfNxtElt; | |
176 | } | ||
177 |
2/2✓ Branch 0 taken 1051 times.
✓ Branch 1 taken 1253 times.
|
2304 | } while ( !isInside1 ); |
178 | } | ||
179 | |||
180 | // Fill the vector of intersected elements | ||
181 |
1/2✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
|
51 | listOfIntElt.assign(setOfIntElt.begin(), setOfIntElt.end()); |
182 | |||
183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | if ( m_verbose > 9 ) |
184 | ✗ | std::cout << "Intersector: all the edges of the structure have been considered!" << std::endl; | |
185 | 51 | } | |
186 | |||
187 | /***********************************************************************************/ | ||
188 | /***********************************************************************************/ | ||
189 | |||
190 | 2506 | void Intersector::addIntersetedEltToList2D(const felInt idxOfElt, const Location& location, std::set<felInt>& setOfIntElt) const | |
191 | { | ||
192 | felInt eltIdx; | ||
193 |
1/2✓ Branch 2 taken 2506 times.
✗ Branch 3 not taken.
|
2506 | std::vector<felInt> verOfTria(3, 0); |
194 | |||
195 | // Get nodes and coordinates of the current triangle | ||
196 |
1/2✓ Branch 1 taken 2506 times.
✗ Branch 2 not taken.
|
2506 | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, idxOfElt, verOfTria, 0); |
197 | |||
198 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1154 times.
✓ Branch 2 taken 1350 times.
✗ Branch 3 not taken.
|
2506 | switch ( location.first ) { |
199 | |||
200 | // Vertex is on a vertex of the triangle | ||
201 | 2 | case Position::OnVertex : { | |
202 | |||
203 | // Variables | ||
204 | GeometricMeshRegion::ElementType eltTyp; | ||
205 | 2 | GeometricMeshRegion::BallMap ball; | |
206 | felInt verPosInBall; | ||
207 | |||
208 | // Get ball | ||
209 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | m_volMesh->getVertexBall(verOfTria[location.second], GeometricMeshRegion::Tria3, idxOfElt, ball); |
210 | |||
211 | // Loop over ball | ||
212 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | for (std::size_t iel = 0; iel < ball.size(); ++iel) { |
213 | 2 | std::tie(eltTyp, eltIdx, verPosInBall) = ball[iel]; | |
214 | |||
215 | // Add element to the set of intersected elements | ||
216 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | setOfIntElt.insert(eltIdx); |
217 | } | ||
218 | 2 | break; | |
219 | 2 | } | |
220 | // Vertex is on an edge of the triangle | ||
221 | 1154 | case Position::OnEdge : { | |
222 | |||
223 | // Variables | ||
224 |
1/2✓ Branch 2 taken 1154 times.
✗ Branch 3 not taken.
|
1154 | std::vector<felInt> verEdgOfTria(2,-1); |
225 | 1154 | Edge edgOfElt; | |
226 | |||
227 | 1154 | auto& mapEltEdgToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tria3]; | |
228 | |||
229 | // Get the ied-th edge of the triangle | ||
230 | 1154 | verEdgOfTria[0] = verOfTria[ mapEltEdgToVer[location.second][0] ]; | |
231 | 1154 | verEdgOfTria[1] = verOfTria[ mapEltEdgToVer[location.second][1] ]; | |
232 |
1/2✓ Branch 1 taken 1154 times.
✗ Branch 2 not taken.
|
1154 | m_volMesh->getEdge(verEdgOfTria, edgOfElt); |
233 | |||
234 | // Loop over elements sharing the edge | ||
235 | 1154 | auto& listNeigh = edgOfElt.listNeighFacesOfEdges(); | |
236 |
2/2✓ Branch 1 taken 2205 times.
✓ Branch 2 taken 1154 times.
|
3359 | for (std::size_t iel = 0; iel < listNeigh.size(); ++iel) { |
237 | 2205 | eltIdx = listNeigh[iel]->idFace(); | |
238 | |||
239 | // Add element to the set of intersected elements | ||
240 |
1/2✓ Branch 1 taken 2205 times.
✗ Branch 2 not taken.
|
2205 | setOfIntElt.insert(eltIdx); |
241 | } | ||
242 | 1154 | break; | |
243 | 1154 | } | |
244 | // Vertex is inside the triangle | ||
245 | 1350 | case Position::Inside : { | |
246 | |||
247 | // Add element to the set of intersected elements | ||
248 |
1/2✓ Branch 1 taken 1350 times.
✗ Branch 2 not taken.
|
1350 | setOfIntElt.insert(idxOfElt); |
249 | 1350 | break; | |
250 | } | ||
251 | |||
252 | ✗ | default : { | |
253 | ✗ | FEL_ERROR("Intersector::addIntersetedEltToList2D : the vertex must be on a vertex, edge or inside the triangle !"); | |
254 | } | ||
255 | } | ||
256 | 2506 | } | |
257 | |||
258 | /***********************************************************************************/ | ||
259 | /***********************************************************************************/ | ||
260 | |||
261 | ✗ | bool Intersector::computeIntersectionVertex2D(const felInt idxOfElt, const felInt idxOfVer, const felInt idxOfPreElt, felInt& idxNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint, bool& isInside) const | |
262 | { | ||
263 | GeometricMeshRegion::ElementType eltTyp; | ||
264 | felInt eltIdx; | ||
265 | felInt verPos; | ||
266 | unsigned short int ied; | ||
267 | int nbrIntPnt; | ||
268 | ✗ | std::vector<Point*> pntOfElt(3, nullptr); | |
269 | ✗ | std::vector<felInt> verOfElt(3, 0); | |
270 | std::array<double,3> bary; | ||
271 | std::array<Point*,2> pntEdgOfElt; | ||
272 | |||
273 | ✗ | GeometricMeshRegion::BallMap ball; | |
274 | |||
275 | ✗ | auto& mapEltEdgToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tria3]; | |
276 | |||
277 | // Get ball | ||
278 | ✗ | m_volMesh->getVertexBall(idxOfVer, GeometricMeshRegion::Tria3, idxOfElt, ball); | |
279 | |||
280 | // Loop over ball | ||
281 | ✗ | for (std::size_t iel = 0; iel < ball.size(); ++iel) { | |
282 | ✗ | std::tie(eltTyp, eltIdx, verPos) = ball[iel]; | |
283 | |||
284 | ✗ | if ( eltIdx == idxOfPreElt ) | |
285 | ✗ | continue; | |
286 | |||
287 | // Get nodes and coordinates of the current triangle | ||
288 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, eltIdx, verOfElt, pntOfElt, 0); | |
289 | |||
290 | // Check if pntOfEdge[1] is inside the current element | ||
291 | // If it is not inside, look for an intersection with the opposite edge | ||
292 | ✗ | if ( !GeoUtilities::isPointInTri(pntOfElt, pntOfEdge[1], bary, m_tol) ) { | |
293 | |||
294 | // Get the points of the edge opposite to the vertex | ||
295 | ✗ | ied = mapEltEdgToVer[verPos][1]; | |
296 | ✗ | pntEdgOfElt[0] = pntOfElt[ mapEltEdgToVer[ied][0] ]; | |
297 | ✗ | pntEdgOfElt[1] = pntOfElt[ mapEltEdgToVer[ied][1] ]; | |
298 | |||
299 | // Compute intersection with opposite edge | ||
300 | ✗ | nbrIntPnt = GeoUtilities::computeSegmentsIntersection(pntOfEdge[0], pntOfEdge[1], *pntEdgOfElt[0], *pntEdgOfElt[1], intPoint[0], intPoint[1], m_tol); | |
301 | |||
302 | // If intersection | ||
303 | ✗ | if ( nbrIntPnt > 0 ) { | |
304 | |||
305 | ✗ | if ( m_verbose > 9 ) | |
306 | ✗ | std::cout << "computeIntersectionVertex2D: Intersection detected in " << intPoint[0] << "." << std::endl; | |
307 | |||
308 | // Return next element to intersect | ||
309 | ✗ | idxNxtElt = eltIdx; | |
310 | |||
311 | ✗ | return true; | |
312 | } | ||
313 | } | ||
314 | // If it is inside, nothing to do | ||
315 | else { | ||
316 | |||
317 | ✗ | if ( m_verbose > 9 ) | |
318 | ✗ | std::cout << "computeIntersectionVertex2D: Point " << pntOfEdge[1] << " has been found in element " << eltIdx << "." << std::endl; | |
319 | |||
320 | // Set intersection | ||
321 | ✗ | intPoint[0] = pntOfEdge[1]; | |
322 | |||
323 | // Return next element to intersect | ||
324 | ✗ | idxNxtElt = eltIdx; | |
325 | |||
326 | // Point inside element | ||
327 | ✗ | isInside = true; | |
328 | |||
329 | ✗ | return true; | |
330 | } | ||
331 | } | ||
332 | |||
333 | ✗ | return false; | |
334 | } | ||
335 | |||
336 | /***********************************************************************************/ | ||
337 | /***********************************************************************************/ | ||
338 | |||
339 | 1052 | bool Intersector::computeIntersectionEdge2D(const felInt idxOfElt, const int idxEdgInt, const felInt idxOfPreElt, felInt& idxNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint, bool& isInside) const | |
340 | { | ||
341 | felInt eltIdx; | ||
342 | int nbrIntPnt; | ||
343 |
1/2✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
|
1052 | std::vector<Point*> pntOfNxtElt(3, nullptr); |
344 |
1/2✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
|
1052 | std::vector<felInt> verOfNxtElt(3, 0); |
345 |
1/2✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
|
1052 | std::vector<felInt> verOfElt(3, 0); |
346 |
1/2✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
|
1052 | std::vector<felInt> verEdgOfElt(2,-1); |
347 | std::array<double,3> bary; | ||
348 | std::array<felInt,2> verEdgOfNxtElt; | ||
349 | std::array<Point*,2> pntEdgOfNxtElt; | ||
350 | 1052 | Edge edgOfElt; | |
351 | |||
352 | 1052 | auto& mapEltEdgToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tria3]; | |
353 | |||
354 | // Get nodes and coordinates of idxOfElt | ||
355 |
1/2✓ Branch 1 taken 1052 times.
✗ Branch 2 not taken.
|
1052 | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, idxOfElt, verOfElt, 0); |
356 | |||
357 | // Get the ied-th edge of the triangle | ||
358 | 1052 | verEdgOfElt[0] = verOfElt[ mapEltEdgToVer[idxEdgInt][0] ]; | |
359 | 1052 | verEdgOfElt[1] = verOfElt[ mapEltEdgToVer[idxEdgInt][1] ]; | |
360 |
1/2✓ Branch 1 taken 1052 times.
✗ Branch 2 not taken.
|
1052 | m_volMesh->getEdge(verEdgOfElt, edgOfElt); |
361 | |||
362 | // Loop over elements sharing the edge | ||
363 | 1052 | auto& listNeigh = edgOfElt.listNeighFacesOfEdges(); | |
364 |
1/2✓ Branch 1 taken 2103 times.
✗ Branch 2 not taken.
|
2103 | for (std::size_t iel = 0; iel < listNeigh.size(); ++iel) { |
365 | 2103 | eltIdx = listNeigh[iel]->idFace(); | |
366 | |||
367 |
2/2✓ Branch 0 taken 1051 times.
✓ Branch 1 taken 1052 times.
|
2103 | if ( eltIdx == idxOfPreElt ) |
368 | 1051 | continue; | |
369 | |||
370 | // Get nodes and coordinates of the current triangle | ||
371 |
1/2✓ Branch 1 taken 1052 times.
✗ Branch 2 not taken.
|
1052 | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, eltIdx, verOfNxtElt, pntOfNxtElt, 0); |
372 | |||
373 | // Check if pntOfEdge[1] is inside the current element | ||
374 | // If it is not inside, look for an intersection with the opposite edges | ||
375 |
3/4✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1051 times.
|
1052 | if ( !GeoUtilities::isPointInTri(pntOfNxtElt, pntOfEdge[1], bary, m_tol) ) { |
376 | |||
377 | // Loop over the two opposite edges | ||
378 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | for (std::size_t ied = 0; ied < 3; ++ied) { |
379 | |||
380 | // Get vertices of the ied-th edge | ||
381 | 2 | verEdgOfNxtElt[0] = verOfNxtElt[ mapEltEdgToVer[ied][0] ]; | |
382 | 2 | verEdgOfNxtElt[1] = verOfNxtElt[ mapEltEdgToVer[ied][1] ]; | |
383 | |||
384 | // Skip edge | ||
385 |
3/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
|
2 | if ( std::is_permutation(verEdgOfElt.begin(), verEdgOfElt.end(), verEdgOfNxtElt.begin()) ) |
386 | 1 | continue; | |
387 | |||
388 | // Get the edge | ||
389 | 1 | pntEdgOfNxtElt[0] = pntOfNxtElt[ mapEltEdgToVer[ied][0] ]; | |
390 | 1 | pntEdgOfNxtElt[1] = pntOfNxtElt[ mapEltEdgToVer[ied][1] ]; | |
391 | |||
392 | // Compute intersection with the edge | ||
393 |
1/2✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | nbrIntPnt = GeoUtilities::computeSegmentsIntersection(pntOfEdge[0], pntOfEdge[1], *pntEdgOfNxtElt[0], *pntEdgOfNxtElt[1], intPoint[0], intPoint[1], m_tol); |
394 | |||
395 | // If intersection | ||
396 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if ( nbrIntPnt > 0 ) { |
397 | |||
398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if ( m_verbose > 9 ) |
399 | ✗ | std::cout << "computeIntersectionEdge2D: Intersection detected in " << intPoint[0] << "." << std::endl; | |
400 | |||
401 | // Return next element to intersect | ||
402 | 1 | idxNxtElt = eltIdx; | |
403 | |||
404 | 1 | return true; | |
405 | } | ||
406 | } | ||
407 | } | ||
408 | // If it is inside, nothing to do | ||
409 | else { | ||
410 | |||
411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1051 times.
|
1051 | if ( m_verbose > 9 ) |
412 | ✗ | std::cout << "computeIntersectionEdge2D: Point " << pntOfEdge[1] << " has been found in element " << eltIdx << "." << std::endl; | |
413 | |||
414 | // Set intersection | ||
415 | 1051 | intPoint[0] = pntOfEdge[1]; | |
416 | |||
417 | // Return next element to intersect | ||
418 | 1051 | idxNxtElt = eltIdx; | |
419 | |||
420 | // Point inside element | ||
421 | 1051 | isInside = true; | |
422 | |||
423 | 1051 | return true; | |
424 | } | ||
425 | } | ||
426 | |||
427 | ✗ | return false; | |
428 | 1052 | } | |
429 | |||
430 | /***********************************************************************************/ | ||
431 | /***********************************************************************************/ | ||
432 | |||
433 | 1050 | bool Intersector::computeIntersectionInside2D(const felInt idxOfElt, felInt& idxNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint) const | |
434 | { | ||
435 | int nbrIntPnt; | ||
436 |
1/2✓ Branch 2 taken 1050 times.
✗ Branch 3 not taken.
|
1050 | std::vector<Point*> pntOfElt(3, nullptr); |
437 |
1/2✓ Branch 2 taken 1050 times.
✗ Branch 3 not taken.
|
1050 | std::vector<felInt> verOfElt(3, 0); |
438 | std::array<Point*,2> pntEdgOfElt; | ||
439 | |||
440 | 1050 | auto& mapEltEdgToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tria3]; | |
441 | |||
442 | // Get nodes and coordinates of the current triangle | ||
443 |
1/2✓ Branch 1 taken 1050 times.
✗ Branch 2 not taken.
|
1050 | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, idxOfElt, verOfElt, pntOfElt, 0); |
444 | |||
445 | // Loop over the edges | ||
446 |
1/2✓ Branch 0 taken 2100 times.
✗ Branch 1 not taken.
|
2100 | for (std::size_t ied = 0; ied < 3; ++ied) { |
447 | |||
448 | // Get the edge | ||
449 | 2100 | pntEdgOfElt[0] = pntOfElt[ mapEltEdgToVer[ied][0] ]; | |
450 | 2100 | pntEdgOfElt[1] = pntOfElt[ mapEltEdgToVer[ied][1] ]; | |
451 | |||
452 | // Compute intersection with the edge | ||
453 |
1/2✓ Branch 7 taken 2100 times.
✗ Branch 8 not taken.
|
2100 | nbrIntPnt = GeoUtilities::computeSegmentsIntersection(pntOfEdge[0], pntOfEdge[1], *pntEdgOfElt[0], *pntEdgOfElt[1], intPoint[0], intPoint[1], m_tol); |
454 | |||
455 | // If intersection | ||
456 |
2/2✓ Branch 0 taken 1050 times.
✓ Branch 1 taken 1050 times.
|
2100 | if ( nbrIntPnt > 0 ) { |
457 | |||
458 | // Return next element to intersect | ||
459 | 1050 | idxNxtElt = idxOfElt; | |
460 | |||
461 | 1050 | return true; | |
462 | } | ||
463 | } | ||
464 | |||
465 | ✗ | return false; | |
466 | 1050 | } | |
467 | |||
468 | /***********************************************************************************/ | ||
469 | /***********************************************************************************/ | ||
470 | |||
471 | ✗ | felInt Intersector::getGermElement2D(const std::vector<felInt>& verOfEdge) const | |
472 | { | ||
473 | ✗ | std::vector<Point*> pntOfTria(3, nullptr); | |
474 | ✗ | std::vector<felInt> verOfTria(3, 0); | |
475 | std::array<double, 3> bary; | ||
476 | |||
477 | // Go through all elements of the mesh | ||
478 | ✗ | for (felInt k = 0; k < m_volMesh->numElements(GeometricMeshRegion::Tria3); ++k) { | |
479 | |||
480 | // Get nodes of the current triangle | ||
481 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tria3, k, verOfTria, pntOfTria, 0); | |
482 | |||
483 | ✗ | if( GeoUtilities::isPointInTri( pntOfTria, m_strMesh->listPoints()[verOfEdge[0]], bary, m_tol) ) | |
484 | ✗ | return k; | |
485 | } | ||
486 | |||
487 | ✗ | FEL_ERROR("Intersector::getGermElement2D cannot localize the point into the volume mesh."); | |
488 | ✗ | return -1; | |
489 | } | ||
490 | |||
491 | /***********************************************************************************/ | ||
492 | /***********************************************************************************/ | ||
493 | |||
494 | 1 | void Intersector::findIntersectedElements3D(const std::vector<felInt>& listVerToElt, std::vector<felInt>& listOfIntElt) const | |
495 | { | ||
496 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<Point*> pntOfTetra(4, nullptr); |
497 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<felInt> verOfTetra(4, 0); |
498 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<Point> pntOfEdge(2); |
499 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<felInt> verOfEdge(2, -1); |
500 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<Point> intPoint(2); |
501 | 1 | std::array<Location,2> intLocation; | |
502 | std::array<double, 4> bary; | ||
503 | bool isInside0, isInside1; | ||
504 | 1 | felInt idxOfPreElt, idxOfNxtElt, idxOfElt = -1; | |
505 | |||
506 | // Set of intersected elements | ||
507 | 1 | std::set<felInt> setOfIntElt; | |
508 | |||
509 | // Build the edges of the interface mesh | ||
510 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if ( !m_strMesh->statusEdges() ) |
511 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | m_strMesh->buildEdges(); |
512 | |||
513 | // Build the faces of the volume mesh | ||
514 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ( !m_volMesh->statusFaces() ) |
515 | ✗ | m_volMesh->buildFaces(); | |
516 | |||
517 | // For each edge of the structure mesh | ||
518 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
|
6 | for (felInt i = 0; i < m_strMesh->numEdges(); ++i) { |
519 | |||
520 | // Get nodes of the current structure edge | ||
521 | 5 | verOfEdge[0] = m_strMesh->listEdges()[i]->idBeg(); | |
522 | 5 | verOfEdge[1] = m_strMesh->listEdges()[i]->idEnd(); | |
523 | 5 | pntOfEdge[0] = m_strMesh->listPoints()[verOfEdge[0]]; | |
524 | 5 | pntOfEdge[1] = m_strMesh->listPoints()[verOfEdge[1]]; | |
525 | |||
526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( m_verbose > 3 ) |
527 | ✗ | std::cout << "Intersector: Processing edge " << i << " = " << verOfEdge[0] << " " << verOfEdge[1] << std::endl; | |
528 | |||
529 | // Find volume element to start the intersection | ||
530 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if ( listVerToElt[ verOfEdge[0] ] != -1 ) { |
531 | 5 | idxOfElt = listVerToElt[ verOfEdge[0] ]; | |
532 | } | ||
533 | ✗ | else if ( listVerToElt[ verOfEdge[1] ] != -1 ) { | |
534 | ✗ | idxOfElt = listVerToElt[ verOfEdge[1] ]; | |
535 | |||
536 | ✗ | std::swap(verOfEdge[0], verOfEdge[1]); | |
537 | ✗ | std::swap(pntOfEdge[0], pntOfEdge[1]); | |
538 | } | ||
539 | else { | ||
540 | ✗ | idxOfElt = getGermElement3D(verOfEdge); | |
541 | } | ||
542 | |||
543 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( m_verbose > 3 ) |
544 | ✗ | std::cout << "Interface edge " << i << " = " << verOfEdge[0] << " " << verOfEdge[1] << ", vertex " << verOfEdge[0] << " is in volume element " << idxOfElt << std::endl; | |
545 | |||
546 | // Reset previous intersected element to -1 | ||
547 | 5 | idxOfPreElt = -1; | |
548 | |||
549 | // Look for intersection until pntOfEdge[1] is inside idxOfElt | ||
550 | do { | ||
551 | |||
552 | // Get nodes and coordinates of the current tetrahedron | ||
553 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, idxOfElt, verOfTetra, pntOfTetra, 0); |
554 | |||
555 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( m_verbose > 9 ) |
556 | ✗ | std::cout << "Volume element " << idxOfElt << " = " << verOfTetra[0] << " " << verOfTetra[1] << " " << verOfTetra[2] << " " << verOfTetra[3] << "." << std::endl; | |
557 | |||
558 | // Check the position of pntOfEdge[0] wrt to the current element | ||
559 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
10 | isInside0 = GeoUtilities::isPointInTetra(pntOfTetra, pntOfEdge[0], bary, intLocation[0], m_tol); |
560 | |||
561 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( !isInside0 ){ |
562 | ✗ | FEL_ERROR("Intersector::findIntersectedElements3D : pntOfEdge[0] must be inside idxOfElt !") | |
563 | } | ||
564 | |||
565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( m_verbose > 9 ) |
566 | ✗ | std::cout << "Point0 " << pntOfEdge[0] << " is in element " << idxOfElt << " with case = " << static_cast<std::underlying_type_t<Position>>(intLocation[0].first) << " and position = " << static_cast<std::underlying_type_t<Position>>(intLocation[0].second) << "." << std::endl; | |
567 | |||
568 | // Add the intersected elements in the list | ||
569 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | addIntersetedEltToList3D(idxOfElt, intLocation[0], setOfIntElt); |
570 | |||
571 | // Check the position of pntOfEdge[0] wrt to the current element | ||
572 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
10 | isInside1 = GeoUtilities::isPointInTetra(pntOfTetra, pntOfEdge[1], bary, intLocation[1], m_tol); |
573 | |||
574 | // If pntOfEdge[1] is inside the current element, add the intersected elements to the list | ||
575 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( isInside1 ) { |
576 | |||
577 | ✗ | if ( m_verbose > 9 ) | |
578 | ✗ | std::cout << "Point1 " << pntOfEdge[1] << " is in element " << idxOfElt << " with case = " << static_cast<std::underlying_type_t<Position>>(intLocation[1].first) << " and position = " << static_cast<std::underlying_type_t<Position>>(intLocation[1].second) << "." << std::endl; | |
579 | |||
580 | // Add the intersected elements in the list | ||
581 | ✗ | addIntersetedEltToList3D(idxOfElt, intLocation[1], setOfIntElt); | |
582 | } | ||
583 | // If pntOfEdge[1] is outside the current element, we must detect the intersections | ||
584 | else { | ||
585 | |||
586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( m_verbose > 9 ) |
587 | ✗ | std::cout << "Point1 " << pntOfEdge[1] << " is not in the volume element " << idxOfElt << " so there is an intersection to detect." << std::endl; | |
588 | |||
589 | 10 | bool intFnd = false; | |
590 | // If verOfEdge[0] on a vertex | ||
591 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | if ( intLocation[0].first == Position::OnVertex ){ |
592 |
1/2✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | intFnd = computeIntersectionVertex3D(idxOfElt, verOfTetra[intLocation[0].second], idxOfPreElt, idxOfNxtElt, pntOfEdge, intPoint, isInside1); |
593 | } | ||
594 | // If verOfEdge[0] on an edge | ||
595 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | else if ( intLocation[0].first == Position::OnEdge ) { |
596 | 5 | auto& edge = GeometricMeshRegion::m_eltTypMapEdgToVer[GeometricMeshRegion::Tetra4][intLocation[0].second]; | |
597 |
2/4✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
|
5 | intFnd = computeIntersectionEdge3D(idxOfElt, {verOfTetra[edge[0]], verOfTetra[edge[1]]}, idxOfPreElt, idxOfNxtElt, pntOfEdge, intPoint, isInside1); |
598 | } | ||
599 | ✗ | else if ( intLocation[0].first == Position::OnFace ) { | |
600 | ✗ | intFnd = computeIntersectionFace3D(idxOfElt, intLocation[0].second, idxOfPreElt, idxOfNxtElt, pntOfEdge, intPoint, isInside1); | |
601 | } | ||
602 | else { // if ( intLocation[0].first == Position::Inside ) { | ||
603 | ✗ | intFnd = computeIntersectionInside3D(idxOfElt, idxOfNxtElt, pntOfEdge, intPoint); | |
604 | } | ||
605 | |||
606 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( !intFnd ) |
607 | ✗ | FEL_ERROR("Intersector::findIntersectedElements3D : there must be at least one intersection point !"); | |
608 | |||
609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( m_verbose > 9 ) |
610 | ✗ | std::cout << "Intersection detected " << intPoint[0] << "." << std::endl; | |
611 | |||
612 | // Update pntOfEdge | ||
613 | 10 | pntOfEdge[0] = intPoint[0]; // TODO is it possible to have two intPoints??? | |
614 | |||
615 | // Update previous intersected element | ||
616 | 10 | idxOfPreElt = idxOfElt; | |
617 | |||
618 | // Update element for new intersections | ||
619 | 10 | idxOfElt = idxOfNxtElt; | |
620 | } | ||
621 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
|
10 | } while ( !isInside1 ); |
622 | } | ||
623 | |||
624 | // Fill the vector of intersected elements | ||
625 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | listOfIntElt.assign(setOfIntElt.begin(), setOfIntElt.end()); |
626 | |||
627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if ( m_verbose > 9 ) |
628 | ✗ | std::cout << "Intersector: all the edges of the structure have been considered!" << std::endl; | |
629 | 1 | } | |
630 | |||
631 | /***********************************************************************************/ | ||
632 | /***********************************************************************************/ | ||
633 | |||
634 | 10 | void Intersector::addIntersetedEltToList3D(const felInt idxOfElt, const Location& location, std::set<felInt>& setOfIntElt) const | |
635 | { | ||
636 | felInt eltIdx; | ||
637 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | std::vector<felInt> verOfTetra(4, 0); |
638 | |||
639 | // Get nodes and coordinates of the current element | ||
640 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, idxOfElt, verOfTetra, 0); |
641 | |||
642 |
2/5✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10 | switch ( location.first ) { |
643 | |||
644 | // Vertex is on a vertex of the element | ||
645 | 5 | case Position::OnVertex : { | |
646 | |||
647 | // Variables | ||
648 | GeometricMeshRegion::ElementType eltTyp; | ||
649 | 5 | GeometricMeshRegion::BallMap ball; | |
650 | felInt verPosInBall; | ||
651 | |||
652 | // Get ball | ||
653 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | m_volMesh->getVertexBall(verOfTetra[location.second], GeometricMeshRegion::Tetra4, idxOfElt, ball); |
654 | |||
655 | // Loop over ball | ||
656 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | for (std::size_t iel = 0; iel < ball.size(); ++iel) { |
657 | 5 | std::tie(eltTyp, eltIdx, verPosInBall) = ball[iel]; | |
658 | |||
659 | // Add element to the set of intersected elements | ||
660 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | setOfIntElt.insert(eltIdx); |
661 | } | ||
662 | 5 | break; | |
663 | 5 | } | |
664 | // Vertex is on an edge of the element | ||
665 | 5 | case Position::OnEdge : { | |
666 | |||
667 | // Variables | ||
668 | GeometricMeshRegion::ElementType eltTyp; | ||
669 | 5 | GeometricMeshRegion::BallMap shell; | |
670 | felInt edgPosInShell; | ||
671 | |||
672 | // Get map edge to ver | ||
673 | 5 | auto& edge = GeometricMeshRegion::m_eltTypMapEdgToVer[GeometricMeshRegion::Tetra4][location.second]; | |
674 | |||
675 | // Get shell | ||
676 |
2/4✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
|
5 | m_volMesh->getEdgeShell({verOfTetra[edge[0]], verOfTetra[edge[1]]}, GeometricMeshRegion::Tetra4, idxOfElt, shell); |
677 | |||
678 | // Loop over the shell | ||
679 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 5 times.
|
20 | for (std::size_t iel = 0; iel < shell.size(); ++iel) { |
680 | 15 | std::tie(eltTyp, eltIdx, edgPosInShell) = shell[iel]; | |
681 | |||
682 | // Add element to the set of intersected elements | ||
683 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | setOfIntElt.insert(eltIdx); |
684 | } | ||
685 | 5 | break; | |
686 | 5 | } | |
687 | // Vertex is on a face of the element | ||
688 | ✗ | case Position::OnFace : { | |
689 | |||
690 | // Variables | ||
691 | ✗ | std::vector<felInt> verFacOfElt(3,-1); | |
692 | ✗ | Face facOfElt; | |
693 | |||
694 | ✗ | auto& mapEltFacToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tetra4]; | |
695 | |||
696 | // Get the ied-th edge of the element | ||
697 | ✗ | verFacOfElt[0] = verOfTetra[ mapEltFacToVer[location.second][0] ]; | |
698 | ✗ | verFacOfElt[1] = verOfTetra[ mapEltFacToVer[location.second][1] ]; | |
699 | ✗ | verFacOfElt[2] = verOfTetra[ mapEltFacToVer[location.second][2] ]; | |
700 | ✗ | m_volMesh->getFace(verFacOfElt, facOfElt); | |
701 | |||
702 | // Loop over elements sharing the face | ||
703 | ✗ | auto& listNeigh = facOfElt.listNeighVolumes(); | |
704 | ✗ | for (std::size_t iel = 0; iel < listNeigh.size(); ++iel) { | |
705 | ✗ | eltIdx = listNeigh[iel]->idVolume(); | |
706 | |||
707 | // Add element to the set of intersected elements | ||
708 | ✗ | setOfIntElt.insert(eltIdx); | |
709 | } | ||
710 | ✗ | break; | |
711 | } | ||
712 | // Vertex is inside the element | ||
713 | ✗ | case Position::Inside : { | |
714 | |||
715 | // Add element to the set of intersected elements | ||
716 | ✗ | setOfIntElt.insert(idxOfElt); | |
717 | ✗ | break; | |
718 | } | ||
719 | ✗ | default : { | |
720 | ✗ | FEL_ERROR("Intersector::addIntersetedEltToList3D : the vertex must be on a vertex, edge or inside the triangle !"); | |
721 | } | ||
722 | } | ||
723 | 10 | } | |
724 | |||
725 | /***********************************************************************************/ | ||
726 | /***********************************************************************************/ | ||
727 | |||
728 | 5 | bool Intersector::computeIntersectionVertex3D(const felInt idxOfElt, const felInt idxOfVer, const felInt idxOfPreElt, felInt& idxOfNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint, bool& isInside) const | |
729 | { | ||
730 | GeometricMeshRegion::ElementType eltTyp; | ||
731 | felInt eltIdx; | ||
732 | felInt verPos; | ||
733 | unsigned short int ifa; | ||
734 | int nbrIntPnt; | ||
735 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | std::vector<Point*> pntOfNxtElt(4, nullptr); |
736 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | std::vector<felInt> verOfNxtElt(4, 0); |
737 | std::array<double,4> bary; | ||
738 | std::array<Point*,3> pntFacOfElt; | ||
739 | |||
740 | 5 | GeometricMeshRegion::BallMap ball; | |
741 | |||
742 | 5 | const std::array<const unsigned short int,4> mapVerToOppFac{2, 3, 1, 0}; | |
743 | |||
744 | 5 | auto& mapEltFacToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tetra4]; | |
745 | |||
746 | // Get ball | ||
747 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | m_volMesh->getVertexBall(idxOfVer, GeometricMeshRegion::Tetra4, idxOfElt, ball); |
748 | |||
749 | // Loop over ball | ||
750 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | for (std::size_t iel = 0; iel < ball.size(); ++iel) { |
751 | 5 | std::tie(eltTyp, eltIdx, verPos) = ball[iel]; | |
752 | |||
753 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( eltIdx == idxOfPreElt ) |
754 | ✗ | continue; | |
755 | |||
756 | // Get nodes and coordinates of the current element | ||
757 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, eltIdx, verOfNxtElt, pntOfNxtElt, 0); |
758 | |||
759 | // Check if pntOfEdge[1] is inside the current element | ||
760 | // If it is not inside, look for an intersection with the opposite face | ||
761 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | if ( !GeoUtilities::isPointInTetra(pntOfNxtElt, pntOfEdge[1], bary, m_tol) ) { |
762 | |||
763 | // Get the points of the face opposite to the vertex | ||
764 | 5 | ifa = mapVerToOppFac[verPos]; | |
765 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 5 times.
|
20 | for (std::size_t ive = 0; ive < pntFacOfElt.size(); ++ive) |
766 | 15 | pntFacOfElt[ive] = pntOfNxtElt[ mapEltFacToVer[ifa][ive] ]; | |
767 | |||
768 | // Compute intersection with opposite face | ||
769 |
1/2✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
|
5 | nbrIntPnt = GeoUtilities::computeSegmentTriangleIntersection(pntOfEdge[0], pntOfEdge[1], *pntFacOfElt[0], *pntFacOfElt[1], *pntFacOfElt[2], intPoint[0], m_tol); |
770 | |||
771 | // If intersection | ||
772 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if ( nbrIntPnt > 0 ) { |
773 | |||
774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( m_verbose > 9 ) |
775 | ✗ | std::cout << "computeIntersectionVertex3D: Intersection detected in " << intPoint[0] << "." << std::endl; | |
776 | |||
777 | // Return next element to intersect | ||
778 | 5 | idxOfNxtElt = eltIdx; | |
779 | |||
780 | 5 | return true; | |
781 | } | ||
782 | } | ||
783 | // If it is inside, nothing to do | ||
784 | else { | ||
785 | |||
786 | ✗ | if ( m_verbose > 9 ) | |
787 | ✗ | std::cout << "computeIntersectionVertex3D: Point " << pntOfEdge[1] << " has been found in element " << eltIdx << "." << std::endl; | |
788 | |||
789 | // Set intersection | ||
790 | ✗ | intPoint[0] = pntOfEdge[1]; | |
791 | |||
792 | // Return next element to intersect | ||
793 | ✗ | idxOfNxtElt = eltIdx; | |
794 | |||
795 | // Point inside element | ||
796 | ✗ | isInside = true; | |
797 | |||
798 | ✗ | return true; | |
799 | } | ||
800 | } | ||
801 | |||
802 | ✗ | return false; | |
803 | 5 | } | |
804 | |||
805 | /***********************************************************************************/ | ||
806 | /***********************************************************************************/ | ||
807 | |||
808 | 5 | bool Intersector::computeIntersectionEdge3D(const felInt idxOfElt, const std::vector<felInt>& idxOfVer, const felInt idxOfPreElt, felInt& idxOfNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint, bool& isInside) const | |
809 | { | ||
810 | GeometricMeshRegion::ElementType eltTyp; | ||
811 | felInt eltIdx; | ||
812 | felInt edgPos; | ||
813 | int nbrIntPnt; | ||
814 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | std::vector<Point*> pntOfNxtElt(4, nullptr); |
815 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | std::vector<felInt> verOfNxtElt(4, 0); |
816 | std::array<double,4> bary; | ||
817 | std::array<Point*,3> pntFacOfNxtElt; | ||
818 | |||
819 | 5 | GeometricMeshRegion::BallMap shell; | |
820 | |||
821 | 5 | auto& mapEltFacToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tetra4]; | |
822 | 5 | auto& mapEltEdgToFac = GeometricMeshRegion::m_eltTypMapEdgToFac[GeometricMeshRegion::Tetra4]; | |
823 | |||
824 | // Get shell | ||
825 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | m_volMesh->getEdgeShell(idxOfVer, GeometricMeshRegion::Tetra4, idxOfElt, shell); |
826 | |||
827 | // Loop over the shell | ||
828 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | for (std::size_t iel = 0; iel < shell.size(); ++iel) { |
829 | 15 | std::tie(eltTyp, eltIdx, edgPos) = shell[iel]; | |
830 | |||
831 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10 times.
|
15 | if ( eltIdx == idxOfPreElt ) |
832 | 5 | continue; | |
833 | |||
834 | // Get nodes and coordinates of the current element | ||
835 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, eltIdx, verOfNxtElt, pntOfNxtElt, 0); |
836 | |||
837 | // Check if pntOfEdge[1] is inside the current element | ||
838 | // If it is not inside, look for an intersection with the opposite edges | ||
839 |
3/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
|
10 | if ( !GeoUtilities::isPointInTetra(pntOfNxtElt, pntOfEdge[1], bary, m_tol) ) { |
840 | |||
841 | // Loop over the two opposite faces | ||
842 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5 times.
|
25 | for (std::size_t ifa = 0; ifa < 4; ++ifa) { |
843 | |||
844 | // Skip face | ||
845 |
6/6✓ Branch 2 taken 15 times.
✓ Branch 3 taken 5 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 10 times.
✓ Branch 9 taken 10 times.
|
20 | if ( ifa == mapEltEdgToFac[edgPos][0] || ifa == mapEltEdgToFac[edgPos][1] ) |
846 | 10 | continue; | |
847 | |||
848 | // Get the edge | ||
849 | 10 | pntFacOfNxtElt[0] = pntOfNxtElt[ mapEltFacToVer[ifa][0] ]; | |
850 | 10 | pntFacOfNxtElt[1] = pntOfNxtElt[ mapEltFacToVer[ifa][1] ]; | |
851 | 10 | pntFacOfNxtElt[2] = pntOfNxtElt[ mapEltFacToVer[ifa][2] ]; | |
852 | |||
853 | // Compute intersection with opposite edge | ||
854 |
1/2✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
|
10 | nbrIntPnt = GeoUtilities::computeSegmentTriangleIntersection(pntOfEdge[0], pntOfEdge[1], *pntFacOfNxtElt[0], *pntFacOfNxtElt[1], *pntFacOfNxtElt[2], intPoint[0], m_tol); |
855 | |||
856 | // If intersection | ||
857 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if ( nbrIntPnt > 0 ) { |
858 | |||
859 | ✗ | if ( m_verbose > 9 ) | |
860 | ✗ | std::cout << "computeIntersectionEdge3D: Intersection detected in " << intPoint[0] << "." << std::endl; | |
861 | |||
862 | // Return next element to intersect | ||
863 | ✗ | idxOfNxtElt = eltIdx; | |
864 | |||
865 | ✗ | return true; | |
866 | } | ||
867 | } | ||
868 | } | ||
869 | // If it is inside, nothing to do | ||
870 | else { | ||
871 | |||
872 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( m_verbose > 9 ) |
873 | ✗ | std::cout << "computeIntersectionEdge3D: Point " << pntOfEdge[1] << " has been found in element " << eltIdx << "." << std::endl; | |
874 | |||
875 | // Set intersection | ||
876 | 5 | intPoint[0] = pntOfEdge[1]; | |
877 | |||
878 | // Return next element to intersect | ||
879 | 5 | idxOfNxtElt = eltIdx; | |
880 | |||
881 | // Point inside element | ||
882 | 5 | isInside = true; | |
883 | |||
884 | 5 | return true; | |
885 | } | ||
886 | } | ||
887 | |||
888 | ✗ | return false; | |
889 | 5 | } | |
890 | |||
891 | /***********************************************************************************/ | ||
892 | /***********************************************************************************/ | ||
893 | |||
894 | ✗ | bool Intersector::computeIntersectionFace3D(const felInt idxOfElt, const int idxFacInt, const felInt idxOfPreElt, felInt& idxNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint, bool& isInside) const | |
895 | { | ||
896 | felInt eltIdx; | ||
897 | int nbrIntPnt; | ||
898 | ✗ | std::vector<Point*> pntOfNxtElt(4, nullptr); | |
899 | ✗ | std::vector<felInt> verOfNxtElt(4, 0); | |
900 | ✗ | std::vector<felInt> verOfElt(4, 0); | |
901 | ✗ | std::vector<felInt> verFacOfElt(3,-1); | |
902 | std::array<double,4> bary; | ||
903 | std::array<felInt,3> verFacOfNxtElt; | ||
904 | std::array<Point*,3> pntFacOfNxtElt; | ||
905 | ✗ | Face facOfElt; | |
906 | |||
907 | ✗ | auto& mapEltFacToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tetra4]; | |
908 | |||
909 | // Get nodes and coordinates of idxOfElt | ||
910 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, idxOfElt, verOfElt, 0); | |
911 | |||
912 | // Get the ied-th edge of the triangle | ||
913 | ✗ | verFacOfElt[0] = verOfElt[ mapEltFacToVer[idxFacInt][0] ]; | |
914 | ✗ | verFacOfElt[1] = verOfElt[ mapEltFacToVer[idxFacInt][1] ]; | |
915 | ✗ | verFacOfElt[2] = verOfElt[ mapEltFacToVer[idxFacInt][2] ]; | |
916 | ✗ | m_volMesh->getFace(verFacOfElt, facOfElt); | |
917 | |||
918 | // Loop over elements sharing the face | ||
919 | ✗ | auto& listNeigh = facOfElt.listNeighVolumes(); | |
920 | ✗ | for (std::size_t iel = 0; iel < listNeigh.size(); ++iel) { | |
921 | ✗ | eltIdx = listNeigh[iel]->idVolume(); | |
922 | |||
923 | ✗ | if ( eltIdx == idxOfPreElt ) | |
924 | ✗ | continue; | |
925 | |||
926 | // Get nodes and coordinates of the current element | ||
927 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, eltIdx, verOfNxtElt, pntOfNxtElt, 0); | |
928 | |||
929 | // Check if pntOfEdge[1] is inside the current element | ||
930 | // If it is not inside, look for an intersection with the opposite edges | ||
931 | ✗ | if ( !GeoUtilities::isPointInTetra(pntOfNxtElt, pntOfEdge[1], bary, m_tol) ) { | |
932 | |||
933 | // Loop over the three opposite faces | ||
934 | ✗ | for (std::size_t ifa = 0; ifa < 4; ++ifa) { | |
935 | |||
936 | // Get vertices of the ied-th face | ||
937 | ✗ | verFacOfNxtElt[0] = verOfNxtElt[ mapEltFacToVer[ifa][0] ]; | |
938 | ✗ | verFacOfNxtElt[1] = verOfNxtElt[ mapEltFacToVer[ifa][1] ]; | |
939 | ✗ | verFacOfNxtElt[2] = verOfNxtElt[ mapEltFacToVer[ifa][2] ]; | |
940 | |||
941 | // Skip edge | ||
942 | ✗ | if ( std::is_permutation(verFacOfElt.begin(), verFacOfElt.end(), verFacOfNxtElt.begin()) ) | |
943 | ✗ | continue; | |
944 | |||
945 | // Get the face | ||
946 | ✗ | pntFacOfNxtElt[0] = pntOfNxtElt[ mapEltFacToVer[ifa][0] ]; | |
947 | ✗ | pntFacOfNxtElt[1] = pntOfNxtElt[ mapEltFacToVer[ifa][1] ]; | |
948 | ✗ | pntFacOfNxtElt[2] = pntOfNxtElt[ mapEltFacToVer[ifa][2] ]; | |
949 | |||
950 | // Compute intersection with the edge | ||
951 | ✗ | nbrIntPnt = GeoUtilities::computeSegmentTriangleIntersection(pntOfEdge[0], pntOfEdge[1], *pntFacOfNxtElt[0], *pntFacOfNxtElt[1], *pntFacOfNxtElt[2], intPoint[0], m_tol); | |
952 | |||
953 | // If intersection | ||
954 | ✗ | if ( nbrIntPnt > 0 ) { | |
955 | |||
956 | ✗ | if ( m_verbose > 9 ) | |
957 | ✗ | std::cout << "computeIntersectionFace3D: Intersection detected in " << intPoint[0] << "." << std::endl; | |
958 | |||
959 | // Return next element to intersect | ||
960 | ✗ | idxNxtElt = eltIdx; | |
961 | |||
962 | ✗ | return true; | |
963 | } | ||
964 | } | ||
965 | } | ||
966 | // If it is inside, nothing to do | ||
967 | else { | ||
968 | |||
969 | ✗ | if ( m_verbose > 9 ) | |
970 | ✗ | std::cout << "computeIntersectionFace3D: Point " << pntOfEdge[1] << " has been found in element " << eltIdx << "." << std::endl; | |
971 | |||
972 | // Set intersection | ||
973 | ✗ | intPoint[0] = pntOfEdge[1]; | |
974 | |||
975 | // Return next element to intersect | ||
976 | ✗ | idxNxtElt = eltIdx; | |
977 | |||
978 | // Point inside element | ||
979 | ✗ | isInside = true; | |
980 | |||
981 | ✗ | return true; | |
982 | } | ||
983 | } | ||
984 | |||
985 | ✗ | return false; | |
986 | } | ||
987 | |||
988 | /***********************************************************************************/ | ||
989 | /***********************************************************************************/ | ||
990 | |||
991 | ✗ | bool Intersector::computeIntersectionInside3D(const felInt idxOfElt, felInt& idxNxtElt, const std::vector<Point>& pntOfEdge, std::vector<Point>& intPoint) const | |
992 | { | ||
993 | int nbrIntPnt; | ||
994 | ✗ | std::vector<Point*> pntOfNxtElt(4, nullptr); | |
995 | ✗ | std::vector<felInt> verOfNxtElt(4, 0); | |
996 | std::array<Point*,3> pntFacOfElt; | ||
997 | |||
998 | ✗ | auto& mapEltFacToVer = GeometricMeshRegion::m_eltTypMapFacToVer[GeometricMeshRegion::Tetra4]; | |
999 | |||
1000 | // Get nodes and coordinates of the current triangle | ||
1001 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, idxOfElt, verOfNxtElt, pntOfNxtElt, 0); | |
1002 | |||
1003 | // Loop over the faces | ||
1004 | ✗ | for (std::size_t ifa = 0; ifa < 4; ++ifa) { | |
1005 | |||
1006 | // Get the face | ||
1007 | ✗ | pntFacOfElt[0] = pntOfNxtElt[ mapEltFacToVer[ifa][0] ]; | |
1008 | ✗ | pntFacOfElt[1] = pntOfNxtElt[ mapEltFacToVer[ifa][1] ]; | |
1009 | ✗ | pntFacOfElt[2] = pntOfNxtElt[ mapEltFacToVer[ifa][2] ]; | |
1010 | |||
1011 | // Compute intersection with the face | ||
1012 | ✗ | nbrIntPnt = GeoUtilities::computeSegmentTriangleIntersection(pntOfEdge[0], pntOfEdge[1], *pntFacOfElt[0], *pntFacOfElt[1], *pntFacOfElt[2], intPoint[0], m_tol); | |
1013 | |||
1014 | // If intersection | ||
1015 | ✗ | if ( nbrIntPnt > 0 ) { | |
1016 | |||
1017 | // Return next element to intersect | ||
1018 | ✗ | idxNxtElt = idxOfElt; | |
1019 | |||
1020 | ✗ | return true; | |
1021 | } | ||
1022 | } | ||
1023 | |||
1024 | ✗ | return false; | |
1025 | } | ||
1026 | |||
1027 | /***********************************************************************************/ | ||
1028 | /***********************************************************************************/ | ||
1029 | |||
1030 | ✗ | felInt Intersector::getGermElement3D(const std::vector<felInt>& verOfEdge) const | |
1031 | { | ||
1032 | ✗ | std::vector<Point*> pntOfTetra(4, nullptr); | |
1033 | ✗ | std::vector<felInt> verOfTetra(4, 0); | |
1034 | std::array<double, 4> bary; | ||
1035 | |||
1036 | // Go through all elements of the mesh | ||
1037 | ✗ | for (felInt k = 0; k < m_volMesh->numElements(GeometricMeshRegion::Tetra4); ++k) { | |
1038 | |||
1039 | // Get nodes of the current triangle | ||
1040 | ✗ | m_volMesh->getOneElement(GeometricMeshRegion::Tetra4, k, verOfTetra, pntOfTetra, 0); | |
1041 | |||
1042 | ✗ | if( GeoUtilities::isPointInTetra( pntOfTetra, m_strMesh->listPoints()[verOfEdge[0]], bary, m_tol) ) | |
1043 | ✗ | return k; | |
1044 | } | ||
1045 | |||
1046 | ✗ | FEL_ERROR("Intersector::getGermElement3D cannot localize the point into the volume mesh."); | |
1047 | ✗ | return -1; | |
1048 | } | ||
1049 | |||
1050 | } | ||
1051 |