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
321 const label otherEdgeI,
329 label edgeI = fEdges[i];
348 <<
" connected to point " << pointi
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."
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"
561 const edge&
e = edges[edgeI];
592 scalar magMidVec =
mag(midVec);
594 if (magMidVec > SMALL)
599 borderPointVec[
e.start()] += midVec;
600 borderPointVec[
e.end()] += midVec;
614 List<triSurface::face_type>& newTris
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"
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;
918 List<labelledTri> newTris(surf.
size());
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
Same as contains().
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.
A HashTable to objects of type <T> with a label key.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
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
Same as contains().
label rcIndex(const label i) const noexcept
The reverse circular index. The previous index in the list which returns to the last at the beginning...
void size(const label n)
Older name for setAddressableSize.
label find(const T &val) const
Find index of the first occurrence of the value.
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
const Cmpt & x() const noexcept
Access to the vector x component.
const Cmpt & z() const noexcept
Access to the vector z component.
const Cmpt & y() const noexcept
Access to the vector y component.
Extract command arguments and options from the supplied argc and argv parameters.
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
static void noParallel()
Remove the parallel options.
static void addNote(const string ¬e)
Add extra notes for the usage information.
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
A topoSetPointSource to select all points based on usage in given faceSet(s).
A class for handling file names.
Triangulated surface description with patch information.
labelledTri face_type
The face type (same as the underlying PrimitivePatch).
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)
Namespace for handling debugging switches.
List< edge > edgeList
List of edge.
List< labelList > labelListList
List of labelList.
List< label > labelList
A List of labels.
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)
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
List< bool > boolList
A List of bools.
static constexpr const zero Zero
Global zero (0).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
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.