50 { booleanOpType::UNION,
"union" },
51 { booleanOpType::INTERSECTION,
"intersection" },
52 { booleanOpType::DIFFERENCE,
"difference" },
53 { booleanOpType::ALL,
"all" },
61void Foam::booleanSurface::checkIncluded
63 const intersectedSurface& surf,
64 const labelList& faceZone,
65 const label includedFace
68 forAll(surf.intersectionEdges(), intEdgeI)
70 label edgeI = surf.intersectionEdges()[intEdgeI];
72 const labelList& myFaces = surf.edgeFaces()[edgeI];
74 bool usesIncluded =
false;
78 if (faceZone[myFaces[myFacei]] == faceZone[includedFace])
89 <<
"None of the faces reachable from face " << includedFace
90 <<
" connects to the intersection."
98Foam::label Foam::booleanSurface::index
106 if (elems[elemI] == elem)
115Foam::label Foam::booleanSurface::findEdge
122 forAll(edgeLabels, edgeLabelI)
124 if (edges[edgeLabels[edgeLabelI]] ==
e)
126 return edgeLabels[edgeLabelI];
130 <<
"Cannot find edge " <<
e <<
" in edges " << edgeLabels
149 surf1.patches().size()
150 + surf2.patches().size()
154 label combinedPatchi = 0;
155 forAll(surf1.patches(), patchi)
157 combinedPatches[combinedPatchi++] = surf1.patches()[patchi];
161 patchMap2.setSize(surf2.patches().size());
163 forAll(surf2.patches(), patch2I)
167 forAll(surf1.patches(), patch1I)
169 if (surf1.patches()[patch1I] == surf2.patches()[patch2I])
179 combinedPatches[combinedPatchi] = surf2.patches()[patch2I];
180 patchMap2[patch2I] = combinedPatchi;
185 patchMap2[patch2I] = index;
189 combinedPatches.setSize(combinedPatchi);
191 return combinedPatches;
195void Foam::booleanSurface::propagateEdgeSide
198 const label prevVert0,
199 const label prevFacei,
200 const label prevState,
205 const labelList& eFaces = surf.sortedEdgeFaces()[edgeI];
208 if (eFaces.size() == 2)
223 if (((eFaces.size() % 2) == 1) && (eFaces.size() != 1))
226 <<
"Don't know how to handle edges with odd number of faces"
228 <<
"edge:" << edgeI <<
" vertices:" << surf.edges()[edgeI]
229 <<
" coming from face:" << prevFacei
235 label ind = index(eFaces, prevFacei);
239 const edge&
e = surf.edges()[edgeI];
245 if (
e.start() == prevVert0)
249 nextInd = eFaces.fcIndex(ind);
250 prevInd = eFaces.rcIndex(ind);
255 nextInd = eFaces.rcIndex(ind);
256 prevInd = eFaces.fcIndex(ind);
260 if (prevState == OUTSIDE)
270 if (eFacei == nextInd)
299 if (eFacei == prevInd)
322void Foam::booleanSurface::propagateSide
325 const label prevState,
330 if (side[facei] == UNVISITED)
332 side[facei] = prevState;
343 const labelList& myEdges = surf.faceEdges()[facei];
369 label edgeCA =
findEdge(surf.edges(), myEdges,
edge(c, a));
399 const label includeFace1,
400 const label includeFace2
408 Pout<<
"booleanSurface : Generating intersected surface for surf1"
413 intersectedSurface cutSurf1(surf1,
true, inter);
418 Pout<<
"booleanSurface : Generated cutSurf1: " <<
endl;
419 cutSurf1.writeStats(
Pout);
421 Pout<<
"Writing to file cutSurf1.obj" <<
endl;
422 cutSurf1.
write(
"cutSurf1.obj");
427 Pout<<
"booleanSurface : Generating intersected surface for surf2"
432 intersectedSurface cutSurf2(surf2,
false, inter);
436 Pout<<
"booleanSurface : Generated cutSurf2: " <<
endl;
437 cutSurf2.writeStats(
Pout);
439 Pout<<
"Writing to file cutSurf2.obj" <<
endl;
440 cutSurf2.
write(
"cutSurf2.obj");
445 label cutSurf1Facei = index(cutSurf1.faceMap(), includeFace1);
449 Pout<<
"cutSurf1 : starting to fill from face:" << cutSurf1Facei
453 if (cutSurf1Facei == -1)
456 <<
"Did not find face with label " << includeFace1
457 <<
" in intersectedSurface."
462 label cutSurf2Facei = index(cutSurf2.faceMap(), includeFace2);
466 Pout<<
"cutSurf2 : starting to fill from face:" << cutSurf2Facei
469 if (cutSurf2Facei == -1)
472 <<
"Did not find face with label " << includeFace2
473 <<
" in intersectedSurface."
484 const labelList& int1Edges = cutSurf1.intersectionEdges();
486 boolList isIntersectionEdge1(cutSurf1.nEdges(),
false);
487 forAll(int1Edges, intEdgeI)
489 label edgeI = int1Edges[intEdgeI];
490 isIntersectionEdge1[edgeI] =
true;
494 cutSurf1.markZones(isIntersectionEdge1, faceZone1);
498 checkIncluded(cutSurf1, faceZone1, cutSurf1Facei);
501 boolList includedFaces1(cutSurf1.size(),
false);
505 if (faceZone1[facei] == faceZone1[cutSurf1Facei])
507 includedFaces1[facei] =
true;
532 const labelList& int2Edges = cutSurf2.intersectionEdges();
534 boolList isIntersectionEdge2(cutSurf2.nEdges(),
false);
535 forAll(int2Edges, intEdgeI)
537 label edgeI = int2Edges[intEdgeI];
538 isIntersectionEdge2[edgeI] =
true;
542 cutSurf2.markZones(isIntersectionEdge2, faceZone2);
546 checkIncluded(cutSurf2, faceZone2, cutSurf2Facei);
549 boolList includedFaces2(cutSurf2.size(),
false);
553 if (faceZone2[facei] == faceZone2[cutSurf2Facei])
555 includedFaces2[facei] =
true;
590 - (cutSurf2.nPoints() - cutSurf2.nSurfacePoints())
597 cutSurf1.nPoints() - cutSurf1.nSurfacePoints()
600 label combinedPointi = 0;
602 forAll(subSurf1.points(), pointi)
605 label cutSurfPointi = pointMap1[pointi];
607 if (!cutSurf1.isSurfacePoint(cutSurfPointi))
612 intersectionLabels[cutSurfPointi] = combinedPointi;
616 combinedPoints[combinedPointi++] = subSurf1.points()[pointi];
623 forAll(subSurf2.points(), pointi)
626 label cutSurfPointi = pointMap2[pointi];
628 if (!cutSurf2.isSurfacePoint(cutSurfPointi))
631 pointMap[pointi] = intersectionLabels[cutSurfPointi];
635 pointMap[pointi] = combinedPointi;
637 combinedPoints[combinedPointi++] = subSurf2.points()[pointi];
663 List<labelledTri> combinedFaces(subSurf1.size() + subSurf2.size());
665 faceMap_.setSize(combinedFaces.size());
668 label combinedFacei = 0;
671 faceMap_[combinedFacei] = faceMap1[facei];
672 combinedFaces[combinedFacei++] = subSurf1[facei];
678 const labelledTri&
f = subSurf2[facei];
680 faceMap_[combinedFacei] = -faceMap2[facei]-1;
682 combinedFaces[combinedFacei++] =
688 patchMap2[
f.region()]
692 triSurface::operator=
710 const label booleanOp
718 Pout<<
"booleanSurface : Testing surf1 and surf2" <<
endl;
727 if (eFaces.
size() == 1)
730 <<
"surf1 is open surface at edge " << edgeI
731 <<
" verts:" << surf1.
edges()[edgeI]
732 <<
" connected to faces " << eFaces <<
endl;
743 if (eFaces.
size() == 1)
746 <<
"surf2 is open surface at edge " << edgeI
747 <<
" verts:" << surf2.
edges()[edgeI]
748 <<
" connected to faces " << eFaces <<
endl;
761 Pout<<
"booleanSurface : Generating intersected surface for surf1"
766 intersectedSurface cutSurf1(surf1,
true, inter);
770 Pout<<
"booleanSurface : Generated cutSurf1: " <<
endl;
771 cutSurf1.writeStats(
Pout);
773 Pout<<
"Writing to file cutSurf1.obj" <<
endl;
774 cutSurf1.
write(
"cutSurf1.obj");
784 Pout<<
"booleanSurface : Generating intersected surface for surf2"
789 intersectedSurface cutSurf2(surf2,
false, inter);
793 Pout<<
"booleanSurface : Generated cutSurf2: " <<
endl;
794 cutSurf2.writeStats(
Pout);
796 Pout<<
"Writing to file cutSurf2.obj" <<
endl;
797 cutSurf2.
write(
"cutSurf2.obj");
827 pointField combinedPoints(cutSurf1.nPoints() + cutSurf2.nSurfacePoints());
831 label combinedPointi = 0;
833 forAll(cutSurf1.points(), pointi)
835 combinedPoints[combinedPointi++] = cutSurf1.points()[pointi];
841 pointi < cutSurf2.nSurfacePoints();
845 combinedPoints[combinedPointi++] = cutSurf2.points()[pointi];
855 Pout<<
"booleanSurface : generated points:" <<
nl
856 <<
" 0 .. " << cutSurf1.nSurfacePoints()-1
857 <<
" : original surface1"
859 <<
" " << cutSurf1.nSurfacePoints()
860 <<
" .. " << cutSurf1.nPoints()-1
861 <<
" : intersection points"
863 <<
" " << cutSurf1.nPoints() <<
" .. "
864 << cutSurf2.nSurfacePoints()-1
865 <<
" : surface2 points"
872 List<labelledTri> combinedFaces(cutSurf1.size() + cutSurf2.size());
874 label combinedFacei = 0;
878 combinedFaces[combinedFacei++] = cutSurf1[facei];
883 labelledTri& combinedTri = combinedFaces[combinedFacei++];
885 const labelledTri& tri = cutSurf2[facei];
889 if (cutSurf2.isSurfacePoint(tri[fp]))
892 combinedTri[fp] = tri[fp] + cutSurf1.nPoints();
899 - cutSurf2.nSurfacePoints()
900 + cutSurf1.nSurfacePoints();
903 combinedTri.region() = patchMap2[tri.region()];
920 Pout<<
"booleanSurface : Generated combinedSurf: " <<
endl;
921 combinedSurf.writeStats(
Pout);
923 Pout<<
"Writing to file combinedSurf.obj" <<
endl;
924 combinedSurf.
write(
"combinedSurf.obj");
932 faceMap_.setSize(combinedSurf.size());
934 label combinedFacei = 0;
938 faceMap_[combinedFacei++] = cutSurf1.faceMap()[facei];
942 faceMap_[combinedFacei++] = -cutSurf2.faceMap()[facei] - 1;
952 point outsidePoint = 2 * treeBoundBox(combinedSurf.localPoints()).span();
963 forAll(combinedSurf, facei)
965 pointHit curHit = combinedSurf[facei].nearestPoint(outsidePoint,
pts);
967 if (curHit.distance() < minHit.distance())
976 Pout<<
"booleanSurface : found for point:" << outsidePoint
977 <<
" nearest face:" << minFacei
978 <<
" nearest point:" << minHit.point()
986 labelList side(combinedSurf.size(), UNVISITED);
989 propagateSide(combinedSurf, OUTSIDE, minFacei, side);
997 boolList include(combinedSurf.size(),
false);
1001 if (side[facei] == UNVISITED)
1004 <<
"Face " << facei <<
" has not been reached by walking from"
1005 <<
" nearest point " << minHit.point()
1008 else if (side[facei] == OUTSIDE)
1012 include[facei] =
true;
1016 include[facei] =
false;
1020 include[facei] = (facei < cutSurf1.size());
1027 include[facei] =
false;
1031 include[facei] =
true;
1035 include[facei] = (facei >= cutSurf1.size());
1045 combinedSurf.subsetMesh
1054 faceMap_.setSize(subSurf.size());
1056 forAll(subToCombinedFace, facei)
1059 label combinedFacei = subToCombinedFace[facei];
1063 if (combinedFacei < cutSurf1.size())
1065 label cutSurf1Face = combinedFacei;
1067 faceMap_[facei] = cutSurf1.faceMap()[cutSurf1Face];
1071 label cutSurf2Face = combinedFacei - cutSurf1.size();
1073 faceMap_[facei] = - cutSurf2.faceMap()[cutSurf2Face] - 1;
1078 orientedSurface outSurf(subSurf);
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
scalar distance() const noexcept
Return distance to hit.
const point_type & point() const noexcept
Return the point, no checks.
label nEdges() const
Number of edges in patch.
label nPoints() const
Number of points supporting patch faces.
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 Field< point_type > & points() const noexcept
Return reference to global points.
const labelListList & edgeFaces() const
void size(const label n)
Older name for setAddressableSize.
Surface-surface intersection. Given two surfaces construct combined surface.
static const Enum< booleanOpType > booleanOpTypeNames
booleanSurface()
Construct null.
booleanOpType
Enumeration listing the possible volume operator types.
vector span() const
The bounding box span (from minimum to maximum).
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Given triSurface and intersection creates the intersected (properly triangulated) surface....
const labelList & faceMap() const
New to old.
bool isSurfacePoint(const label pointi) const
Is point coming from original surface?
const labelList & intersectionEdges() const
Labels of edges in *this which originate from 'cuts'.
label nSurfacePoints() const
Number of points from original surface.
A triFace with additional (region) index.
label region() const noexcept
Return the region index.
Given point flip all faces such that normals point in same direction.
Basic surface-surface intersection description. Constructed from two surfaces it creates a descriptio...
Standard boundBox with extra functionality for use in octree.
Triangulated surface description with patch information.
triSurface()
Default construct.
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
triSurface subsetMesh(const UList< bool > &include, labelList &pointMap, labelList &faceMap) const
Return a new surface subsetted on the selected faces.
void write(Ostream &os) const
Write to Ostream in simple OpenFOAM format.
void writeStats(Ostream &os) const
Write some statistics.
void operator=(const triSurface &surf)
Copy assignment.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for handling debugging switches.
List< edge > edgeList
List of edge.
List< labelList > labelListList
List of labelList.
PointHit< point > pointHit
A PointHit with a 3D point.
List< label > labelList
A List of labels.
Ostream & endl(Ostream &os)
Add newline and flush stream.
errorManip< error > abort(error &err)
vector point
Point is a vector.
List< geometricSurfacePatch > geometricSurfacePatchList
List of geometricSurfacePatch.
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...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.