50 { booleanOpType::UNION,
"union" },
51 { booleanOpType::INTERSECTION,
"intersection" },
52 { booleanOpType::DIFFERENCE,
"difference" },
53 { booleanOpType::ALL,
"all" },
61 void Foam::booleanSurface::checkIncluded
63 const intersectedSurface& surf,
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." 98 Foam::label Foam::booleanSurface::index
106 if (elems[elemI] == elem)
115 Foam::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
141 const triSurface& surf1,
142 const triSurface& surf2,
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;
195 void Foam::booleanSurface::propagateEdgeSide
197 const triSurface& surf,
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)
322 void Foam::booleanSurface::propagateSide
324 const triSurface& surf,
325 const label prevState,
330 if (side[facei] == UNVISITED)
332 side[facei] = prevState;
334 const labelledTri& tri = surf.localFaces()[facei];
343 const labelList& myEdges = surf.faceEdges()[facei];
345 label edgeAB =
findEdge(surf.edges(), myEdges, edge(a,
b));
357 label edgeBC =
findEdge(surf.edges(), myEdges, edge(
b,
c));
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);
void size(const label n)
Older name for setAddressableSize.
booleanSurface()
Construct null.
errorManipArg< error, int > exit(error &err, const int errNo=1)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
List< edge > edgeList
List of edge.
constexpr char nl
The newline '\n' character (0x0a)
Basic surface-surface intersection description. Constructed from two surfaces it creates a descriptio...
Ostream & endl(Ostream &os)
Add newline and flush stream.
#define forAll(list, i)
Loop across all elements in list.
vectorField pointField
pointField is a vectorField.
const dimensionedScalar e
Elementary charge.
void setSize(const label n)
Alias for resize()
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
errorManip< error > abort(error &err)
int debug
Static debugging option.
List< geometricSurfacePatch > geometricSurfacePatchList
List of geometricSurfacePatch.
defineTypeNameAndDebug(combustionModel, 0)
static const Enum< booleanOpType > booleanOpTypeNames
triSurface()
Default construct.
vector point
Point is a vector.
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
booleanOpType
Enumeration listing the possible volume operator types.
const dimensionedScalar c
Speed of light in a vacuum.
List< label > labelList
A List of labels.
Triangulated surface description with patch information.
void operator=(const triSurface &surf)
Copy assignment.
List< bool > boolList
A List of bools.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
PointHit< point > pointHit
A PointHit with a 3D point.
static constexpr const zero Zero
Global zero (0)