smoothTriSurfaceMesh.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) 2016-2018 OpenFOAM Foundation
9  Copyright (C) 2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 
29 #include "smoothTriSurfaceMesh.H"
31 #include "unitConversion.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 defineTypeNameAndDebug(smoothTriSurfaceMesh, 0);
39 addToRunTimeSelectionTable(searchableSurface, smoothTriSurfaceMesh, dict);
40 
41 }
42 
43 
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 
46 void Foam::smoothTriSurfaceMesh::calcFeatureEdges(const scalar featureAngle)
47 {
48  if (featureAngle <= -180)
49  {
50  return;
51  }
52 
53  const triSurface& s = *this;
54 
55  scalar cosAngle = Foam::cos(degToRad(featureAngle));
56 
57  const labelListList& edgeFaces = s.edgeFaces();
58  const edgeList& edges = s.edges();
59 
60  forAll(edgeFaces, edgei)
61  {
62  const labelList& eFaces = edgeFaces[edgei];
63 
64  if (eFaces.size() > 2)
65  {
66  isBorderEdge_[edgei] = true;
67  }
68  else if (eFaces.size() == 2)
69  {
70  const vector n0(s[eFaces[0]].unitNormal(points()));
71  const vector n1(s[eFaces[1]].unitNormal(points()));
72  if ((n0&n1) < cosAngle)
73  {
74  isBorderEdge_[edgei] = true;
75  }
76  }
77  }
78 
79  forAll(isBorderEdge_, edgei)
80  {
81  if (isBorderEdge_[edgei])
82  {
83  const edge& e = edges[edgei];
84  isPointOnBorderEdge_[e[0]] = true;
85  isPointOnBorderEdge_[e[1]] = true;
86  }
87  }
88 }
89 
90 
91 Foam::vector Foam::smoothTriSurfaceMesh::pointNormal
92 (
93  const label startFacei,
94  const label localPointi
95 ) const
96 {
97  const triSurface& s = *this;
98 
99  if (!isPointOnBorderEdge_[localPointi])
100  {
101  const labelList& pFaces = pointFaces()[localPointi];
102  vector pn(Zero);
103  forAll(pFaces, i)
104  {
105  label facei = pFaces[i];
106  pn += s[facei].unitNormal(points());
107  }
108  return pn.normalise();
109  }
110 
111 
112  // Calculate the local point normal on the face. This routine
113  // only gets called if the point is on a border edge so we can
114  // walk and always hit a border edge.
115 
116  const edgeList& edges = triSurface::edges();
117  const labelList& fEdges = faceEdges()[startFacei];
118 
119  // Get the two edges on the point
120  label e0 = -1;
121  label e1 = -1;
122  forAll(fEdges, i)
123  {
124  const edge& e = edges[fEdges[i]];
125  if (e.otherVertex(localPointi) == -1)
126  {
127  e0 = fEdges[fEdges.rcIndex(i)];
128  e1 = fEdges[fEdges.fcIndex(i)];
129  break;
130  }
131  }
132 
133  label facei = startFacei;
134  label edgei = e0;
135 
136  // Initialise normal
137  vector n(s[facei].unitNormal(points()));
138 
139  while (!isBorderEdge_[edgei])
140  {
141  // Cross edge to next face
142  const labelList& eFaces = edgeFaces()[edgei];
143  if (eFaces.size() != 2)
144  {
145  break;
146  }
147 
148  forAll(eFaces, i)
149  {
150  if (eFaces[i] != facei)
151  {
152  facei = eFaces[i];
153  break;
154  }
155  }
156 
157  if (facei == startFacei)
158  {
159  break;
160  }
161 
162  n += s[facei].unitNormal(points());
163 
164  // Cross face to next edge
165  const labelList& fEdges = faceEdges()[facei];
166 
167  forAll(fEdges, i)
168  {
169  label ei = fEdges[i];
170  if (ei != edgei && edges[ei].otherVertex(localPointi) != -1)
171  {
172  edgei = ei;
173  break;
174  }
175  }
176  }
177 
178 
179  // Walk in other direction
180  {
181 
182  facei = startFacei;
183  edgei = e1;
184 
185  while (!isBorderEdge_[edgei])
186  {
187  // Cross edge to next face
188  const labelList& eFaces = edgeFaces()[edgei];
189  if (eFaces.size() != 2)
190  {
191  break;
192  }
193 
194  forAll(eFaces, i)
195  {
196  if (eFaces[i] != facei)
197  {
198  facei = eFaces[i];
199  break;
200  }
201  }
202 
203  if (facei == startFacei)
204  {
205  break;
206  }
207 
208  n += s[facei].unitNormal(points());
209 
210  // Cross face to next edge
211  const labelList& fEdges = faceEdges()[facei];
212 
213  forAll(fEdges, i)
214  {
215  label ei = fEdges[i];
216  if (ei != edgei && edges[ei].otherVertex(localPointi) != -1)
217  {
218  edgei = ei;
219  break;
220  }
221  }
222  }
223  }
224 
225  return n.normalise();
226 }
227 
228 
229 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
230 
231 Foam::smoothTriSurfaceMesh::smoothTriSurfaceMesh
232 (
233  const IOobject& io,
234  const scalar featureAngle
235 )
236 :
238  isBorderEdge_(nEdges()),
239  isPointOnBorderEdge_(nPoints())
240 {
241  calcFeatureEdges(featureAngle);
242 }
243 
244 
245 Foam::smoothTriSurfaceMesh::smoothTriSurfaceMesh
246 (
247  const IOobject& io,
248  const dictionary& dict
249 )
250 :
252  isBorderEdge_(nEdges()),
253  isPointOnBorderEdge_(nPoints())
254 {
255  if (dict.found("featureAngle"))
256  {
257  calcFeatureEdges(readScalar(dict.lookup("featureAngle")));
258  }
259 }
260 
261 
262 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
263 
265 {}
266 
267 
268 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
269 
271 (
272  const List<pointIndexHit>& info,
273  vectorField& normal
274 ) const
275 {
276  const triSurface& s = static_cast<const triSurface&>(*this);
277  const pointField& pts = s.points();
278 
279  DebugPout<< "smoothTriSurfaceMesh::getNormal :"
280  << " surface:" << this->searchableSurface::name()
281  << " tris:" << s.size()
282  << " feat edges:" << isBorderEdge_.count()
283  << endl;
284 
285  normal.setSize(info.size());
286 
287  forAll(info, i)
288  {
289  if (info[i].hit())
290  {
291  label facei = info[i].index();
292 
293  // Get local coordinates in triangle
295  (
296  s[facei].tri(pts).pointToBarycentric(info[i].hitPoint())
297  );
298 
299  // Average point normals
300  const triFace& localTri = s.localFaces()[facei];
301 
302  vector n(Zero);
303  forAll(localTri, fp)
304  {
305  n += coordinates[fp]*pointNormal(facei, localTri[fp]);
306  }
307  normal[i] = n.normalise();
308  }
309  else
310  {
311  // Set to what?
312  normal[i] = Zero;
313  }
314  }
315 }
316 
317 
318 // ************************************************************************* //
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
virtual tmp< pointField > points() const
Get the points that define the surface.
Unit conversion functions.
virtual ~smoothTriSurfaceMesh()
Destructor.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
IOoject and searching on triSurface.
Templated 2D Barycentric derived from VectorSpace. Has 3 components, one of which is redundant...
Definition: Barycentric2D.H:50
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:325
dimensionedScalar cos(const dimensionedScalar &ds)
const pointField & points
label nPoints
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:65
const labelListList & edgeFaces() const
Return edge-face addressing.
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} pointMap[start]=pointMap[end]=Foam::min(start, end);} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};constexpr label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< DynamicList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:233
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Vector< scalar > vector
Definition: vector.H:57
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
defineTypeNameAndDebug(combustionModel, 0)
triSurface()
Default construct.
Definition: triSurface.C:426
PtrList< coordinateSystem > coordinates(solidRegions.size())
#define DebugPout
Report an information message using Foam::Pout.
label n
List< label > labelList
A List of labels.
Definition: List.H:61
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Triangulated surface description with patch information.
Definition: triSurface.H:71
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
const pointField & pts
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127