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
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
125 scalar dist = nBins/(max -
min);
131 scalar val = vals[i];
139 else if (val >= max - small)
145 index =
label((val - min)*dist);
147 if ((index < 0) || (index >= nBins))
150 <<
"value " << val <<
" at index " << i
151 <<
" outside range " << min <<
" .. " << max <<
endl;
172 int main(
int argc,
char *argv[])
179 "checkSelfIntersection",
180 "also check for self-intersection" 185 "split surface along non-manifold edges" 186 " (default split is fully disconnected)" 196 "write vertices/blocks for blockMeshDict" 202 const bool checkSelfIntersect =
args.
optionFound(
"checkSelfIntersection");
206 Info<<
"Reading surface from " << surfFileName <<
" ..." << nl <<
endl;
224 Info<<
"// blockMeshDict info" << nl <<
nl;
226 Info<<
"vertices\n(" <<
nl;
229 Info<<
" " << cornerPts[ptI] <<
nl;
236 <<
" hex (0 1 2 3 4 5 6 7) (10 10 10) simpleGrading (1 1 1)\n" 239 Info<<
"edges\n();" << nl
240 <<
"patches\n();" <<
endl;
242 Info<< nl <<
"// end blockMeshDict info" << nl <<
endl;
254 label region = surf[facei].region();
256 if (region < 0 || region >= regionSize.size())
259 <<
"Triangle " << facei <<
" vertices " << surf[facei]
260 <<
" has region " << region <<
" which is outside the range" 266 regionSize[region]++;
270 Info<<
"Region\tSize" << nl
271 <<
"------\t----" <<
nl;
289 if (!validTri(verbose, surf, facei))
291 illegalFaces.append(facei);
295 if (illegalFaces.size())
297 Info<<
"Surface has " << illegalFaces.size()
298 <<
" illegal triangles." <<
endl;
301 Info<<
"Dumping conflicting face labels to " << str.name() << endl
302 <<
"Paste this into the input for surfaceSubset" <<
endl;
307 Info<<
"Surface has no illegal triangles." <<
endl;
323 if (f[0] == f[1] || f[0] == f[2] || f[1] == f[2])
340 labelList binCount = countBins(0, 1, 20, triQ);
342 Info<<
"Triangle quality (equilateral=1, collapsed=0):" 349 scalar dist = (1.0 - 0.0)/20.0;
353 Info<<
" " << min <<
" .. " << min+dist <<
" : " 354 << 1.0/surf.
size() * binCount[binI]
363 Info<<
" min " << triQ[minIndex] <<
" for triangle " << minIndex
365 <<
" max " << triQ[maxIndex] <<
" for triangle " << maxIndex
370 if (triQ[minIndex] < small)
373 << triQ[minIndex] <<
". This might give problems in" 374 <<
" self-intersection testing later on." <<
endl;
383 if (triQ[facei] < 1e-11)
385 problemFaces.append(facei);
389 if (!problemFaces.empty())
393 Info<<
"Dumping bad quality faces to " << str.name() << endl
394 <<
"Paste this into the input for surfaceSubset" << nl
414 edgeMag[edgeI] = edges[edgeI].mag(localPoints);
420 const edge& minE = edges[minEdgeI];
421 const edge& maxE = edges[maxEdgeI];
424 Info<<
"Edges:" << nl
425 <<
" min " << edgeMag[minEdgeI] <<
" for edge " << minEdgeI
426 <<
" points " << localPoints[minE[0]] << localPoints[minE[1]]
428 <<
" max " << edgeMag[maxEdgeI] <<
" for edge " << maxEdgeI
429 <<
" points " << localPoints[maxE[0]] << localPoints[maxE[1]]
443 scalar smallDim = 1e-6 * bb.
mag();
445 Info<<
"Checking for points less than 1e-6 of bounding box (" 446 << bb.span() <<
" metre) apart." 454 for (
label i = 1; i < sortedMag.size(); i++)
456 label ptI = sortedMag.indices()[i];
458 label prevPtI = sortedMag.indices()[i-1];
460 if (
mag(localPoints[ptI] - localPoints[prevPtI]) < smallDim)
469 const edge& e = edges[pEdges[i]];
471 if (e[0] == prevPtI || e[1] == prevPtI)
484 Info<<
" close unconnected points " 485 << ptI <<
' ' << localPoints[ptI]
486 <<
" and " << prevPtI <<
' ' 487 << localPoints[prevPtI]
489 <<
mag(localPoints[ptI] - localPoints[prevPtI])
494 Info<<
" small edge between points " 495 << ptI <<
' ' << localPoints[ptI]
496 <<
" and " << prevPtI <<
' ' 497 << localPoints[prevPtI]
499 <<
mag(localPoints[ptI] - localPoints[prevPtI])
505 Info<<
"Found " << nClose <<
" nearby points." << nl
518 label nSingleEdges = 0;
521 const labelList& myFaces = eFaces[edgeI];
523 if (myFaces.
size() == 1)
525 problemFaces.
append(myFaces[0]);
531 label nMultEdges = 0;
534 const labelList& myFaces = eFaces[edgeI];
536 if (myFaces.
size() > 2)
540 problemFaces.append(myFaces[myFacei]);
546 problemFaces.shrink();
548 if ((nSingleEdges != 0) || (nMultEdges != 0))
550 Info<<
"Surface is not closed since not all edges connected to " 551 <<
"two faces:" << endl
552 <<
" connected to one face : " << nSingleEdges << endl
553 <<
" connected to >2 faces : " << nMultEdges <<
endl;
555 Info<<
"Conflicting face labels:" << problemFaces.size() <<
endl;
559 Info<<
"Dumping conflicting face labels to " << str.name() << endl
560 <<
"Paste this into the input for surfaceSubset" <<
endl;
566 Info<<
"Surface is closed. All edges connected to two faces." <<
endl;
577 if (splitNonManifold)
582 if (eFaces[edgeI].size() > 2)
584 borderEdge[edgeI] =
true;
592 Info<<
"Number of unconnected parts : " << numZones <<
endl;
596 Info<<
"Splitting surface into parts ..." << endl <<
endl;
599 const word fileType = surfFileNameBase.ext();
601 surfFileNameBase = surfFileNameBase.lessExt();
603 if (fileType ==
"gz")
605 surfFileNameBase = surfFileNameBase.lessExt();
610 Info<<
"Writing zoning to " 616 + vtkSurfaceWriter::typeName
618 <<
"..." << endl <<
endl;
624 scalarFaceZone[i] = faceZone[i];
629 faces[i] = surf[i].triFaceFace();
651 if (faceZone[facei] ==
zone)
653 includeMap[facei] =
true;
672 Info<<
"writing part " <<
zone <<
" size " << subSurf.
size()
673 <<
" to " << subName <<
endl;
675 subSurf.
write(subName);
695 <<
"Number of zones (connected area with consistent normal) : " 696 << numNormalZones <<
endl;
698 if (numNormalZones > 1)
700 Info<<
"More than one normal orientation." <<
endl;
709 if (checkSelfIntersect)
711 Info<<
"Checking self-intersection." <<
endl;
717 OBJstream intStream(
"selfInterPoints.obj");
741 intStream.write(hitInfo.hitPoint());
748 Info<<
"Surface is not self-intersecting" <<
endl;
752 Info<<
"Surface is self-intersecting at " << nInt
753 <<
" locations." <<
endl;
754 Info<<
"Writing intersection points to " << intStream.name()
const labelListList & pointEdges() const
Return point-edge addressing.
#define forAll(list, i)
Loop across all elements in list.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
A class for handling file names.
A list that is sorted upon construction or when explicitly requested with the sort() method...
void size(const label)
Override size to be inconsistent with allocated storage.
Ostream & endl(Ostream &os)
Add newline and flush stream.
bool optionFound(const word &opt) const
Return true if the named option is found.
static SLList< string > validArgs
A list of valid (mandatory) arguments.
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
A bounding box defined in terms of the points at its extremities.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Helper class to search on triSurface.
const labelListList & faceFaces() const
Return face-face addressing.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
void writeStats(Ostream &) const
Write some statistics.
A class for handling words, derived from string.
pointField points(const pointField &) const
Return the points corresponding to this face.
Extract command arguments and options from the supplied argc and argv parameters. ...
word name() const
Return file name (part beyond last /)
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
const Field< PointType > & points() const
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
scalar mag(const pointField &) const
Return scalar magnitude.
Triangle with additional region number.
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
label nEdges() const
Return number of edges in patch.
OFstream which keeps track of vertices.
virtual void write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const bool verbose=false) const
Write single surface geometry to file.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
word name(const complex &)
Return a string representation of a complex.
const geometricSurfacePatchList & patches() const
virtual int width() const
Get width of output field.
Non-pointer based hierarchical recursive searching.
#define WarningInFunction
Report a warning using Foam::Warning.
A surfaceWriter for VTK legacy format.
triangle< point, const point & > triPointRef
dimensioned< scalar > mag(const dimensioned< Type > &)
fileName path() const
Return directory path name (part before last /)
virtual Ostream & write(const token &)=0
Write next token to stream.
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
Triangulated surface description with patch information.
Foam::argList args(argc, argv)