triSurfaceCloseness.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) 2017-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "triSurfaceTools.H"
29 
30 #include "triSurface.H"
31 #include "triSurfaceMesh.H"
32 #include "triSurfaceFields.H"
33 #include "MeshedSurface.H"
34 #include "OFstream.H"
35 #include "unitConversion.H"
36 #include "meshTools.H"
37 
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42 
43 static void drawHitProblem
44 (
45  label fI,
46  const triSurface& surf,
47  const pointField& start,
48  const pointField& faceCentres,
49  const pointField& end,
50  const List<pointIndexHit>& hitInfo
51 )
52 {
53  Info<< nl << "# findLineAll did not hit its own face."
54  << nl << "# fI " << fI
55  << nl << "# start " << start[fI]
56  << nl << "# f centre " << faceCentres[fI]
57  << nl << "# end " << end[fI]
58  << nl << "# hitInfo " << hitInfo
59  << endl;
60 
61  meshTools::writeOBJ(Info, start[fI]);
62  meshTools::writeOBJ(Info, faceCentres[fI]);
64 
65  Info<< "l 1 2 3" << endl;
66 
67  meshTools::writeOBJ(Info, surf.points()[surf[fI][0]]);
68  meshTools::writeOBJ(Info, surf.points()[surf[fI][1]]);
69  meshTools::writeOBJ(Info, surf.points()[surf[fI][2]]);
70 
71  Info<< "f 4 5 6" << endl;
72 
73  forAll(hitInfo, hI)
74  {
75  label hFI = hitInfo[hI].index();
76 
77  meshTools::writeOBJ(Info, surf.points()[surf[hFI][0]]);
78  meshTools::writeOBJ(Info, surf.points()[surf[hFI][1]]);
79  meshTools::writeOBJ(Info, surf.points()[surf[hFI][2]]);
80 
81  Info<< "f "
82  << 3*hI + 7 << " "
83  << 3*hI + 8 << " "
84  << 3*hI + 9
85  << endl;
86  }
87 }
88 
89 } // End namespace Foam
90 
91 
92 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
93 
96 (
97  const Time& runTime,
98  const word& basename,
99  const triSurface& surf,
100  const scalar internalAngleTolerance,
101  const scalar externalAngleTolerance
102 )
103 {
104  Pair<tmp<scalarField>> tpair
105  (
106  tmp<scalarField>(new scalarField(surf.size(), GREAT)),
107  tmp<scalarField>(new scalarField(surf.size(), GREAT))
108  );
109 
110  Info<< "Extracting internal and external closeness of surface." << endl;
111 
112  triSurfaceMesh searchSurf
113  (
114  IOobject
115  (
116  basename + ".closeness",
117  runTime.constant(),
118  "triSurface",
119  runTime,
122  ),
123  surf
124  );
125 
126  // Prepare start and end points for intersection tests
127 
128  const vectorField& normals = searchSurf.faceNormals();
129  const scalar span = searchSurf.bounds().mag();
130 
131  const scalar externalToleranceCosAngle =
132  Foam::cos
133  (
134  degToRad(180 - externalAngleTolerance)
135  );
136 
137  const scalar internalToleranceCosAngle =
138  Foam::cos
139  (
140  degToRad(180 - internalAngleTolerance)
141  );
142 
143  Info<< "externalToleranceCosAngle: " << externalToleranceCosAngle << nl
144  << "internalToleranceCosAngle: " << internalToleranceCosAngle << endl;
145 
146  // Info<< "span " << span << endl;
147 
148  const pointField start(searchSurf.faceCentres() - span*normals);
149  const pointField end(searchSurf.faceCentres() + span*normals);
150  const pointField& faceCentres = searchSurf.faceCentres();
151 
152  List<List<pointIndexHit>> allHitInfo;
153 
154  // Find all intersections (in order)
155  searchSurf.findLineAll(start, end, allHitInfo);
156 
157  scalarField& internalCloseness = tpair[0].ref();
158  scalarField& externalCloseness = tpair[1].ref();
159 
160  forAll(allHitInfo, fI)
161  {
162  const List<pointIndexHit>& hitInfo = allHitInfo[fI];
163 
164  if (hitInfo.size() < 1)
165  {
166  drawHitProblem(fI, surf, start, faceCentres, end, hitInfo);
167 
168  // FatalErrorInFunction
169  // << "findLineAll did not hit its own face."
170  // << exit(FatalError);
171  }
172  else if (hitInfo.size() == 1)
173  {
174  if (!hitInfo[0].hit())
175  {
176  // FatalErrorInFunction
177  // << "findLineAll did not hit any face."
178  // << exit(FatalError);
179  }
180  else if (hitInfo[0].index() != fI)
181  {
183  (
184  fI,
185  surf,
186  start,
187  faceCentres,
188  end,
189  hitInfo
190  );
191 
192  // FatalErrorInFunction
193  // << "findLineAll did not hit its own face."
194  // << exit(FatalError);
195  }
196  }
197  else
198  {
199  label ownHitI = -1;
200 
201  forAll(hitInfo, hI)
202  {
203  // Find the hit on the triangle that launched the ray
204 
205  if (hitInfo[hI].index() == fI)
206  {
207  ownHitI = hI;
208 
209  break;
210  }
211  }
212 
213  if (ownHitI < 0)
214  {
216  (
217  fI,
218  surf,
219  start,
220  faceCentres,
221  end,
222  hitInfo
223  );
224 
225  // FatalErrorInFunction
226  // << "findLineAll did not hit its own face."
227  // << exit(FatalError);
228  }
229  else if (ownHitI == 0)
230  {
231  // There are no internal hits, the first hit is the
232  // closest external hit
233 
234  if
235  (
236  (
237  normals[fI]
238  & normals[hitInfo[ownHitI + 1].index()]
239  )
240  < externalToleranceCosAngle
241  )
242  {
243  externalCloseness[fI] =
244  faceCentres[fI].dist(hitInfo[ownHitI + 1].point());
245  }
246  }
247  else if (ownHitI == hitInfo.size() - 1)
248  {
249  // There are no external hits, the last but one hit is
250  // the closest internal hit
251 
252  if
253  (
254  (
255  normals[fI]
256  & normals[hitInfo[ownHitI - 1].index()]
257  )
258  < internalToleranceCosAngle
259  )
260  {
261  internalCloseness[fI] =
262  faceCentres[fI].dist(hitInfo[ownHitI - 1].point());
263  }
264  }
265  else
266  {
267  if
268  (
269  (
270  normals[fI]
271  & normals[hitInfo[ownHitI + 1].index()]
272  )
273  < externalToleranceCosAngle
274  )
275  {
276  externalCloseness[fI] =
277  faceCentres[fI].dist(hitInfo[ownHitI + 1].point());
278  }
279 
280  if
281  (
282  (
283  normals[fI]
284  & normals[hitInfo[ownHitI - 1].index()]
285  )
286  < internalToleranceCosAngle
287  )
288  {
289  internalCloseness[fI] =
290  faceCentres[fI].dist(hitInfo[ownHitI - 1].point());
291  }
292  }
293  }
294  }
295 
296  // write as 'internalCloseness'
297  {
298  triSurfaceScalarField outputField
299  (
300  IOobject
301  (
302  basename + ".internalCloseness",
303  runTime.constant(),
304  "triSurface",
305  runTime,
308  ),
309  surf,
310  dimLength,
311  scalarField()
312  );
313 
314  outputField.swap(internalCloseness);
315  outputField.write();
316  outputField.swap(internalCloseness);
317  }
318 
319  // write as 'externalCloseness'
320  {
321  triSurfaceScalarField outputField
322  (
323  IOobject
324  (
325  basename + ".externalCloseness",
326  runTime.constant(),
327  "triSurface",
328  runTime,
331  ),
332  surf,
333  dimLength,
334  scalarField()
335  );
336 
337  outputField.swap(externalCloseness);
338  outputField.write();
339  outputField.swap(externalCloseness);
340  }
341 
342  return tpair;
343 }
344 
345 
346 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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
Fields for triSurface.
Unit conversion functions.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:196
static void drawHitProblem(label fI, const triSurface &surf, const pointField &start, const pointField &faceCentres, const pointField &end, const List< pointIndexHit > &hitInfo)
Ignore writing from objectRegistry::writeObject()
virtual const boundBox & bounds() const
Return const reference to boundBox.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
IOoject and searching on triSurface.
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: instant.H:46
dimensionedScalar cos(const dimensionedScalar &ds)
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
scalar mag() const
The magnitude/length of the bounding box diagonal.
Definition: boundBoxI.H:198
const Field< point_type > & faceCentres() const
Return face centres for patch.
virtual void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &) const
Get all intersections in order from start to end.
const Field< point_type > & points() const noexcept
Return reference to global points.
static Pair< tmp< scalarField > > writeCloseness(const Time &runTime, const word &basename, const triSurface &surf, const scalar internalAngleTolerance=45, const scalar externalAngleTolerance=10)
Check and write internal/external closeness fields.
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
vector point
Point is a vector.
Definition: point.H:37
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
Nothing to be read.
messageStream Info
Information stream (stdout output on master, null elsewhere)
A class for managing temporary objects.
Definition: HashPtrTable.H:50
Triangulated surface description with patch information.
Definition: triSurface.H:71
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:172
Foam::DimensionedField< scalar, triSurfaceGeoMesh > triSurfaceScalarField
Namespace for OpenFOAM.