60 <<
"triangle " << facei <<
" vertices " <<
f
61 <<
" uses point indices outside point range 0.."
67 if ((
f[0] ==
f[1]) || (
f[0] ==
f[2]) || (
f[1] ==
f[2]))
70 <<
"triangle " << facei
71 <<
" uses non-unique vertices " <<
f
72 <<
" coords:" <<
f.points(surf.
points())
85 label nbrFacei = fFaces[i];
87 if (nbrFacei <= facei)
97 ((
f[0] == nbrF[0]) || (
f[0] == nbrF[1]) || (
f[0] == nbrF[2]))
98 && ((
f[1] == nbrF[0]) || (
f[1] == nbrF[1]) || (
f[1] == nbrF[2]))
99 && ((
f[2] == nbrF[0]) || (
f[2] == nbrF[1]) || (
f[2] == nbrF[2]))
103 <<
"triangle " << facei <<
" vertices " <<
f
104 <<
" has the same vertices as triangle " << nbrFacei
105 <<
" vertices " << nbrF
106 <<
" coords:" <<
f.points(surf.
points())
124 scalar dist = nBins/(
max -
min);
130 scalar val = vals[i];
138 else if (val >=
max - small)
146 if ((index < 0) || (index >= nBins))
149 <<
"value " << val <<
" at index " << i
150 <<
" outside range " <<
min <<
" .. " <<
max <<
endl;
171 int main(
int argc,
char *argv[])
178 "checkSelfIntersection",
179 "also check for self-intersection"
184 "split surface along non-manifold edges"
185 " (default split is fully disconnected)"
195 "write vertices/blocks for blockMeshDict"
201 const bool checkSelfIntersect =
args.
optionFound(
"checkSelfIntersection");
205 Info<<
"Reading surface from " << surfFileName <<
" ..." <<
nl <<
endl;
223 Info<<
"// blockMeshDict info" <<
nl <<
nl;
225 Info<<
"vertices\n(" <<
nl;
228 Info<<
" " << cornerPts[ptI] <<
nl;
235 <<
" hex (0 1 2 3 4 5 6 7) (10 10 10) simpleGrading (1 1 1)\n"
239 <<
"patches\n();" <<
endl;
257 label region = surf[facei].region();
259 if (region < 0 || region >= regionSize.size())
262 <<
"Triangle " << facei <<
" vertices " << surf[facei]
263 <<
" has region " << region <<
" which is outside the range"
269 regionSize[region]++;
273 Info<<
"Region\tSize" <<
nl
274 <<
"------\t----" <<
nl;
292 if (!validTri(surf, facei))
294 illegalFaces.append(facei);
298 if (illegalFaces.size())
300 Info<<
"Surface has " << illegalFaces.size()
301 <<
" illegal triangles." <<
endl;
304 Info<<
"Dumping conflicting face labels to " << str.name() <<
endl
305 <<
"Paste this into the input for surfaceSubset" <<
endl;
310 Info<<
"Surface has no illegal triangles." <<
endl;
326 if (
f[0] ==
f[1] ||
f[0] ==
f[2] ||
f[1] ==
f[2])
343 labelList binCount = countBins(0, 1, 20, triQ);
345 Info<<
"Triangle quality (equilateral=1, collapsed=0):"
352 scalar dist = (1.0 - 0.0)/20.0;
356 Info<<
" " <<
min <<
" .. " <<
min+dist <<
" : "
357 << 1.0/surf.
size() * binCount[binI]
366 Info<<
" min " << triQ[minIndex] <<
" for triangle " << minIndex
368 <<
" max " << triQ[maxIndex] <<
" for triangle " << maxIndex
373 if (triQ[minIndex] < small)
376 << triQ[minIndex] <<
". This might give problems in"
377 <<
" self-intersection testing later on." <<
endl;
386 if (triQ[facei] < 1
e-11)
388 problemFaces.append(facei);
392 if (!problemFaces.empty())
396 Info<<
"Dumping bad quality faces to " << str.name() <<
endl
397 <<
"Paste this into the input for surfaceSubset" <<
nl
417 edgeMag[edgeI] = edges[edgeI].mag(localPoints);
423 const edge& minE = edges[minEdgeI];
424 const edge& maxE = edges[maxEdgeI];
428 <<
" min " << edgeMag[minEdgeI] <<
" for edge " << minEdgeI
429 <<
" points " << localPoints[minE[0]] << localPoints[minE[1]]
431 <<
" max " << edgeMag[maxEdgeI] <<
" for edge " << maxEdgeI
432 <<
" points " << localPoints[maxE[0]] << localPoints[maxE[1]]
446 scalar smallDim = 1
e-6 * bb.mag();
448 Info<<
"Checking for points less than 1e-6 of bounding box ("
449 << bb.span() <<
" metre) apart."
457 for (
label i = 1; i < sortedMag.size(); i++)
459 label ptI = sortedMag.indices()[i];
461 label prevPtI = sortedMag.indices()[i-1];
463 if (
mag(localPoints[ptI] - localPoints[prevPtI]) < smallDim)
472 const edge&
e = edges[pEdges[i]];
474 if (
e[0] == prevPtI ||
e[1] == prevPtI)
487 Info<<
" close unconnected points "
488 << ptI <<
' ' << localPoints[ptI]
489 <<
" and " << prevPtI <<
' '
490 << localPoints[prevPtI]
492 <<
mag(localPoints[ptI] - localPoints[prevPtI])
497 Info<<
" small edge between points "
498 << ptI <<
' ' << localPoints[ptI]
499 <<
" and " << prevPtI <<
' '
500 << localPoints[prevPtI]
502 <<
mag(localPoints[ptI] - localPoints[prevPtI])
508 Info<<
"Found " << nClose <<
" nearby points." <<
nl
521 label nSingleEdges = 0;
524 const labelList& myFaces = eFaces[edgeI];
526 if (myFaces.
size() == 1)
528 problemFaces.
append(myFaces[0]);
534 label nMultEdges = 0;
537 const labelList& myFaces = eFaces[edgeI];
539 if (myFaces.
size() > 2)
543 problemFaces.append(myFaces[myFacei]);
549 problemFaces.shrink();
551 if ((nSingleEdges != 0) || (nMultEdges != 0))
553 Info<<
"Surface is not closed since not all edges connected to "
554 <<
"two faces:" <<
endl
555 <<
" connected to one face : " << nSingleEdges <<
endl
556 <<
" connected to >2 faces : " << nMultEdges <<
endl;
558 Info<<
"Conflicting face labels:" << problemFaces.size() <<
endl;
562 Info<<
"Dumping conflicting face labels to " << str.name() <<
endl
563 <<
"Paste this into the input for surfaceSubset" <<
endl;
569 Info<<
"Surface is closed. All edges connected to two faces." <<
endl;
580 if (splitNonManifold)
585 if (eFaces[edgeI].size() > 2)
587 borderEdge[edgeI] =
true;
595 Info<<
"Number of unconnected parts : " << numZones <<
endl;
599 Info<<
"Splitting surface into parts ..." <<
endl <<
endl;
604 surfFileNameBase = surfFileNameBase.lessExt();
608 surfFileNameBase = surfFileNameBase.lessExt();
613 Info<<
"Writing zoning to "
619 + vtkSurfaceWriter::typeName
632 faces[i] = surf[i].triFaceFace();
638 "zone_" + surfFileNameBase,
648 for (
label zone = 0; zone < numZones; zone++)
656 includeMap[facei] =
true;
673 fileName subName(surfFileNameBase +
"_" +
name(zone) +
".obj");
675 Info<<
"writing part " << zone <<
" size " << subSurf.size()
676 <<
" to " << subName <<
endl;
678 subSurf.
write(subName);
698 <<
"Number of zones (connected area with consistent normal) : "
699 << numNormalZones <<
endl;
701 if (numNormalZones > 1)
703 Info<<
"More than one normal orientation." <<
endl;
712 if (checkSelfIntersect)
714 Info<<
"Checking self-intersection." <<
endl;
720 OBJstream intStream(
"selfInterPoints.obj");
744 intStream.write(hitInfo.hitPoint());
751 Info<<
"Surface is not self-intersecting" <<
endl;
755 Info<<
"Surface is self-intersecting at " << nInt
756 <<
" locations." <<
endl;
757 Info<<
"Writing intersection points to " << intStream.name()
#define forAll(list, i)
Loop across all elements in list.
void append(const T &)
Append an element at the end of the list.
void size(const label)
Override size to be inconsistent with allocated storage.
OFstream which keeps track of vertices.
virtual int width() const
Get width of output field.
virtual Ostream & write(const char)=0
Write character.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
label nEdges() const
Return number of edges in patch.
const labelListList & pointEdges() const
Return point-edge addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
const Field< PointType > & points() const
Return reference to global points.
const labelListList & faceFaces() const
Return face-face addressing.
const labelListList & edgeFaces() const
Return edge-face addressing.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
A list that is sorted upon construction or when explicitly requested with the sort() method.
Extract command arguments and options from the supplied argc and argv parameters.
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
bool optionFound(const word &opt) const
Return true if the named option is found.
static SLList< string > validArgs
A list of valid (mandatory) arguments.
A bounding box defined in terms of the points at its extremities.
tmp< pointField > points() const
Return corner points in an order corresponding to a 'hex' cell.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
A subset of mesh faces organised as a primitive patch.
A class for handling file names.
word name() const
Return file name (part beyond last /)
fileName path() const
Return directory path name (part before last /)
Non-pointer based hierarchical recursive searching.
Triangle with additional region number.
Helper class to search on triSurface.
Triangulated surface description with patch information.
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
const geometricSurfacePatchList & patches() const
void writeStats(Ostream &) const
Write some statistics.
A surfaceWriter for VTK legacy format with support for writing ASCII or binary.
virtual void write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const wordList &fieldNames, const bool writePointValues #define FieldTypeValuesConstArg(Type, nullArg)) const
Write fields for a single surface to file.
A class for handling words, derived from string.
int main(int argc, char *argv[])
#define WarningInFunction
Report a warning using Foam::Warning.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
Ostream & endl(Ostream &os)
Add newline and flush stream.
word name(const bool)
Return a word representation of a bool.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
fileType
Enumeration of file types.
triangle< point, const point & > triPointRef
Foam::argList args(argc, argv)