77 const point& pt = pts[i];
79 os <<
"v " << pt.
x() <<
' ' << pt.
y() <<
' ' << pt.
z() <<
endl;
88 Info<<
"Dumping borderPoints as obj file: " << fName <<
endl;
92 forAll(borderPoint, pointi)
94 if (borderPoint[pointi] != -1)
98 os <<
"v " << pt.
x() <<
' ' << pt.
y() <<
' ' << pt.
z() <<
endl;
108 Info<<
"Dumping borderEdges as obj file: " << fName <<
endl;
116 if (borderEdge[edgeI])
120 os <<
"l " <<
e.start()+1 <<
' ' <<
e.end()+1 <<
endl;
133 Info<<
"Dumping connectedFaces as obj file: " << fName <<
endl;
141 os <<
"v " << ctr.
x() <<
' ' << ctr.
y() <<
' ' << ctr.
z() <<
endl;
146void testSortedEdgeFaces(
const triSurface& surf)
153 const labelList& myFaces = edgeFaces[edgeI];
154 const labelList& sortMyFaces = sortedEdgeFaces[edgeI];
158 if (!sortMyFaces.
found(myFaces[i]))
165 if (!myFaces.
found(sortMyFaces[i]))
182 label nBorderEdges = 0;
188 if (edgeFaces[edgeI].size() == 4)
190 borderEdge[edgeI] =
true;
198 dumpEdges(surf, borderEdge);
207label markBorderPoints
219 forAll(pointEdges, pointi)
221 const labelList& pEdges = pointEdges[pointi];
223 label nBorderEdges = 0;
227 if (borderEdge[pEdges[i]])
233 if (nBorderEdges == 2 && borderPoint[pointi] == -1)
235 borderPoint[pointi] =
nPoints++;
243 dumpPoints(surf, borderPoint);
246 return nBorderPoints;
252scalar minEdgeLen(
const triSurface& surf,
const label pointi)
258 scalar minLen = GREAT;
262 label edgeI = pEdges[i];
286 label edgeI = edgeLabels[i];
308 <<
' ' << v1 <<
" in candidates " << edgeLabels
310 <<
abort(FatalError);
321 const label otherEdgeI,
329 label edgeI = fEdges[i];
348 <<
" connected to point " << pointi
350 <<
abort(FatalError);
365 const label startFacei,
366 const label startEdgeI,
367 const label startPointi,
373 label facei = startFacei;
374 label edgeI = startEdgeI;
375 label pointi = startPointi;
386 edgeI =
otherEdge(surf, facei, edgeI, pointi);
388 if (borderEdge[edgeI])
390 if (!faceToEdge.
insert(facei, edgeI))
410 if (eFaces.
size() != 2)
413 <<
"Can only handle edges with 2 or 4 edges for now."
414 <<
abort(FatalError);
417 if (eFaces[0] == facei)
421 else if (eFaces[1] == facei)
437 pointi = surf.
edges()[edgeI].otherVertex(pointi);
439 if (borderPoint[pointi] == -1)
454 const label firstFacei,
455 const label sharedEdgeI
464 label startIndex =
f.find(
e.start());
467 const bool edgeOrder = (
f[
f.fcIndex(startIndex)] ==
e.end());
475 const label faceIndex = eFaces.
find(firstFacei);
480 return eFaces[eFaces.
rcIndex(faceIndex)];
485 return eFaces[eFaces.
fcIndex(faceIndex)];
508 const label edgeI = iter.val();
510 if (!edgeDone[edgeI])
512 edgeDone[edgeI] =
true;
520 const labelList& eFaces = sortedEdgeFaces[edgeI];
524 label facei = eFaces[i];
526 if (faceToEdge.
found(facei))
532 else if (face1I == -1)
541 if (face0I == -1 && face1I == -1)
543 Info<<
"Writing surface to errorSurf.obj" <<
endl;
545 surf.
write(
"errorSurf.obj");
548 <<
"Cannot find two faces using border edge " << edgeI
549 <<
" verts:" << edges[edgeI]
550 <<
" eFaces:" << eFaces <<
endl
551 <<
"face0I:" << face0I
552 <<
" face1I:" << face1I <<
nl
553 <<
"faceToEdge:" << faceToEdge <<
nl
555 <<
"Written surface to errorSurf.obj"
556 <<
abort(FatalError);
561 const edge&
e = edges[edgeI];
570 label v0 = triSurfaceTools::oppositeVertex(surf, face0I, edgeI);
582 label v1 = triSurfaceTools::oppositeVertex(surf, face1I, edgeI);
592 scalar magMidVec =
mag(midVec);
594 if (magMidVec > SMALL)
599 borderPointVec[
e.start()] += midVec;
600 borderPointVec[
e.end()] += midVec;
619 const label facei = iter.key();
624 if (pointMap[
f[fp]] != -1)
626 newTris[facei][fp] = pointMap[
f[fp]];
647 if (borderEdge[edgeI])
651 if (borderPoint[
e.start()] == -1 && borderPoint[
e.end()] == -1)
655 edgesToBeSplit[nSplit++] = edgeI;
659 edgesToBeSplit.
setSize(nSplit);
663 Info<<
"Splitting surface along " << nSplit <<
" borderEdges that don't"
664 <<
" neighbour other borderEdges" <<
nl <<
endl;
666 surf = triSurfaceTools::greenRefine(surf, edgesToBeSplit);
677int main(
int argc,
char *argv[])
681 "Split multiply connected surface edges by duplicating points"
683 argList::noParallel();
684 argList::addArgument(
"input",
"The input surface file");
685 argList::addArgument(
"output",
"The output surface file");
686 argList::addBoolOption
689 "Add debugging output"
698 Info<<
"Reading surface from " << inSurfName <<
endl;
703 testSortedEdgeFaces(surf);
707 markBorderEdges(debug, surf, borderEdge);
713 markBorderPoints(debug, surf, borderEdge, borderPoint);
716 splitBorderEdges(surf, borderEdge, borderPoint);
719 Info<<
"Writing split surface to " << outSurfName <<
nl <<
endl;
720 surf.
write(outSurfName);
721 Info<<
"Finished writing surface to " << outSurfName <<
nl <<
endl;
725 label nOldBorderEdges = -1;
726 label nOldBorderPoints = -1;
735 label nBorderEdges = markBorderEdges(debug, surf, borderEdge);
737 if (nBorderEdges == 0)
739 Info<<
"Found no border edges. Exiting." <<
nl <<
nl;
747 label nBorderPoints =
756 if (nBorderPoints == 0)
758 Info<<
"Found no border points. Exiting." <<
nl <<
nl;
764 <<
" border edges :" << nBorderEdges <<
nl
765 <<
" border points:" << nBorderPoints <<
nl
770 nBorderPoints == nOldBorderPoints
771 && nBorderEdges == nOldBorderEdges
774 Info<<
"Stopping since number of border edges and point is same"
775 <<
" as in previous iteration" <<
nl <<
endl;
785 label startEdgeI = -1;
786 label startPointi = -1;
790 if (borderEdge[edgeI])
794 if ((borderPoint[
e[0]] != -1) && (borderPoint[
e[1]] == -1))
801 else if ((borderPoint[
e[0]] == -1) && (borderPoint[
e[1]] != -1))
811 if (startEdgeI == -1)
813 Info<<
"Cannot find starting point of splitLine\n" <<
endl;
821 label firstFacei = eFaces[0];
825 label secondFacei = sharedFace(surf, firstFacei, startEdgeI);
827 Info<<
"Starting local walk from:" <<
endl
828 <<
" edge :" << startEdgeI <<
endl
829 <<
" point:" << startPointi <<
endl
830 <<
" face0:" << firstFacei <<
endl
831 <<
" face1:" << secondFacei <<
endl
839 faceToEdge.
insert(firstFacei, startEdgeI);
855 faceToEdge.
insert(secondFacei, startEdgeI);
871 Info<<
"Finished local walk and visited" <<
nl
872 <<
" border edges :" << faceToEdge.
size() <<
nl
873 <<
" border points(but not edges):" <<
faceToPoint.size() <<
nl
878 dumpFaces(
"faceToEdge.obj", surf, faceToEdge);
891 calcPointVecs(surf, faceToEdge,
faceToPoint, borderPointVec);
896 newPoints.setSize(newPoints.size() + nBorderPoints);
898 forAll(borderPoint, pointi)
904 scalar minLen = minEdgeLen(surf, pointi);
908 newPoints[
newPointi] = newPoints[pointi] + 0.1 * minLen *
n;
923 newTris[facei].region() = surf[facei].region();
927 renumberFaces(surf, borderPoint, faceToEdge, newTris);
929 renumberFaces(surf, borderPoint,
faceToPoint, newTris);
939 const point& pt = newPoints[
f[fp]];
941 if (
mag(pt) >= GREAT/2)
943 Info<<
"newTri:" << facei <<
" verts:" <<
f
944 <<
" vert:" <<
f[fp] <<
" point:" << pt <<
endl;
952 if (debug || (iteration != 0 && (iteration % 20) == 0))
954 Info<<
"Writing surface to " << outSurfName <<
nl <<
endl;
956 surf.
write(outSurfName);
958 Info<<
"Finished writing surface to " << outSurfName <<
nl <<
endl;
962 nOldBorderEdges = nBorderEdges;
963 nOldBorderPoints = nBorderPoints;
969 Info<<
"Writing final surface to " << outSurfName <<
nl <<
endl;
971 surf.
write(outSurfName);
Various functions to operate on Lists.
bool found(const Key &key) const
Return true if hashed entry is found in table.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
label size() const noexcept
The number of elements in table.
void setSize(const label n)
Alias for resize()
A HashTable to objects of type <T> with a label key.
Output to file stream, using an OSstream.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
label nEdges() const
Number of edges in patch.
label nPoints() const
Number of points supporting patch faces.
const labelListList & pointEdges() const
Return point-edge addressing.
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.
const labelListList & edgeFaces() const
Return edge-face addressing.
const labelListList & faceEdges() const
Return face-edge addressing.
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
A List with indirect addressing. Like IndirectList but does not store addressing.
bool found(const T &val, label pos=0) const
True if the value if found in the list.
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
label rcIndex(const label i) const noexcept
void size(const label n)
Older name for setAddressableSize.
label fcIndex(const label i) const noexcept
const Cmpt & z() const
Access to the vector z component.
const Cmpt & y() const
Access to the vector y component.
const Cmpt & x() const
Access to the vector x component.
Extract command arguments and options from the supplied argc and argv parameters.
T get(const label index) const
Get a value from the argument at index.
bool found(const word &optName) const
Return true if the named option is found.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
A topoSetPointSource to select all points based on usage in given faceSet(s).
A class for handling file names.
A triFace with additional (region) index.
Triangulated surface description with patch information.
void write(Ostream &os) const
Write to Ostream in simple OpenFOAM format.
const geometricSurfacePatchList & patches() const noexcept
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
int debug
Static debugging option.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
errorManip< error > abort(error &err)
constexpr char nl
The newline '\n' character (0x0a)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.