Go to the documentation of this file.
33 #include "triSurface.H"
39 #include "PatchTools.H"
58 if (
f[fp] < 0 ||
f[fp] >= surf.
points().size())
61 <<
"triangle " << faceI <<
" vertices " <<
f
62 <<
" uses point indices outside point range 0.."
68 if ((
f[0] ==
f[1]) || (
f[0] ==
f[2]) || (
f[1] ==
f[2]))
71 <<
"triangle " << faceI
72 <<
" uses non-unique vertices " <<
f
73 <<
" coords:" <<
f.points(surf.
points())
86 label nbrFaceI = fFaces[i];
88 if (nbrFaceI <= faceI)
98 ((
f[0] == nbrF[0]) || (
f[0] == nbrF[1]) || (
f[0] == nbrF[2]))
99 && ((
f[1] == nbrF[0]) || (
f[1] == nbrF[1]) || (
f[1] == nbrF[2]))
100 && ((
f[2] == nbrF[0]) || (
f[2] == nbrF[1]) || (
f[2] == nbrF[2]))
104 <<
"triangle " << faceI <<
" vertices " <<
f
105 <<
" has the same vertices as triangle " << nbrFaceI
106 <<
" vertices " << nbrF
107 <<
" coords:" <<
f.points(surf.
points())
125 scalar dist = nBins/(
max -
min);
131 scalar val = vals[i];
139 else if (val >=
max - SMALL)
147 if ((index < 0) || (index >= nBins))
150 <<
"value " << val <<
" at index " << i
151 <<
" outside range " <<
min <<
" .. " <<
max <<
endl;
175 const word& fieldName,
180 Info<<
"Writing zoning to "
188 + vtkSurfaceWriter::typeName
201 faces[i] = surf[i].triFaceFace();
220 const label nFaceZones,
234 includeMap[faceI] =
true;
254 /surfFileNameBase +
"_" +
name(
zone) +
".obj"
257 Info<<
"writing part " <<
zone <<
" size " << subSurf.
size()
258 <<
" to " << subName <<
endl;
260 subSurf.
write(subName);
267 int main(
int argc,
char *argv[])
273 "checkSelfIntersection",
274 "also check for self-intersection"
279 "split surface along non-manifold edges"
280 " (default split is fully disconnected)"
290 "write vertices/blocks for blockMeshDict"
296 const bool checkSelfIntersect =
args.
optionFound(
"checkSelfIntersection");
300 Info<<
"Reading surface from " << surfFileName <<
" ..." <<
nl <<
endl;
316 const word fileType = surfFileNameBase.
ext();
318 surfFileNameBase = surfFileNameBase.
lessExt();
320 if (fileType ==
"gz")
322 surfFileNameBase = surfFileNameBase.
lessExt();
332 Info<<
"// blockMeshDict info" <<
nl <<
nl;
334 Info<<
"vertices\n(" <<
nl;
337 Info<<
" " << cornerPts[ptI] <<
nl;
344 <<
" hex (0 1 2 3 4 5 6 7) (10 10 10) simpleGrading (1 1 1)\n"
348 <<
"patches\n();" <<
endl;
362 label region = surf[faceI].region();
364 if (region < 0 || region >= regionSize.size())
367 <<
"Triangle " << faceI <<
" vertices " << surf[faceI]
368 <<
" has region " << region <<
" which is outside the range"
374 regionSize[region]++;
378 Info<<
"Region\tSize" <<
nl
379 <<
"------\t----" <<
nl;
383 << regionSize[patchI] <<
nl;
397 if (!validTri(verbose, surf, faceI))
399 illegalFaces.append(faceI);
403 if (illegalFaces.size())
405 Info<<
"Surface has " << illegalFaces.size()
406 <<
" illegal triangles." <<
endl;
409 Info<<
"Dumping conflicting face labels to " << str.name() <<
endl
410 <<
"Paste this into the input for surfaceSubset" <<
endl;
415 Info<<
"Surface has no illegal triangles." <<
endl;
431 if (
f[0] ==
f[1] ||
f[0] ==
f[2] ||
f[1] ==
f[2])
448 labelList binCount = countBins(0, 1, 20, triQ);
450 Info<<
"Triangle quality (equilateral=1, collapsed=0):"
457 scalar dist = (1.0 - 0.0)/20.0;
461 Info<<
" " <<
min <<
" .. " <<
min+dist <<
" : "
462 << 1.0/surf.
size() * binCount[binI]
471 Info<<
" min " << triQ[minIndex] <<
" for triangle " << minIndex
473 <<
" max " << triQ[maxIndex] <<
" for triangle " << maxIndex
478 if (triQ[minIndex] < SMALL)
481 << triQ[minIndex] <<
". This might give problems in"
482 <<
" self-intersection testing later on." <<
endl;
491 if (triQ[faceI] < 1
e-11)
493 problemFaces.append(faceI);
497 if (!problemFaces.empty())
501 Info<<
"Dumping bad quality faces to " << str.name() <<
endl
502 <<
"Paste this into the input for surfaceSubset" <<
nl
522 edgeMag[edgeI] = edges[edgeI].mag(localPoints);
528 const edge& minE = edges[minEdgeI];
529 const edge& maxE = edges[maxEdgeI];
533 <<
" min " << edgeMag[minEdgeI] <<
" for edge " << minEdgeI
534 <<
" points " << localPoints[minE[0]] << localPoints[minE[1]]
536 <<
" max " << edgeMag[maxEdgeI] <<
" for edge " << maxEdgeI
537 <<
" points " << localPoints[maxE[0]] << localPoints[maxE[1]]
551 scalar smallDim = 1
e-6 * bb.mag();
553 Info<<
"Checking for points less than 1e-6 of bounding box ("
554 << bb.span() <<
" metre) apart."
562 for (
label i = 1; i < sortedMag.size(); i++)
564 label ptI = sortedMag.indices()[i];
566 label prevPtI = sortedMag.indices()[i-1];
568 if (
mag(localPoints[ptI] - localPoints[prevPtI]) < smallDim)
577 const edge&
e = edges[pEdges[i]];
579 if (
e[0] == prevPtI ||
e[1] == prevPtI)
592 Info<<
" close unconnected points "
593 << ptI <<
' ' << localPoints[ptI]
594 <<
" and " << prevPtI <<
' '
595 << localPoints[prevPtI]
597 <<
mag(localPoints[ptI] - localPoints[prevPtI])
602 Info<<
" small edge between points "
603 << ptI <<
' ' << localPoints[ptI]
604 <<
" and " << prevPtI <<
' '
605 << localPoints[prevPtI]
607 <<
mag(localPoints[ptI] - localPoints[prevPtI])
613 Info<<
"Found " << nClose <<
" nearby points." <<
nl
626 label nSingleEdges = 0;
629 const labelList& myFaces = edgeFaces[edgeI];
631 if (myFaces.
size() == 1)
633 problemFaces.
append(myFaces[0]);
639 label nMultEdges = 0;
642 const labelList& myFaces = edgeFaces[edgeI];
644 if (myFaces.
size() > 2)
648 problemFaces.append(myFaces[myFaceI]);
654 problemFaces.shrink();
656 if ((nSingleEdges != 0) || (nMultEdges != 0))
658 Info<<
"Surface is not closed since not all edges ("
659 << edgeFaces.
size() <<
") connected to "
660 <<
"two faces:" <<
endl
661 <<
" connected to one face : " << nSingleEdges <<
endl
662 <<
" connected to >2 faces : " << nMultEdges <<
endl;
664 Info<<
"Conflicting face labels:" << problemFaces.size() <<
endl;
668 Info<<
"Dumping conflicting face labels to " << str.name() <<
endl
669 <<
"Paste this into the input for surfaceSubset" <<
endl;
675 Info<<
"Surface is closed. All edges connected to two faces." <<
endl;
686 if (splitNonManifold)
690 if (edgeFaces[edgeI].size() > 2)
692 borderEdge[edgeI] =
true;
700 Info<<
"Number of unconnected parts : " << numZones <<
endl;
704 Info<<
"Splitting surface into parts ..." <<
endl <<
endl;
706 writeZoning(surf,
faceZone,
"zone", surfFilePath, surfFileNameBase);
733 <<
"Number of zones (connected area with consistent normal) : "
734 << numNormalZones <<
endl;
736 if (numNormalZones > 1)
738 Info<<
"More than one normal orientation." <<
endl;
739 writeZoning(surf, normalZone,
"normal", surfFilePath, surfFileNameBase);
746 surfFileNameBase +
"_normal"
756 if (checkSelfIntersect)
758 Info<<
"Checking self-intersection." <<
endl;
764 OBJstream intStream(
"selfInterPoints.obj");
788 intStream.write(hitInfo.hitPoint());
795 Info<<
"Surface is not self-intersecting" <<
endl;
799 Info<<
"Surface is self-intersecting at " << nInt
800 <<
" locations." <<
endl;
801 Info<<
"Writing intersection points to " << intStream.name()
static SLList< string > validArgs
A list of valid (mandatory) arguments.
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
const Field< PointType > & points() const
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
void writeStats(Ostream &) const
Write some statistics.
A class for handling words, derived from string.
A class for handling file names.
virtual fileName write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const bool verbose=false) const
Write single surface geometry to file.
OFstream which keeps track of vertices.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
#define forAll(list, i)
Loop across all elements in list.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
label nEdges() const
Return number of edges in patch.
virtual int width() const
Get width of output field.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
fileName path() const
Return directory path name (part before last /)
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Extract command arguments and options from the supplied argc and argv parameters.
Ostream & endl(Ostream &os)
Add newline and flush stream.
fileName lessExt() const
Return file name without extension (part before last .)
dimensioned< scalar > mag(const dimensioned< Type > &)
const geometricSurfacePatchList & patches() const
Helper class to search on triSurface.
word name() const
Return file name (part beyond last /)
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Pre-declare SubField and related Field type.
Triangulated surface description with patch information.
A subset of mesh faces organised as a primitive patch.
void append(const T &)
Append an element at the end of the list.
pointIndexHit findLine(const bool findAny, const point &treeStart, const point &treeEnd, const label startNodeI, const direction startOctantI, const FindIntersectOp &fiOp, const bool verbose=false) const
Find any or nearest intersection.
virtual Ostream & write(const token &)=0
Write next token to stream.
const labelListList & pointEdges() const
Return point-edge addressing.
Non-pointer based hierarchical recursive searching.
int main(int argc, char *argv[])
A list that is sorted upon construction or when explicitly requested with the sort() method.
word ext() const
Return file name extension (part after last .)
const double e
Elementary charge.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
bool optionFound(const word &opt) const
Return true if the named option is found.
Triangle with additional region number.
A bounding box defined in terms of the points at its extremities.
A surfaceWriter for VTK legacy format.
void size(const label)
Override size to be inconsistent with allocated storage.
static void noParallel()
Remove the parallel options.
const labelListList & faceFaces() const
Return face-face addressing.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
tmp< pointField > points() const
Return corner points in an order corresponding to a 'hex' cell.
Foam::argList args(argc, argv)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
#define WarningInFunction
Report a warning using Foam::Warning.
word name(const complex &)
Return a string representation of a complex.
triangle< point, const point & > triPointRef