triSurface_searchableSurface.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
27 #include "randomGenerator.H"
29 #include "EdgeMap.H"
30 #include "triSurfaceFields.H"
31 #include "Time.H"
32 #include "PatchTools.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  namespace searchableSurfaces
39  {
41 
43  (
45  triSurface,
47  );
48 
50  (
52  triSurface,
53  dictionary,
54  triSurfaceMesh,
55  "triSurfaceMesh"
56  );
57  }
58 }
59 
60 
61 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
62 
63 Foam::fileName Foam::searchableSurfaces::triSurface::checkFile
64 (
65  const regIOobject& io,
66  const bool isGlobal
67 )
68 {
69  const fileName fName(io.filePath(isGlobal));
70 
71  if (fName.empty())
72  {
74  << "Cannot find triSurface file starting from "
75  << io.objectPath() << exit(FatalError);
76  }
77 
78  return fName;
79 }
80 
81 
82 Foam::fileName Foam::searchableSurfaces::triSurface::relativeFilePath
83 (
84  const regIOobject& io,
85  const fileName& f,
86  const bool isGlobal
87 )
88 {
89  fileName fName(f);
90  fName.expand();
91  if (!fName.isAbsolute())
92  {
93  // Is the specified file:
94  // - local to the cwd?
95  // - local to the case dir?
96  // - or just another name?
97  fName = fileHandler().filePath(isGlobal, IOobject(io, fName));
98  }
99  return fName;
100 }
101 
102 
103 Foam::fileName Foam::searchableSurfaces::triSurface::checkFile
104 (
105  const regIOobject& io,
106  const dictionary& dict,
107  const bool isGlobal
108 )
109 {
110  fileName dictFName, fName;
111 
112  if (dict.readIfPresent("file", dictFName, false, false))
113  {
114  fName = relativeFilePath(io, dictFName, isGlobal);
115 
116  if (!exists(fName))
117  {
119  << "Cannot find triSurface file " << io.path()/dictFName
120  << exit(FatalError);
121  }
122  }
123  else
124  {
125  fName = io.filePath(isGlobal);
126 
127  if (!exists(fName))
128  {
130  << "Cannot find triSurface file starting from "
131  << io.objectPath() << exit(FatalError);
132  }
133  }
134 
135  return fName;
136 }
137 
138 
139 bool Foam::searchableSurfaces::triSurface::addFaceToEdge
140 (
141  const edge& e,
142  EdgeMap<label>& facesPerEdge
143 )
144 {
145  EdgeMap<label>::iterator eFnd = facesPerEdge.find(e);
146  if (eFnd != facesPerEdge.end())
147  {
148  if (eFnd() == 2)
149  {
150  return false;
151  }
152  eFnd()++;
153  }
154  else
155  {
156  facesPerEdge.insert(e, 1);
157  }
158  return true;
159 }
160 
161 
162 bool Foam::searchableSurfaces::triSurface::isSurfaceClosed() const
163 {
164  const pointField& pts = Foam::triSurface::points();
165 
166  // Construct pointFaces. Let's hope surface has compact point
167  // numbering ...
168  labelListList pointFaces;
169  invertManyToMany(pts.size(), *this, pointFaces);
170 
171  // Loop over all faces surrounding point. Count edges emanating from point.
172  // Every edge should be used by two faces exactly.
173  // To prevent doing work twice per edge only look at edges to higher
174  // point
175  EdgeMap<label> facesPerEdge(100);
176  forAll(pointFaces, pointi)
177  {
178  const labelList& pFaces = pointFaces[pointi];
179 
180  facesPerEdge.clear();
181  forAll(pFaces, i)
182  {
183  const triSurface::FaceType& f =
185  label fp = findIndex(f, pointi);
186 
187  // Something weird: if I expand the code of addFaceToEdge in both
188  // below instances it gives a segmentation violation on some
189  // surfaces. Compiler (4.3.2) problem?
190 
191 
192  // Forward edge
193  label nextPointi = f[f.fcIndex(fp)];
194 
195  if (nextPointi > pointi)
196  {
197  bool okFace = addFaceToEdge
198  (
199  edge(pointi, nextPointi),
200  facesPerEdge
201  );
202 
203  if (!okFace)
204  {
205  return false;
206  }
207  }
208  // Reverse edge
209  label prevPointi = f[f.rcIndex(fp)];
210 
211  if (prevPointi > pointi)
212  {
213  bool okFace = addFaceToEdge
214  (
215  edge(pointi, prevPointi),
216  facesPerEdge
217  );
218 
219  if (!okFace)
220  {
221  return false;
222  }
223  }
224  }
225 
226  // Check for any edges used only once.
227  forAllConstIter(EdgeMap<label>, facesPerEdge, iter)
228  {
229  if (iter() != 2)
230  {
231  return false;
232  }
233  }
234  }
235 
236  return true;
237 }
238 
239 
240 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
241 
243 (
244  const IOobject& io,
245  const Foam::triSurface& s
246 )
247 :
248  searchableSurface(io),
250  (
251  IOobject
252  (
253  io.name(),
254  io.instance(),
255  io.local(),
256  io.db(),
257  io.readOpt(),
258  io.writeOpt(),
259  false // searchableSurface already registered under name
260  )
261  ),
262  Foam::triSurface(s),
264  minQuality_(-1),
265  surfaceClosed_(-1)
266 {
267  const pointField& pts = Foam::triSurface::points();
268 
269  bounds() = boundBox(pts);
270 }
271 
272 
274 :
275  // Find instance for triSurface
276  searchableSurface(io),
277  // Reused found instance in objectRegistry
279  (
280  IOobject
281  (
282  io.name(),
283  searchableSurface::instance(),
284  io.local(),
285  io.db(),
286  io.readOpt(),
287  io.writeOpt(),
288  false // searchableSurface already registered under name
289  )
290  ),
292  (
293  checkFile(static_cast<const searchableSurface&>(*this), true)
294  ),
295  triSurfaceRegionSearch(static_cast<const Foam::triSurface&>(*this)),
296  minQuality_(-1),
297  surfaceClosed_(-1)
298 {
299  const pointField& pts = Foam::triSurface::points();
300 
301  bounds() = boundBox(pts);
302 }
303 
304 
306 (
307  const IOobject& io,
308  const dictionary& dict
309 )
310 :
311  searchableSurface(io),
312  // Reused found instance in objectRegistry
314  (
315  IOobject
316  (
317  io.name(),
318  searchableSurface::instance(),
319  io.local(),
320  io.db(),
321  io.readOpt(),
322  io.writeOpt(),
323  false // searchableSurface already registered under name
324  )
325  ),
327  (
328  checkFile(static_cast<const searchableSurface&>(*this), dict, true)
329  ),
330  triSurfaceRegionSearch(static_cast<const Foam::triSurface&>(*this), dict),
331  fName_
332  (
333  relativeFilePath
334  (
335  static_cast<const searchableSurface&>(*this),
336  dict.lookup("file", false, false),
337  true
338  )
339  ),
340  minQuality_(-1),
341  surfaceClosed_(-1)
342 {
343  scalar scaleFactor = 0;
344 
345  // Allow rescaling of the surface points
346  // eg, CAD geometries are often done in millimeters
347  if (dict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
348  {
349  Info<< searchableSurface::name() << " : using scale " << scaleFactor
350  << endl;
351  Foam::triSurface::scalePoints(scaleFactor);
352  }
353 
354  const pointField& pts = Foam::triSurface::points();
355 
356  bounds() = boundBox(pts);
357 
358  // Have optional minimum quality for normal calculation
359  if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0)
360  {
362  << " : ignoring triangles with quality < "
363  << minQuality_ << " for normals calculation." << endl;
364  }
365 }
366 
367 
369 (
370  const IOobject& io,
371  const bool isGlobal
372 )
373 :
374  // Find instance for triSurface
375  searchableSurface(io),
376  // Reused found instance in objectRegistry
378  (
379  IOobject
380  (
381  io.name(),
382  searchableSurface::instance(),
383  io.local(),
384  io.db(),
385  io.readOpt(),
386  io.writeOpt(),
387  false // searchableSurface already registered under name
388  )
389  ),
391  (
392  checkFile(static_cast<const searchableSurface&>(*this), isGlobal)
393  ),
394  triSurfaceRegionSearch(static_cast<const Foam::triSurface&>(*this)),
395  minQuality_(-1),
396  surfaceClosed_(-1)
397 {
398  const pointField& pts = Foam::triSurface::points();
399 
400  bounds() = boundBox(pts);
401 }
402 
403 
405 (
406  const IOobject& io,
407  const dictionary& dict,
408  const bool isGlobal
409 )
410 :
411  searchableSurface(io),
412  // Reused found instance in objectRegistry
414  (
415  IOobject
416  (
417  io.name(),
418  searchableSurface::instance(),
419  io.local(),
420  io.db(),
421  io.readOpt(),
422  io.writeOpt(),
423  false // searchableSurface already registered under name
424  )
425  ),
427  (
428  checkFile(static_cast<const searchableSurface&>(*this), dict, isGlobal)
429  ),
430  triSurfaceRegionSearch(static_cast<const Foam::triSurface&>(*this), dict),
431  minQuality_(-1),
432  surfaceClosed_(-1)
433 {
434  // Reading from supplied file name instead of objectPath/filePath
435  if (dict.readIfPresent("file", fName_, false, false))
436  {
437  fName_ = relativeFilePath
438  (
439  static_cast<const searchableSurface&>(*this),
440  fName_,
441  isGlobal
442  );
443  }
444 
445  scalar scaleFactor = 0;
446 
447  // Allow rescaling of the surface points
448  // eg, CAD geometries are often done in millimeters
449  if (dict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
450  {
451  Info<< searchableSurface::name() << " : using scale " << scaleFactor
452  << endl;
453  Foam::triSurface::scalePoints(scaleFactor);
454  }
455 
456  const pointField& pts = Foam::triSurface::points();
457 
458  bounds() = boundBox(pts);
459 
460  // Have optional minimum quality for normal calculation
461  if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0)
462  {
464  << " : ignoring triangles with quality < "
465  << minQuality_ << " for normals calculation." << endl;
466  }
467 }
468 
469 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
470 
472 {
473  clearOut();
474 }
475 
476 
478 {
480  edgeTree_.clear();
482 }
483 
484 
485 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
486 
489 {
490  tmp<pointField> tPts(new pointField(8));
491  pointField& pt = tPts.ref();
492 
493  // Use copy to calculate face centres so they don't get stored
495  (
498  ).faceCentres();
499 
500  return tPts;
501 }
502 
503 
505 (
506  pointField& centres,
507  scalarField& radiusSqr
508 ) const
509 {
510  centres = coordinates();
511  radiusSqr.setSize(size());
512  radiusSqr = 0.0;
513 
514  const pointField& pts = Foam::triSurface::points();
515 
516  forAll(*this, facei)
517  {
519  const point& fc = centres[facei];
520  forAll(f, fp)
521  {
522  const point& pt = pts[f[fp]];
523  radiusSqr[facei] = max(radiusSqr[facei], Foam::magSqr(fc-pt));
524  }
525  }
526 
527  // Add a bit to make sure all points are tested inside
528  radiusSqr += Foam::sqr(small);
529 }
530 
531 
534 {
535  return Foam::triSurface::points();
536 }
537 
538 
540 (
541  const boundBox& bb
542 ) const
543 {
544  const indexedOctree<treeDataTriSurface>& octree = tree();
545 
546  labelList indices = octree.findBox(treeBoundBox(bb));
547 
548  return !indices.empty();
549 }
550 
551 
553 (
554  const pointField& newPoints
555 )
556 {
558  edgeTree_.clear();
559  Foam::triSurface::setPoints(newPoints);
560 }
561 
562 
565 {
566  if (edgeTree_.empty())
567  {
568  // Boundary edges
569  labelList bEdges
570  (
572  (
573  nEdges()
574  -nInternalEdges()
575  )
576  + nInternalEdges()
577  );
578 
579  treeBoundBox bb(Zero, Zero);
580 
581  if (bEdges.size())
582  {
583  label nPoints;
585  (
586  *this,
587  bb,
588  nPoints
589  );
590 
591  // Slightly extended bb. Slightly off-centred just so on symmetric
592  // geometry there are less face/edge aligned items.
593  bb = bb.extend(1e-4);
594  }
595 
596  scalar oldTol = indexedOctree<treeDataEdge>::perturbTol();
598 
599  edgeTree_.reset
600  (
602  (
604  (
605  false, // cachebb
606  edges(), // edges
607  localPoints(), // points
608  bEdges // selected edges
609  ),
610  bb, // bb
611  maxTreeDepth(), // maxLevel
612  10, // leafsize
613  3.0 // duplicity
614  )
615  );
616 
618  }
619  return edgeTree_();
620 }
621 
622 
624 {
625  if (regions_.empty())
626  {
627  regions_.setSize(patches().size());
628  forAll(regions_, regionI)
629  {
630  regions_[regionI] = patches()[regionI].name();
631  }
632  }
633  return regions_;
634 }
635 
636 
638 {
639  if (surfaceClosed_ == -1)
640  {
641  if (isSurfaceClosed())
642  {
643  surfaceClosed_ = 1;
644  }
645  else
646  {
647  surfaceClosed_ = 0;
648  }
649  }
650 
651  return surfaceClosed_ == 1;
652 }
653 
654 
656 (
657  const pointField& samples,
658  const scalarField& nearestDistSqr,
659  List<pointIndexHit>& info
660 ) const
661 {
662  triSurfaceSearch::findNearest(samples, nearestDistSqr, info);
663 }
664 
665 
667 (
668  const pointField& samples,
669  const scalarField& nearestDistSqr,
670  const labelList& regionIndices,
671  List<pointIndexHit>& info
672 ) const
673 {
675  (
676  samples,
677  nearestDistSqr,
678  regionIndices,
679  info
680  );
681 }
682 
683 
685 (
686  const pointField& start,
687  const pointField& end,
688  List<pointIndexHit>& info
689 ) const
690 {
691  triSurfaceSearch::findLine(start, end, info);
692 }
693 
694 
696 (
697  const pointField& start,
698  const pointField& end,
699  List<pointIndexHit>& info
700 ) const
701 {
702  triSurfaceSearch::findLineAny(start, end, info);
703 }
704 
705 
707 (
708  const pointField& start,
709  const pointField& end,
711 ) const
712 {
713  triSurfaceSearch::findLineAll(start, end, info);
714 }
715 
716 
718 (
719  const List<pointIndexHit>& info,
720  labelList& region
721 ) const
722 {
723  region.setSize(info.size());
724  forAll(info, i)
725  {
726  if (info[i].hit())
727  {
728  region[i] = Foam::triSurface::operator[](info[i].index()).region();
729  }
730  else
731  {
732  region[i] = -1;
733  }
734  }
735 }
736 
737 
739 (
740  const List<pointIndexHit>& info,
741  vectorField& normal
742 ) const
743 {
744  const Foam::triSurface& s = *this;
745  const pointField& pts = s.points();
746 
747  normal.setSize(info.size());
748 
749  if (minQuality_ >= 0)
750  {
751  // Make sure we don't use triangles with low quality since
752  // normal is not reliable.
753 
754  const labelListList& faceFaces = s.faceFaces();
755 
756  forAll(info, i)
757  {
758  if (info[i].hit())
759  {
760  label facei = info[i].index();
761  normal[i] = s[facei].area(pts);
762 
763  scalar qual = s[facei].tri(pts).quality();
764 
765  if (qual < minQuality_)
766  {
767  // Search neighbouring triangles
768  const labelList& fFaces = faceFaces[facei];
769 
770  forAll(fFaces, j)
771  {
772  label nbrI = fFaces[j];
773  scalar nbrQual = s[nbrI].tri(pts).quality();
774  if (nbrQual > qual)
775  {
776  qual = nbrQual;
777  normal[i] = s[nbrI].area(pts);
778  }
779  }
780  }
781 
782  normal[i] /= mag(normal[i]) + vSmall;
783  }
784  else
785  {
786  // Set to what?
787  normal[i] = Zero;
788  }
789  }
790  }
791  else
792  {
793  forAll(info, i)
794  {
795  if (info[i].hit())
796  {
797  label facei = info[i].index();
798  // Cached:
799  // normal[i] = faceNormals()[facei];
800 
801  // Uncached
802  normal[i] = s[facei].normal(pts);
803  }
804  else
805  {
806  // Set to what?
807  normal[i] = Zero;
808  }
809  }
810  }
811 }
812 
813 
815 (
816  const pointField& points,
817  List<volumeType>& volType
818 ) const
819 {
820  volType.setSize(points.size());
821 
824 
825  forAll(points, pointi)
826  {
827  const point& pt = points[pointi];
828 
829  if (!tree().bb().contains(pt))
830  {
831  // Have to calculate directly as outside the octree
832  volType[pointi] = tree().shapes().getVolumeType(tree(), pt);
833  }
834  else
835  {
836  // - use cached volume type per each tree node
837  volType[pointi] = tree().getVolumeType(pt);
838  }
839  }
840 
842 }
843 
844 
846 {
848  (
850  (
851  IOobject
852  (
853  "values",
856  *this,
859  ),
860  *this,
861  dimless,
862  labelField(values)
863  )
864  );
865 
866  // Store field on triMesh
867  fldPtr.ptr()->store();
868 }
869 
870 
872 (
873  const List<pointIndexHit>& info,
874  labelList& values
875 ) const
876 {
877  if (foundObject<triSurfaceLabelField>("values"))
878  {
879  values.setSize(info.size());
880 
881  const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
882  (
883  "values"
884  );
885 
886  forAll(info, i)
887  {
888  if (info[i].hit())
889  {
890  values[i] = fld[info[i].index()];
891  }
892  }
893  }
894 }
895 
896 
898 (
902  const bool write
903 ) const
904 {
905  fileName fullPath;
906  if (fName_.size())
907  {
908  // Override file name
909 
910  fullPath = fName_;
911 
912  fullPath.expand();
913  if (!fullPath.isAbsolute())
914  {
915  // Add directory from regIOobject
916  fullPath = searchableSurface::objectPath().path()/fullPath;
917  }
918  }
919  else
920  {
921  fullPath = searchableSurface::objectPath();
922  }
923 
924  if (!mkDir(fullPath.path()))
925  {
926  return false;
927  }
928 
929  Foam::triSurface::write(fullPath);
930 
931  if (!isFile(fullPath))
932  {
933  return false;
934  }
935 
936  return true;
937 }
938 
939 
940 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
Macros for easy insertion into run-time selection tables.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
friend class iterator
Declare friendship with the iterator.
Definition: HashTable.H:194
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const word & name() const
Return name.
Definition: IOobject.H:307
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
static void calcBounds(const PrimitivePatch< FaceList, PointField > &p, boundBox &bb, label &nPoints)
A list of faces which address into the list of points.
const Field< PointType > & points() const
Return reference to global points.
std::remove_reference< ::Foam::List< labelledTri > >::type::value_type FaceType
A List obtained as a section of another List.
Definition: SubList.H:56
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
T & operator[](const label)
Return element of UList.
Definition: UListI.H:167
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
T * ptr()
Return object pointer for reuse.
Definition: autoPtrI.H:90
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
A class for handling file names.
Definition: fileName.H:82
bool isAbsolute() const
Return true if file name is absolute.
Definition: fileName.C:73
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:284
virtual fileName filePath(const bool globalFile, const IOobject &) const =0
Search for an object. globalFile : also check undecomposed case.
Non-pointer based hierarchical recursive searching.
Definition: indexedOctree.H:72
static scalar & perturbTol()
Get the perturbation tolerance.
Triangle with additional region number.
Definition: labelledTri.H:60
Registry of regIOobjects.
const Time & time() const
Return time.
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:158
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
static const word & geometryDir()
Return the geometry directory name.
const boundBox & bounds() const
Return const reference to boundBox.
A surface geometry formed of discrete facets, e.g. triangles and/or quadrilaterals,...
virtual void getVolumeType(const pointField &, List< volumeType > &) const
Determine type (inside/outside/mixed) for point. unknown if.
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find first intersection on segment from start to end.
virtual bool overlaps(const boundBox &bb) const
Does any part of the surface overlap the supplied bound box?
const indexedOctree< treeDataEdge > & edgeTree() const
Demand driven construction of octree for boundary edges.
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Return any intersection on segment from start to end.
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const
Get bounding spheres (centre and radius squared). Any point.
virtual void setField(const labelList &values)
WIP. Store element-wise field.
virtual void getField(const List< pointIndexHit > &, labelList &) const
WIP. From a set of hits (points and.
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write using given format, version and compression.
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const
From a set of points and indices get the region.
virtual const wordList & regions() const
Names of regions.
virtual bool hasVolumeType() const
Whether supports volume type below. I.e. whether is closed.
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
virtual tmp< pointField > coordinates() const
Get representative set of element coordinates.
virtual void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &) const
Get all intersections in order from start to end.
virtual void setPoints(const pointField &)
Move points.
virtual tmp< pointField > points() const
Get the points that define the surface.
string & expand(const bool allowEmpty=false)
Expand initial tildes and all occurrences of environment variables.
Definition: string.C:125
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:90
treeBoundBox extend(const scalar s) const
Return asymmetrically extended bounding box, with guaranteed.
Holds data for octree to work on an edges subset.
Definition: treeDataEdge.H:54
Helper class to search on triSurface. Creates an octree for each region of the surface and only searc...
void findNearest(const pointField &samples, const scalarField &nearestDistSqr, const labelList &regionIndices, List< pointIndexHit > &info) const
Find the nearest point on the surface out of the regions.
void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &info) const
Calculate all intersections from start to end.
void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &info) const
void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &info) const
void findNearest(const pointField &samples, const scalarField &nearestDistSqr, List< pointIndexHit > &info) const
Triangulated surface description with patch information.
Definition: triSurface.H:69
virtual void scalePoints(const scalar)
Scale points. A non-positive factor is ignored.
Definition: triSurface.C:750
triSurface()
Construct null.
Definition: triSurface.C:535
virtual void setPoints(const pointField &)
Move points.
Definition: triSurface.C:737
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const pointField & points
label nPoints
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const fvPatchList & patches
addToRunTimeSelectionTable(searchableSurface, box, dictionary)
addBackwardCompatibleToRunTimeSelectionTable(searchableSurface, box, dictionary, searchableBox, "searchableBox")
barycentric coordinates(const polyMesh &mesh, const point &position, const label celli, const label facei, const label faceTrii, const scalar stepFraction)
Return the coordinates given the position and tet topology.
Definition: tracking.C:1259
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
bool isFile(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist as a file in the file system?
Definition: POSIX.C:555
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
const doubleScalar e
Definition: doubleScalar.H:106
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
const dimensionSet dimless
bool exists(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist (as directory or file) in the file system?
Definition: POSIX.C:520
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:49
void sqr(LagrangianPatchField< typename outerProduct< Type, Type >::type > &f, const LagrangianPatchField< Type > &f1)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
void magSqr(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
void invertManyToMany(const label len, const UList< InList > &, List< OutList > &)
Invert many-to-many.
labelList f(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("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]=cellShape(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];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } 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};const 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, &mergedCyclicPolyPatch::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< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:229
dictionary dict
Fields for triSurface.
scalarField samples(nIntervals, 0)