searchableSurfaces.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) 2015-2022 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
29#include "searchableSurfaces.H"
31#include "ListOps.H"
32#include "Time.H"
33#include "DynamicField.H"
34#include "PatchTools.H"
35#include "coordSetWriter.H"
36#include "triSurfaceMesh.H"
37
38// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39
40namespace Foam
41{
43}
44
45
46// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47
48bool Foam::searchableSurfaces::connected
49(
50 const triSurface& s,
51 const label edgeI,
52 const pointIndexHit& hit
53)
54{
55 const edge& e = s.edges()[edgeI];
56 const labelList& mp = s.meshPoints();
57 const edge meshE(mp[e[0]], mp[e[1]]);
58
59 const triFace& f = s[hit.index()];
60
61 forAll(f, i)
62 {
63 if (meshE.otherVertex(f[i]) != -1)
64 {
65 return true;
66 }
67 }
68
69 // Account for triangle intersection routine going wrong for
70 // lines in same plane as triangle. Tbd!
71
72 vector eVec(meshE.vec(s.points()));
73 scalar magEVec(mag(eVec));
74 if (magEVec > ROOTVSMALL)
75 {
76 vector n(f.areaNormal(s.points()));
77 scalar magArea(mag(n));
78 if (magArea > ROOTVSMALL)
79 {
80 n /= magArea;
81 if (mag(n&(eVec/magEVec)) < SMALL)
82 {
83 // Bad intersection
84 return true;
85 }
86 else
87 {
88 return false;
89 }
90 }
91 }
92
93 return true;
94}
95
96
97// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
98
100:
102 regionNames_(size),
103 allSurfaces_(identity(size))
104{}
105
106
107//Foam::searchableSurfaces::searchableSurfaces
108//(
109// const IOobject& io,
110// const PtrList<dictionary>& dicts
111//)
112//:
113// PtrList<searchableSurface>(dicts.size()),
114// regionNames_(dicts.size()),
115// allSurfaces_(identity(dicts.size()))
116//{
117// forAll(dicts, surfI)
118// {
119// const dictionary& dict = dicts[surfI];
120//
121// // Make IOobject with correct name
122// autoPtr<IOobject> namedIO(io.clone());
123// namedIO().rename(dict.get<word>("name"));
124//
125// // Create and hook surface
126// set
127// (
128// surfI,
129// searchableSurface::New
130// (
131// dict.get<word>("type"),
132// namedIO(),
133// dict
134// )
135// );
136// const searchableSurface& s = operator[](surfI);
137//
138// // Construct default region names by prepending surface name
139// // to region name.
140// const wordList& localNames = s.regions();
141//
142// wordList globalNames(localNames.size());
143// forAll(localNames, regionI)
144// {
145// globalNames[regionI] = s.name() + '_' + localNames[regionI];
146// }
147//
148// // See if dictionary provides any global region names.
149// if (dict.found("regions"))
150// {
151// const dictionary& regionsDict = dict.subDict("regions");
152//
153// for (const entry& dEntry : regionsDict)
154// {
155// if (dEntry.isDict())
156// {
157// const word& key = dEntry.keyword();
158// const dictionary& regionDict = dEntry.dict();
159//
160// label index = localNames.find(key);
161//
162// if (index == -1)
163// {
164// FatalErrorInFunction
165// << "Unknown region name " << key
166// << " for surface " << s.name() << endl
167// << "Valid region names are " << localNames
168// << exit(FatalError);
169// }
170//
171// globalNames[index] = regionDict.get<word>("name");
172// }
173// }
174// }
175//
176// // Now globalNames contains the names of the regions.
177// Info<< "Surface:" << s.name() << " has regions:"
178// << endl;
179// forAll(globalNames, regionI)
180// {
181// Info<< " " << globalNames[regionI] << endl;
182// }
183//
184// // Create reverse lookup
185// forAll(globalNames, regionI)
186// {
187// regionNames_.insert
188// (
189// globalNames[regionI],
190// labelPair(surfI, regionI)
191// );
192// }
193// }
194//}
195
196
198(
199 const IOobject& io,
200 const dictionary& topDict,
201 const bool singleRegionName
202)
203:
204 PtrList<searchableSurface>(topDict.size()),
205 names_(topDict.size()),
206 regionNames_(topDict.size()),
207 allSurfaces_(identity(topDict.size()))
208{
209 label surfI = 0;
210
211 for (const entry& dEntry : topDict)
212 {
213 if (!dEntry.isDict())
214 {
216 << "Found non-dictionary entry " << dEntry
217 << " in top-level dictionary " << topDict
218 << exit(FatalError);
219 }
220
221 const word& key = dEntry.keyword();
222 const dictionary& dict = topDict.subDict(key);
223
224 names_[surfI] = dict.getOrDefault<word>("name", key);
225
226 // Make IOobject with correct name
227 autoPtr<IOobject> namedIO(io.clone());
228 // Note: we would like to e.g. register triSurface 'sphere.stl' as
229 // 'sphere'. Unfortunately
230 // no support for having object read from different location than
231 // their object name. Maybe have stlTriSurfaceMesh which appends .stl
232 // when reading/writing?
233 namedIO().rename(key); // names_[surfI]
234
235 // Create and hook surface
236 set
237 (
238 surfI,
240 (
241 dict.get<word>("type"),
242 namedIO(),
243 dict
244 )
245 );
246 const searchableSurface& s = operator[](surfI);
247
248 // Construct default region names by prepending surface name
249 // to region name.
250 const wordList& localNames = s.regions();
251
252 wordList& rNames = regionNames_[surfI];
253 rNames.setSize(localNames.size());
254
255 if (singleRegionName && localNames.size() == 1)
256 {
257 rNames[0] = names_[surfI];
258 }
259 else
260 {
261 forAll(localNames, regionI)
262 {
263 rNames[regionI] = names_[surfI] + '_' + localNames[regionI];
264 }
265 }
266
267 // See if dictionary provides any global region names.
268 if (dict.found("regions"))
269 {
270 const dictionary& regionsDict = dict.subDict("regions");
271
272 for (const entry& dEntry : regionsDict)
273 {
274 if (dEntry.isDict())
275 {
276 const word& key = dEntry.keyword();
277 const dictionary& regionDict = dEntry.dict();
278
279 label index = localNames.find(key);
280
281 if (index == -1)
282 {
284 << "Unknown region name " << key
285 << " for surface " << s.name() << nl
286 << "Valid region names are " << localNames
287 << endl
288 << exit(FatalError);
289 }
290
291 rNames[index] = regionDict.get<word>("name");
292 }
293 }
294 }
295
296 surfI++;
297 }
298
299 // Trim (not really necessary since we don't allow non-dictionary entries)
301 names_.setSize(surfI);
302 regionNames_.setSize(surfI);
303 allSurfaces_.setSize(surfI);
304}
305
306
307// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
308
310(
311 const word& wantedName
312) const
313{
314 return names_.find(wantedName);
315}
316
317
319(
320 const word& surfaceName,
321 const word& regionName
322) const
323{
324 const label surfaceIndex = findSurfaceID(surfaceName);
325
326 return this->operator[](surfaceIndex).regions().find(regionName);
327}
328
329
330// Find any intersection
332(
333 const pointField& start,
334 const pointField& end,
335 labelList& hitSurfaces,
336 List<pointIndexHit>& hitInfo
337) const
338{
340 (
341 *this,
342 allSurfaces_,
343 start,
344 end,
345 hitSurfaces,
346 hitInfo
347 );
348}
349
350
352(
353 const pointField& start,
354 const pointField& end,
355 labelListList& hitSurfaces,
356 List<List<pointIndexHit>>& hitInfo
357) const
358{
360 (
361 *this,
362 allSurfaces_,
363 start,
364 end,
365 hitSurfaces,
366 hitInfo
367 );
368}
369
370
371//Find intersections of edge nearest to both endpoints.
373(
374 const pointField& start,
375 const pointField& end,
376 labelList& surface1,
378 labelList& surface2,
380) const
381{
383 (
384 *this,
385 allSurfaces_,
386 start,
387 end,
388 surface1,
389 hit1,
390 surface2,
391 hit2
392 );
393}
394
395
397(
398 const pointField& samples,
399 const scalarField& nearestDistSqr,
400 labelList& nearestSurfaces,
401 List<pointIndexHit>& nearestInfo
402) const
403{
405 (
406 *this,
407 allSurfaces_,
408 samples,
409 nearestDistSqr,
410 nearestSurfaces,
411 nearestInfo
412 );
413}
414
415
417(
418 const labelListList& regionIndices,
419 const pointField& samples,
420 const scalarField& nearestDistSqr,
421 labelList& nearestSurfaces,
422 List<pointIndexHit>& nearestInfo
423) const
424{
426 (
427 *this,
428 allSurfaces_,
429 regionIndices,
430
431 samples,
432 nearestDistSqr,
433
434 nearestSurfaces,
435 nearestInfo
436 );
437}
438
439
441{
442 return searchableSurfacesQueries::bounds
443 (
444 *this,
445 allSurfaces_
446 );
447}
448
449
450bool Foam::searchableSurfaces::checkClosed(const bool report) const
451{
452 if (report)
453 {
454 Info<< "Checking for closedness." << endl;
455 }
456
457 bool hasError = false;
458
459 forAll(*this, surfI)
460 {
461 if (!operator[](surfI).hasVolumeType())
462 {
463 hasError = true;
464
465 if (report)
466 {
467 Info<< " " << names()[surfI]
468 << " : not closed" << endl;
469 }
470
471 if (isA<triSurface>(operator[](surfI)))
472 {
473 const triSurface& s = dynamic_cast<const triSurface&>
474 (
475 operator[](surfI)
476 );
477 const labelListList& edgeFaces = s.edgeFaces();
478
479 label nSingleEdges = 0;
480 forAll(edgeFaces, edgeI)
481 {
482 if (edgeFaces[edgeI].size() == 1)
483 {
484 nSingleEdges++;
485 }
486 }
487
488 label nMultEdges = 0;
489 forAll(edgeFaces, edgeI)
490 {
491 if (edgeFaces[edgeI].size() > 2)
492 {
493 nMultEdges++;
494 }
495 }
496
497 if (report && (nSingleEdges != 0 || nMultEdges != 0))
498 {
499 Info<< " connected to one face : "
500 << nSingleEdges << nl
501 << " connected to >2 faces : "
502 << nMultEdges << endl;
503 }
504 }
505 }
506 }
507
508 if (report)
509 {
510 Info<< endl;
511 }
512
513 return returnReduce(hasError, orOp<bool>());
514}
515
516
518{
519 if (report)
520 {
521 Info<< "Checking for normal orientation." << endl;
522 }
523
524 bool hasError = false;
525
526 forAll(*this, surfI)
527 {
528 if (isA<triSurface>(operator[](surfI)))
529 {
530 const triSurface& s = dynamic_cast<const triSurface&>
531 (
532 operator[](surfI)
533 );
534
535 labelHashSet borderEdge(s.size()/1000);
536 PatchTools::checkOrientation(s, false, &borderEdge);
537 // Colour all faces into zones using borderEdge
538 labelList normalZone;
539 label nZones = PatchTools::markZones(s, borderEdge, normalZone);
540 if (nZones > 1)
541 {
542 hasError = true;
543
544 if (report)
545 {
546 Info<< " " << names()[surfI]
547 << " : has multiple orientation zones ("
548 << nZones << ")" << endl;
549 }
550 }
551 }
552 }
553
554 if (report)
555 {
556 Info<< endl;
557 }
558
559 return returnReduce(hasError, orOp<bool>());
560}
561
562
564(
565 const scalar maxRatio,
566 const bool report
567) const
568{
569 if (report)
570 {
571 Info<< "Checking for size." << endl;
572 }
573
574 bool hasError = false;
575
576 forAll(*this, i)
577 {
578 const boundBox& bb = operator[](i).bounds();
579
580 for (label j = i+1; j < size(); j++)
581 {
582 scalar ratio = bb.mag()/operator[](j).bounds().mag();
583
584 if (ratio > maxRatio || ratio < 1.0/maxRatio)
585 {
586 hasError = true;
587
588 if (report)
589 {
590 Info<< " " << names()[i]
591 << " bounds differ from " << names()[j]
592 << " by more than a factor 100:" << nl
593 << " bounding box : " << bb << nl
594 << " bounding box : " << operator[](j).bounds()
595 << endl;
596 }
597 break;
598 }
599 }
600 }
601
602 if (report)
603 {
604 Info<< endl;
605 }
606
607 return returnReduce(hasError, orOp<bool>());
608}
609
610
612(
613 const scalar tolerance,
614 autoPtr<coordSetWriter>& setWriter,
615 const bool report
616) const
617{
618 if (report)
619 {
620 Info<< "Checking for intersection." << endl;
621 }
622
623 //cpuTime timer;
624
625 bool hasError = false;
626
627 forAll(*this, i)
628 {
629 if (isA<triSurfaceMesh>(operator[](i)))
630 {
631 const triSurfaceMesh& s0 = dynamic_cast<const triSurfaceMesh&>
632 (
633 operator[](i)
634 );
635 const edgeList& edges0 = s0.edges();
636 const pointField& localPoints0 = s0.localPoints();
637
638 // Collect all the edge vectors
639 pointField start(edges0.size());
640 pointField end(edges0.size());
641 forAll(edges0, edgeI)
642 {
643 const edge& e = edges0[edgeI];
644 start[edgeI] = localPoints0[e[0]];
645 end[edgeI] = localPoints0[e[1]];
646 }
647
648 // Test all other surfaces for intersection
649 forAll(*this, j)
650 {
652
653 //if (i == j)
654 //{
655 // // Slightly shorten the edges to prevent finding lots of
656 // // intersections. The fast triangle intersection routine
657 // // has problems with rays passing through a point of the
658 // // triangle. Now done in 'connected' routine. Tbd.
659 // vectorField d
660 // (
661 // max(tolerance, 10*s0.tolerance())
662 // *(end-start)
663 // );
664 // start += d;
665 // end -= d;
666 //}
667
668 operator[](j).findLineAny(start, end, hits);
669
670 label nHits = 0;
671 DynamicField<point> intersections(edges0.size()/100);
672 DynamicField<label> intersectionEdge(intersections.capacity());
673
674 forAll(hits, edgeI)
675 {
676 if
677 (
678 hits[edgeI].hit()
679 && (i != j || !connected(s0, edgeI, hits[edgeI]))
680 )
681 {
682 intersections.append(hits[edgeI].hitPoint());
683 intersectionEdge.append(edgeI);
684 nHits++;
685 }
686 }
687
688 // tdb. What about distributedTriSurfaceMesh?
689 //reduce(nHits, sumOp<label>());
690
691 if (nHits > 0)
692 {
693 if (report)
694 {
695 Info<< " " << names()[i]
696 << " intersects " << names()[j]
697 << " at " << nHits
698 << " locations."
699 << endl;
700
701 if (setWriter && setWriter->enabled())
702 {
703 scalarField dist(mag(intersections));
704 coordSet track
705 (
706 names()[i] + '_' + names()[j],
707 "xyz",
708 std::move(intersections),
709 std::move(dist)
710 );
711
712
713 auto& writer = *setWriter;
714 writer.nFields(1);
715
717 (
718 track,
719 (
720 s0.searchableSurface::time().path()
721 / (track.name() + "_edgeIndex")
722 )
723 );
724
725 fileName fName =
726 writer.write("edgeIndex", intersectionEdge);
727
728 writer.close(true);
729
730 Info<< " Wrote intersection locations to "
731 << fName << endl;
732 }
733 }
734
735 hasError = true;
736 break;
737 }
738 }
739 }
740 }
741
742 if (report)
743 {
744 Info<< endl;
745 }
746
747 return returnReduce(hasError, orOp<bool>());
748}
749
750
752(
753 const scalar minQuality,
754 const bool report
755) const
756{
757 if (report)
758 {
759 Info<< "Checking for triangle quality." << endl;
760 }
761
762 bool hasError = false;
763
764 forAll(*this, surfI)
765 {
766 if (isA<triSurface>(operator[](surfI)))
767 {
768 const triSurface& s = dynamic_cast<const triSurface&>
769 (
770 operator[](surfI)
771 );
772
773 label nBadTris = 0;
774 forAll(s, facei)
775 {
776 const labelledTri& f = s[facei];
777
778 scalar q = triPointRef
779 (
780 s.points()[f[0]],
781 s.points()[f[1]],
782 s.points()[f[2]]
783 ).quality();
784
785 if (q < minQuality)
786 {
787 nBadTris++;
788 }
789 }
790
791 if (nBadTris > 0)
792 {
793 hasError = true;
794
795 if (report)
796 {
797 Info<< " " << names()[surfI]
798 << " : has " << nBadTris << " bad quality triangles "
799 << " (quality < " << minQuality << ")" << endl;
800 }
801 }
802 }
803 }
804
805 if (report)
806 {
807 Info<< endl;
808 }
809
810 return returnReduce(hasError, orOp<bool>());
811
812}
813
814
815// Check all surfaces. Return number of failures.
817(
818 const bool report
819) const
820{
821 label noFailedChecks = 0;
822
823 if (checkClosed(report))
824 {
825 noFailedChecks++;
826 }
827
828 if (checkNormalOrientation(report))
829 {
830 noFailedChecks++;
831 }
832 return noFailedChecks;
833}
834
835
837(
838 const scalar maxRatio,
839 const scalar tol,
840 autoPtr<coordSetWriter>& setWriter,
841 const scalar minQuality,
842 const bool report
843) const
844{
845 label noFailedChecks = 0;
846
847 if (maxRatio > 0 && checkSizes(maxRatio, report))
848 {
849 noFailedChecks++;
850 }
851
852 if (checkIntersection(tol, setWriter, report))
853 {
854 noFailedChecks++;
855 }
856
857 if (checkQuality(minQuality, report))
858 {
859 noFailedChecks++;
860 }
861
862 return noFailedChecks;
863}
864
865
867(
869 Ostream& os
870) const
871{
872 Info<< "Statistics." << endl;
873 forAll(*this, surfI)
874 {
875 Info<< " " << names()[surfI] << ':' << endl;
876
877 const searchableSurface& s = operator[](surfI);
878
879 Info<< " type : " << s.type() << nl
880 << " size : " << s.globalSize() << nl;
881 if (isA<triSurfaceMesh>(s))
882 {
883 const triSurfaceMesh& ts = dynamic_cast<const triSurfaceMesh&>(s);
884 Info<< " edges : " << ts.nEdges() << nl
885 << " points : " << ts.points()().size() << nl;
886 }
887 Info<< " bounds : " << s.bounds() << nl
888 << " closed : " << Switch(s.hasVolumeType()) << endl;
889
890 if (patchTypes.size() && patchTypes[surfI].size() >= 1)
891 {
892 wordList unique(wordHashSet(patchTypes[surfI]).sortedToc());
893 Info<< " patches : ";
894 forAll(unique, i)
895 {
896 Info<< unique[i];
897 if (i < unique.size()-1)
898 {
899 Info<< ',';
900 }
901 }
902 Info<< endl;
903 }
904 }
905 Info<< endl;
906}
907
908
909// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
910
912(
913 const word& surfName
914) const
915{
916 const label surfI = findSurfaceID(surfName);
917
918 if (surfI < 0)
919 {
921 << "Surface named " << surfName << " not found." << nl
922 << "Available surface names: " << names_ << endl
923 << abort(FatalError);
924 }
925
926 return operator[](surfI);
927}
928
929
931(
932 const word& surfName
933)
934{
935 const label surfI = findSurfaceID(surfName);
936
937 if (surfI < 0)
938 {
940 << "Surface named " << surfName << " not found." << nl
941 << "Available surface names: " << names_ << endl
942 << abort(FatalError);
943 }
944
945 return operator[](surfI);
946}
947
948
949// ************************************************************************* //
Various functions to operate on Lists.
label n
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
Dynamically sized Field.
Definition: DynamicField.H:65
void append(const T &val)
Append an element at the end of the list.
label capacity() const noexcept
Size of the underlying storage.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
fileName path() const
The complete path.
Definition: IOobject.C:524
autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:459
void setSize(const label n)
Alias for resize()
Definition: List.H:218
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
static bool checkOrientation(const PrimitivePatch< FaceList, PointField > &, const bool report=false, labelHashSet *marked=0)
Check for orientation issues.
static label markZones(const PrimitivePatch< FaceList, PointField > &, const BoolListType &borderEdge, labelList &faceZone)
Size and fills faceZone with zone of face.
label nEdges() const
Number of edges in patch.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const searchableSurface * set(const label i) const
Definition: PtrList.H:138
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:151
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:78
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:212
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:64
scalar mag() const
The magnitude of the bounding box span.
Definition: boundBoxI.H:133
Holds list of sampling positions.
Definition: coordSet.H:56
const word & name() const noexcept
The coord-set name.
Definition: coordSet.H:134
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
friend Ostream & operator(Ostream &, const faMatrix< Type > &)
A class for handling file names.
Definition: fileName.H:76
void checkSizes() const
Check that all components of sizes() are non-negative.
A triFace with additional (region) index.
Definition: labelledTri.H:60
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
static void findNearestIntersection(const PtrList< searchableSurface > &allSurfaces, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &surface2, List< pointIndexHit > &hit2)
Find intersections of edge nearest to both endpoints.
static void findAnyIntersection(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &)
Find any intersection. Return hit point information and.
static void findAllIntersections(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelListList &surfaces, List< List< pointIndexHit > > &surfaceHits)
Find all intersections in order from start to end. Returns for.
static void findNearest(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &)
Find nearest. Return -1 (and a miss()) or surface and nearest.
Container for searchableSurfaces. The collection is specified as a dictionary. For example,...
bool checkQuality(const scalar minQuality, const bool report) const
Check triangle quality.
bool checkIntersection(const scalar tol, autoPtr< coordSetWriter > &setWriter, const bool report) const
Do surfaces self-intersect or intersect others.
boundBox bounds() const
Calculate bounding box.
label findSurfaceRegionID(const word &surfaceName, const word &regionName) const
bool checkClosed(const bool report) const
Are all surfaces closed and manifold.
const searchableSurface & operator[](const word &) const
Return const reference to searchableSurface by name.
void findAllIntersections(const pointField &start, const pointField &end, labelListList &surfaces, List< List< pointIndexHit > > &) const
Find all intersections in order from start to end. Returns for.
label checkTopology(const bool report) const
All topological checks. Return number of failed checks.
label checkGeometry(const scalar maxRatio, const scalar tolerance, autoPtr< coordSetWriter > &setWriter, const scalar minQuality, const bool report) const
All geometric checks. Return number of failed checks.
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Find any intersection. Return hit point information and.
void writeStats(const List< wordList > &, Ostream &) const
Write some stats.
bool checkNormalOrientation(const bool report) const
Are all (triangulated) surfaces consistent normal orientation.
void findNearest(const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest. Return -1 (and a miss()) or surface and nearest.
label findSurfaceID(const word &name) const
Find index of surface. Return -1 if not found.
void findNearestIntersection(const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &surface2, List< pointIndexHit > &hit2) const
IOoject and searching on triSurface.
virtual tmp< pointField > points() const
Get the points that define the surface.
Triangulated surface description with patch information.
Definition: triSurface.H:79
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
void close()
End the file contents and close the file after writing.
virtual bool open(const fileName &file, bool parallel=Pstream::parRun())
Open file for writing (creates parent directory).
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
Foam::word regionName(Foam::polyMesh::defaultRegion)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
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))
label nZones
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
Namespace for OpenFOAM.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
List< label > labelList
A List of labels.
Definition: List.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangle.H:71
errorManip< error > abort(error &err)
Definition: errorManip.H:144
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:82
error FatalError
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
wordList patchTypes(nPatches)
face triFace(3)
labelList f(nPoints)
dictionary dict
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
scalarField samples(nIntervals, Zero)