extendedFeatureEdgeMeshTemplates.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2018 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
30#include "ListListOps.H"
31#include "unitConversion.H"
32#include "bitSet.H"
33#include "PatchTools.H"
34#include "searchableBox.H"
35
36// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37
38template<class Patch>
40(
41 const Patch& surf,
42 const labelList& featureEdges,
43 const labelList& regionFeatureEdges,// subset of featureEdges: inter-region
44 const labelList& featurePoints
45)
46{
47 const pointField& sFeatLocalPts(surf.localPoints());
48 const edgeList& sFeatEds(surf.edges());
49 const labelListList edgeFaces = PatchTools::sortedEdgeFaces(surf);
50 const vectorField& faceNormals = surf.faceNormals();
52
53 // Extract and reorder the data from surfaceFeatures
54
55 // References to the surfaceFeatures data
56
57 // Filling the extendedFeatureEdgeMesh with the raw geometrical data.
58
59 label nFeatEds = featureEdges.size();
60 label nFeatPts = featurePoints.size();
61
62 DynamicList<point> tmpPts;
63 edgeList eds(nFeatEds);
64 DynamicList<vector> norms;
66 labelListList edgeNormals(nFeatEds);
68 DynamicList<label> regionEdges;
69
70 // Keep track of the ordered feature point feature edges
71 labelListList featurePointFeatureEdges(nFeatPts);
72 forAll(featurePointFeatureEdges, pI)
73 {
74 featurePointFeatureEdges[pI] = pointEdges[featurePoints[pI]];
75 }
76
77 // Mapping between old and new indices, there is entry in the map for each
78 // of surf.localPoints, -1 means that this point hasn't been used (yet),
79 // >= 0 corresponds to the index
80 labelList pointMap(sFeatLocalPts.size(), -1);
81
82 // Mapping between surface edge index and its feature edge index. -1 if it
83 // is not a feature edge
84 labelList edgeMap(sFeatEds.size(), -1);
85
86 // Noting when the normal of a face has been used so not to duplicate
87 labelList faceMap(surf.size(), -1);
88
89 // Collecting the status of edge for subsequent sorting
90 List<edgeStatus> edStatus(nFeatEds, NONE);
91
92 forAll(featurePoints, i)
93 {
94 label sFPI = featurePoints[i];
95
96 tmpPts.append(sFeatLocalPts[sFPI]);
97
98 pointMap[sFPI] = tmpPts.size() - 1;
99 }
100
101 // All feature points have been added
102 nonFeatureStart_ = tmpPts.size();
103
104 bitSet isRegionFeatureEdge(regionFeatureEdges);
105
106 forAll(featureEdges, i)
107 {
108 label sFEI = featureEdges[i];
109
110 edgeMap[sFEI] = i;
111
112 const edge& fE = sFeatEds[sFEI];
113
114 edgeDirections[i] = fE.vec(sFeatLocalPts);
115
116 // Check to see if the points have been already used
117 if (pointMap[fE.start()] == -1)
118 {
119 tmpPts.append(sFeatLocalPts[fE.start()]);
120
121 pointMap[fE.start()] = tmpPts.size() - 1;
122 }
123
124 eds[i].start() = pointMap[fE.start()];
125
126 if (pointMap[fE.end()] == -1)
127 {
128 tmpPts.append(sFeatLocalPts[fE.end()]);
129
130 pointMap[fE.end()] = tmpPts.size() - 1;
131 }
132
133 eds[i].end() = pointMap[fE.end()];
134
135 // Pick up the faces adjacent to the feature edge
136 const labelList& eFaces = edgeFaces[sFEI];
137
138 edgeNormals[i].setSize(eFaces.size());
139 normalDirections[i].setSize(eFaces.size());
140
141 forAll(eFaces, j)
142 {
143 label eFI = eFaces[j];
144
145 // Check to see if the points have been already used
146 if (faceMap[eFI] == -1)
147 {
148 norms.append(faceNormals[eFI]);
149
150 faceMap[eFI] = norms.size() - 1;
151 }
152
153 edgeNormals[i][j] = faceMap[eFI];
154
155 const vector cross = (faceNormals[eFI] ^ edgeDirections[i]);
156 const vector fC0tofE0 =
157 surf[eFI].centre(surf.points())
158 - sFeatLocalPts[fE.start()];
159
160 normalDirections[i][j] =
161 (
162 (
163 (cross/(mag(cross) + VSMALL))
164 & (fC0tofE0/(mag(fC0tofE0)+ VSMALL))
165 )
166 > 0.0
167 ? 1
168 : -1
169 );
170 }
171
172 vector fC0tofC1(Zero);
173
174 if (eFaces.size() == 2)
175 {
176 fC0tofC1 =
177 surf[eFaces[1]].centre(surf.points())
178 - surf[eFaces[0]].centre(surf.points());
179 }
180
181 edStatus[i] = classifyEdge(norms, edgeNormals[i], fC0tofC1);
182
183 if (isRegionFeatureEdge.test(i))
184 {
186 }
187 }
188
189 // Populate feature point feature edges
190 DynamicList<label> newFeatureEdges;
191
192 forAll(featurePointFeatureEdges, pI)
193 {
194 const labelList& fpfe = featurePointFeatureEdges[pI];
195
196 newFeatureEdges.setCapacity(fpfe.size());
197
198 forAll(fpfe, eI)
199 {
200 const label oldEdgeIndex = fpfe[eI];
201
202 const label newFeatureEdgeIndex = edgeMap[oldEdgeIndex];
203
204 if (newFeatureEdgeIndex != -1)
205 {
206 newFeatureEdges.append(newFeatureEdgeIndex);
207 }
208 }
209
210 featurePointFeatureEdges[pI].transfer(newFeatureEdges);
211 }
212
213 // Reorder the edges by classification
214 List<DynamicList<label>> allEds(nEdgeTypes);
215
216 DynamicList<label>& externalEds(allEds[0]);
217 DynamicList<label>& internalEds(allEds[1]);
218 DynamicList<label>& flatEds(allEds[2]);
219 DynamicList<label>& openEds(allEds[3]);
220 DynamicList<label>& multipleEds(allEds[4]);
221
222 forAll(eds, i)
223 {
224 edgeStatus eStat = edStatus[i];
225
226 if (eStat == EXTERNAL)
227 {
228 externalEds.append(i);
229 }
230 else if (eStat == INTERNAL)
231 {
232 internalEds.append(i);
233 }
234 else if (eStat == FLAT)
235 {
236 flatEds.append(i);
237 }
238 else if (eStat == OPEN)
239 {
240 openEds.append(i);
241 }
242 else if (eStat == MULTIPLE)
243 {
244 multipleEds.append(i);
245 }
246 else if (eStat == NONE)
247 {
249 << nl << "classifyEdge returned NONE on edge "
250 << eds[i]
251 << ". There is a problem with definition of this edge."
252 << nl << abort(FatalError);
253 }
254 }
255
256 internalStart_ = externalEds.size();
257 flatStart_ = internalStart_ + internalEds.size();
258 openStart_ = flatStart_ + flatEds.size();
259 multipleStart_ = openStart_ + openEds.size();
260
261 labelList edMap
262 (
263 ListListOps::combine<labelList>
264 (
265 allEds,
266 accessOp<labelList>()
267 )
268 );
269
270 edMap = invert(edMap.size(), edMap);
271
272 inplaceReorder(edMap, eds);
273 inplaceReorder(edMap, edStatus);
278
279 forAll(featurePointFeatureEdges, pI)
280 {
281 inplaceRenumber(edMap, featurePointFeatureEdges[pI]);
282 }
283
284 pointField pts(tmpPts);
285
286 // Initialise the edgeMesh
287 edgeMesh::operator=(edgeMesh(pts, eds));
288
289 // Initialise sorted edge related data
294
295 // Normals are all now found and indirectly addressed, can also be stored
296 normals_ = vectorField(norms);
297
298
299 // Reorder the feature points by classification
300
301 List<DynamicList<label>> allPts(3);
302
303 DynamicList<label>& convexPts(allPts[0]);
304 DynamicList<label>& concavePts(allPts[1]);
305 DynamicList<label>& mixedPts(allPts[2]);
306
307 for (label i = 0; i < nonFeatureStart_; i++)
308 {
309 pointStatus ptStatus = classifyFeaturePoint(i);
310
311 if (ptStatus == CONVEX)
312 {
313 convexPts.append(i);
314 }
315 else if (ptStatus == CONCAVE)
316 {
317 concavePts.append(i);
318 }
319 else if (ptStatus == MIXED)
320 {
321 mixedPts.append(i);
322 }
323 else if (ptStatus == NONFEATURE)
324 {
326 << nl << "classifyFeaturePoint returned NONFEATURE on point at "
327 << points()[i]
328 << ". There is a problem with definition of this feature point."
329 << nl << abort(FatalError);
330 }
331 }
332
333 concaveStart_ = convexPts.size();
334 mixedStart_ = concaveStart_ + concavePts.size();
335
336 labelList ftPtMap
337 (
338 ListListOps::combine<labelList>
339 (
340 allPts,
341 accessOp<labelList>()
342 )
343 );
344
345 ftPtMap = invert(ftPtMap.size(), ftPtMap);
346
347 // Creating the ptMap from the ftPtMap with identity values up to the size
348 // of pts to create an oldToNew map for inplaceReorder
349
350 labelList ptMap(identity(pts.size()));
351
352 forAll(ftPtMap, i)
353 {
354 ptMap[i] = ftPtMap[i];
355 }
356
357 inplaceReorder(ptMap, pts);
358 inplaceReorder(ptMap, featurePointFeatureEdges);
359
360 forAll(eds, i)
361 {
362 inplaceRenumber(ptMap, eds[i]);
363 }
364
365 // Reinitialise the edgeMesh with sorted feature points and
366 // renumbered edges
367 {
368 edgeMesh newmesh(std::move(pts), std::move(eds));
369 edgeMesh::transfer(newmesh);
370 }
371
372 // Generate the featurePointNormals
373
375
376 for (label i = 0; i < nonFeatureStart_; i++)
377 {
378 DynamicList<label> tmpFtPtNorms;
379
380 const labelList& ptEds = edgeMesh::pointEdges()[i];
381
382 forAll(ptEds, j)
383 {
384 const labelList& ptEdNorms(edgeNormals[ptEds[j]]);
385
386 forAll(ptEdNorms, k)
387 {
388 if (!tmpFtPtNorms.found(ptEdNorms[k]))
389 {
390 bool addNormal = true;
391
392 // Check that the normal direction is unique at this feature
393 forAll(tmpFtPtNorms, q)
394 {
395 if
396 (
397 (normals_[ptEdNorms[k]] & normals_[tmpFtPtNorms[q]])
399 )
400 {
401 // Parallel to an existing normal, do not add
402 addNormal = false;
403
404 break;
405 }
406 }
407
408 if (addNormal)
409 {
410 tmpFtPtNorms.append(ptEdNorms[k]);
411 }
412 }
413 }
414 }
415
416 featurePointNormals[i] = tmpFtPtNorms;
417 }
418
420 featurePointEdges_ = featurePointFeatureEdges;
421}
422
423
424// ************************************************************************* //
label k
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
static labelListList sortedPointEdges(const PrimitivePatch< FaceList, PointField > &)
Return point-edge addressing sorted by order around the point.
const labelListList & pointEdges() const
Return edges.
Definition: edgeMeshI.H:111
edgeMesh(const faMesh &mesh)
Construct finite-area edge mesh faMesh reference.
Definition: edgeFaMesh.H:62
const pointField & points() const noexcept
Return points.
Definition: edgeMeshI.H:99
void operator=(const edgeMesh &rhs)
Copy assignment.
Definition: edgeMeshI.H:123
labelList regionEdges_
Feature edges which are on the boundary between regions.
const labelListList & normalDirections() const
labelListList edgeNormals_
Indices of the normals that are adjacent to the feature edges.
const vectorField & edgeDirections() const
Return the edgeDirection vectors.
void sortPointsAndEdges(const Patch &, const labelUList &featureEdges, const labelUList &regionFeatureEdges, const labelUList &feaurePoints)
pointStatus classifyFeaturePoint(label ptI) const
Classify the type of feature point. Requires valid stored member.
label nonFeatureStart_
Index of the start of the non-feature points.
const labelList & regionEdges() const
Return the feature edges which are on the boundary between.
const labelListList & edgeNormals() const
Return the indices of the normals that are adjacent to the.
vectorField edgeDirections_
Flat and open edges require the direction of the edge.
label openStart_
Index of the start of the open feature edges.
labelListList featurePointEdges_
Indices of feature edges attached to feature points. The edges are.
label flatStart_
Index of the start of the flat feature edges.
@ NONFEATURE
Not a feature point.
@ MIXED
A point surrounded by both convex and concave edges.
@ CONCAVE
Fully concave point.
@ CONVEX
Fully convex point (w.r.t normals)
static edgeStatus classifyEdge(const List< vector > &norms, const labelList &edNorms, const vector &fC0tofC1)
Classify the type of feature edge. Requires face centre 0 to face.
@ FLAT
Neither concave or convex, on a flat surface.
@ OPEN
Only connected to a single face.
@ MULTIPLE
Multiply connected (connected to more than two faces)
@ NONE
Unclassified (consistency with surfaceFeatures)
@ INTERNAL
"Concave" edge
label internalStart_
Index of the start of the internal feature edges.
vectorField normals_
Normals of the features, to be referred to by index by both feature.
static constexpr label nEdgeTypes
Number of possible feature edge types (i.e. number of slices)
label mixedStart_
Index of the start of the mixed type feature points.
labelListList normalDirections_
Starting directions for the edges.
const labelListList & featurePointNormals() const
Return the indices of the normals that are adjacent to the.
label multipleStart_
Index of the start of the multiply-connected feature edges.
labelListList featurePointNormals_
Indices of the normals that are adjacent to the feature points.
static scalar cosNormalAngleTol_
Angular closeness tolerance for treating normals as the same.
label concaveStart_
Index of the start of the concave feature points.
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
Definition: triSurface.C:590
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
surfaceVectorField faceNormals(mesh.Sf()/mesh.magSf())
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
List< label > labelList
A List of labels.
Definition: List.H:66
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition: ListOps.C:36
void cross(FieldField< Field1, typename crossProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Unit conversion functions.