// File: BOP_SolidSolid.cxx // Created: Fri May 25 14:57:05 2001 // Author: Peter KURNEV // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static Standard_Boolean CheckFaceIntersection(const Standard_Integer theFaceIndex, const BOPTools_DSFiller* theDSFiller); static Standard_Boolean BuildWESForCommonZone(const Standard_Integer theFaceIndex, const TColStd_IndexedMapOfInteger& theFFIndicesMap, const BOPTools_DSFiller* theDSFiller, const BOP_Operation& theOperation, BOP_WireEdgeSet& theWES, BOP_WireEdgeSet& theWESAvoid); static void LocalAddPartsEFSo (const Standard_Integer nF1, const Standard_Integer iFF, const TopTools_IndexedDataMapOfShapeListOfShape& aMEFObj, const TopTools_IndexedDataMapOfShapeListOfShape& aMEFTool, const BOPTools_DSFiller* theDSFiller, const BOP_Operation& theOperation, const TopTools_ListOfShape& theListOfSDFace, TopTools_IndexedMapOfShape& anEMap, BOP_WireEdgeSet& aWES); static Standard_Boolean LocalIsKeepTwice(const TopoDS_Face& aF1, const TopoDS_Face& aF2, const TopoDS_Face& aF2Adj, const TopoDS_Edge& aSpEF2, const TopTools_ListOfShape& theFacesToAvoid2, const TopTools_ListOfShape& theFacesToAvoidAdj); //======================================================================= // function: BOP_SolidSolid::BOP_SolidSolid // purpose: //======================================================================= BOP_SolidSolid::BOP_SolidSolid() { } //======================================================================= // function: Destroy // purpose: //======================================================================= void BOP_SolidSolid::Destroy() {} //======================================================================= // function: DoDoWithFiller // purpose: //======================================================================= void BOP_SolidSolid::DoWithFiller(const BOPTools_DSFiller& aDSFiller) { myErrorStatus=0; myIsDone=Standard_False; // myResultMap.Clear(); myModifiedMap.Clear(); // myDSFiller=(BOPTools_DSFiller*) &aDSFiller; // try { OCC_CATCH_SIGNALS // modified by NIZHNY-MKK Fri Sep 3 15:14:17 2004.BEGIN if(!myDSFiller->IsDone()) { myErrorStatus = 1; BOPTColStd_Dump::PrintMessage("DSFiller is invalid: Can not build result\n"); return; } // modified by NIZHNY-MKK Fri Sep 3 15:14:20 2004.END Standard_Boolean bIsNewFiller; bIsNewFiller=aDSFiller.IsNewFiller(); if (bIsNewFiller) { Prepare(); PrepareFaceSplits(); aDSFiller.SetNewFiller(!bIsNewFiller); } // DoNewFaces(); // BuildResult(); // // Treat of internals CollectInternals(); BOP_Refiner aRefiner; aRefiner.SetShape(myResult); aRefiner.SetInternals(myInternals); aRefiner.Do(); // BOP_CorrectTolerances::CorrectTolerances(myResult, 0.01); // FillModified(); if(!myHistory.IsNull()) { Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory); aSolidHistory->SetResult(myResult, myDSFiller); } myIsDone=Standard_True; } catch ( Standard_Failure ) { myErrorStatus = 1; BOPTColStd_Dump::PrintMessage("Can not build result\n"); } } //================================================================================= // function: BuildResult // purpose: //================================================================================= void BOP_SolidSolid::BuildResult() { BOP_ShellFaceSet theSFS(TopoDS::Solid(myShape1)); PrepareSFS(myNewFaces, theSFS); // BOP_SolidBuilder aSOBU; BRep_Builder aBB; TopoDS_Solid aNewSolid; TopoDS_Shell aNewShell; TopTools_ListOfShape aListOfResult; aSOBU.InitSolidBuilder(theSFS, Standard_True); for(aSOBU.InitSolid(); aSOBU.MoreSolid(); aSOBU.NextSolid()) { aBB.MakeSolid(aNewSolid); for(aSOBU.InitShell(); aSOBU.MoreShell(); aSOBU.NextShell()) { if(aSOBU.IsOldShell()) { aNewShell = aSOBU.OldShell(); } else { aBB.MakeShell(aNewShell); for(aSOBU.InitFace(); aSOBU.MoreFace(); aSOBU.NextFace()) { TopoDS_Face aFace = aSOBU.Face(); aBB.Add(aNewShell, aFace); } Standard_Boolean isclosed = Standard_False; TopTools_IndexedDataMapOfShapeListOfShape aMap; TopExp::MapShapesAndAncestors(aNewShell, TopAbs_EDGE, TopAbs_FACE, aMap); Standard_Integer nbedge = aMap.Extent(); for(Standard_Integer eiterator = 1; eiterator <= nbedge; eiterator++) { const TopoDS_Shape& aShape = aMap.FindKey(eiterator); TopAbs_Orientation anOrientation = aShape.Orientation(); if((anOrientation == TopAbs_INTERNAL) || (anOrientation == TopAbs_EXTERNAL) || (BRep_Tool::Degenerated(TopoDS::Edge(aShape)))) continue; Standard_Integer nbface = aMap(eiterator).Extent(); if(nbface < 2) { // (here should be additional condition) isclosed = Standard_False; break; } } aNewShell.Closed(isclosed); } // end else of if(aSOBU.IsOldShell()) aBB.Add(aNewSolid, aNewShell); } aListOfResult.Append(aNewSolid); } TopoDS_Compound aCompound; aBB.MakeCompound(aCompound); TopTools_ListIteratorOfListOfShape aResultIt(aListOfResult); for(; aResultIt.More(); aResultIt.Next()) { aBB.Add(aCompound, aResultIt.Value()); } myResult=aCompound; } //======================================================================= // function: DoNewFaces // purpose: //======================================================================= void BOP_SolidSolid::DoNewFaces() { const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS(); BOPTools_InterferencePool* pIntrPool=(BOPTools_InterferencePool*)&myDSFiller->InterfPool(); BOPTools_CArray1OfSSInterference& aFFs=pIntrPool->SSInterferences(); // // EF Maps const TopoDS_Shape& anObj=aDS.Object(); const TopoDS_Shape& aTool=aDS.Tool(); TopTools_IndexedMapOfShape anEMap; TopTools_IndexedDataMapOfShapeListOfShape aMEFObj, aMEFTool; TopExp::MapShapesAndAncestors (anObj, TopAbs_EDGE , TopAbs_FACE , aMEFObj); TopExp::MapShapesAndAncestors (aTool, TopAbs_EDGE , TopAbs_FACE , aMEFTool); // Standard_Boolean bIsTouchCase, bIsTouch, bToReverseFace; Standard_Integer i, aNb, j, aNbj, iFF, nF1, iRank; TopTools_ListOfShape aListOfNewFaces; TopAbs_Orientation anOriF1; TopTools_ListIteratorOfListOfShape anIt; const TColStd_DataMapOfIntegerListOfInteger& aMapOfFaceSplits = myDSFiller->SplitFacePool(); // // DoMap BOPTColStd_IndexedDataMapOfIntegerIndexedMapOfInteger aFFMap; BOP_BuilderTools::DoMap(aFFs, aFFMap); // aNb=aFFMap.Extent(); for (i=1; i<=aNb; i++) { // // a. Prepare info about the Face nF1 and create WES for nF1 nF1=aFFMap.FindKey(i); const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1)); anOriF1=aF1.Orientation(); iRank=aDS.Rank(nF1); if(aMapOfFaceSplits.IsBound(nF1)) { TopoDS_Face aFace = aF1; TopTools_ListOfShape aLF; const TColStd_ListOfInteger& aListOfSplitIndex = aMapOfFaceSplits.Find(nF1); TColStd_ListIteratorOfListOfInteger aSplIt(aListOfSplitIndex); for(; aSplIt.More(); aSplIt.Next()) { Standard_Integer nFSpl = aSplIt.Value(); Standard_Boolean bAddFace = Standard_False; BooleanOperations_StateOfShape aSt = aDS.GetState(nFSpl); if(aSt != BooleanOperations_ON) { BooleanOperations_StateOfShape aStateComp = BOP_BuilderTools::StateToCompare(iRank, myOperation); if(aStateComp == aSt) { bAddFace = Standard_True; } } else { if(iRank == 1) { bAddFace = TakeOnSplit(nFSpl, nF1); } } if(bAddFace) { const TopoDS_Shape& aFaceSpl = aDS.Shape(nFSpl); aLF.Append(aFaceSpl); } } TopTools_ListOfShape aLFx; anIt.Initialize(aLF); for (; anIt.More(); anIt.Next()) { TopoDS_Shape& aFx=anIt.Value(); aFx.Orientation(anOriF1); bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation); if (bToReverseFace) { aFx.Reverse(); } aListOfNewFaces.Append(aFx); aLFx.Append(aFx); if(!myHistory.IsNull()) { Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory); aSolidHistory->AddNewShape(aFace, aFx, myDSFiller); } } // // Fill "Modified" FillModified(aFace, aLFx); continue; } myFace=aF1; myFace.Orientation(TopAbs_FORWARD); BOP_WireEdgeSet aWES (myFace); const TColStd_IndexedMapOfInteger& aFFIndicesMap=aFFMap.FindFromIndex(i); aNbj=aFFIndicesMap.Extent(); // // b. The Switch: Same Domain Faces or Non-Same Domain Faces bIsTouchCase=Standard_False; for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); BOPTools_SSInterference& aFF=aFFs(iFF); bIsTouchCase=aFF.IsTangentFaces(); if (bIsTouchCase) { break; } } // modified by NIZHNY-MKK Tue Sep 16 11:11:22 2003.BEGIN Standard_Boolean bIsCommonalgo = CheckFaceIntersection(nF1, myDSFiller); BOP_WireEdgeSet atmpWES (myFace); BOP_WireEdgeSet atmpWESAvoid (myFace); if(!bIsCommonalgo) { bIsCommonalgo = !BuildWESForCommonZone(nF1, aFFIndicesMap, myDSFiller, myOperation, atmpWES, atmpWESAvoid); } if(bIsCommonalgo) { // // c. Filling the WES for nF1 if (bIsTouchCase) { // XXXXXXXXXXXXXXXXXXXXXXXXXX // X nF1 has SD face(s) X // XXXXXXXXXXXXXXXXXXXXXXXXXX // // 1. Add Split Parts having states in accordance with operation AddSplitPartsINOUT (nF1, aWES); // // 2. Add Section Edges to the WES for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); BOPTools_SSInterference& aFF=aFFs(iFF); bIsTouch=aFF.IsTangentFaces(); if (!bIsTouch) { AddSectionPartsSo(nF1, iFF, aWES); } } // // 3. Add IN2D, ON2D Parts to the WES for (j=1; j<=aNbj; j++) { iFF = aFFIndicesMap(j); BOPTools_SSInterference& aFF=aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (bIsTouch) { Standard_Integer nF2; nF2 = aFF.OppositeIndex(nF1); AddINON2DPartsSo(iFF, nF1, nF2, aWES); AddPartsEFSDSo(nF1, iFF, aMEFObj, aMEFTool, aWES); AddPartsEESDSo(nF1, iFF, aMEFObj, aMEFTool, aWES); } } // // 4. On3D parts for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); BOPTools_SSInterference& aFF=aFFs(iFF); bIsTouch=aFF.IsTangentFaces(); if (!bIsTouch) { AddSplitPartsON3DSo (nF1, iFF, aWES); } } // 5. Add EF parts (E (from F2) on F1 ), // where F2 is non-same-domain face to F1 anEMap.Clear(); // // anEMap will contain all Split parts that has already in aWES const TopTools_ListOfShape& aLE=aWES.StartElements(); anIt.Initialize (aLE); for (; anIt.More(); anIt.Next()) { TopoDS_Shape& anE=anIt.Value(); anEMap.Add(anE); } // for (j=1; j<=aNbj; j++) { iFF = aFFIndicesMap(j); BOPTools_SSInterference& aFF=aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (!bIsTouch) { AddPartsEFNonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES); AddPartsEENonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES); } } } // end of if (bIsTouchCase) // else { // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // X nF1 does not have SD face(s) X // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // // 1. Add Split Parts having states in accordance with operation AddSplitPartsINOUT (nF1, aWES); // // 2. Add Split Parts with state ON AddSplitPartsONSo (nF1, aMEFObj, aMEFTool, aWES); // // 3. Add Section Edges to the WES for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); AddSectionPartsSo(nF1, iFF, aWES); } // // 4. Add EF parts (E (from F2) on F1 ) anEMap.Clear(); for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); AddPartsEFSo(nF1, iFF, aMEFObj, aMEFTool, anEMap, aWES); } } } // end of if(bIsCommonalgo) else { TopTools_IndexedMapOfOrientedShape aMapOfSDFaceEdges; BOP_WireEdgeSet aSDWES(myFace); if (bIsTouchCase) { // Add IN2D, ON2D Parts to the WES for (j=1; j<=aNbj; j++) { iFF = aFFIndicesMap(j); BOPTools_SSInterference& aFF = aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (bIsTouch) { Standard_Integer nF2 = aFF.OppositeIndex(nF1); AddINON2DPartsSo(iFF, nF1, nF2, aSDWES); AddPartsEFSDSo(nF1, iFF, aMEFObj, aMEFTool, aSDWES); AddPartsEESDSo(nF1, iFF, aMEFObj, aMEFTool, aSDWES); } } // // On3D parts for (j=1; j<=aNbj; j++) { iFF = aFFIndicesMap(j); BOPTools_SSInterference& aFF = aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (!bIsTouch) { AddSplitPartsON3DSo (nF1, iFF, aSDWES); } } TopTools_IndexedMapOfOrientedShape aMapOfWESEdges; for(aSDWES.InitStartElements(); aSDWES.MoreStartElements(); aSDWES.NextStartElement()) { aMapOfWESEdges.Add(aSDWES.StartElement()); } // Build SameDomain faces. // Only edges from aMapOfWESEdges are represented in these faces TopTools_ListOfShape aListOfSDFaces; for (j = 1; j <= aNbj; j++) { iFF = aFFIndicesMap(j); BOPTools_SSInterference& aFF = aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (bIsTouch) { Standard_Integer nF2 = aFF.OppositeIndex(nF1); TopoDS_Face aF1FWD = aF1; aF1FWD.Orientation (TopAbs_FORWARD); BOP_WireEdgeSet aWEScommon (aF1FWD); BOP_SDFWESFiller aWESFiller(nF1, nF2, *myDSFiller); aWESFiller.SetSenseFlag(aFF.SenseFlag()); aWESFiller.SetOperation(BOP_COMMON); aWESFiller.Do(aWEScommon); BOP_FaceBuilder aFB; aFB.Do(aWEScommon); const TopTools_ListOfShape& aLF = aFB.NewFaces(); TopTools_ListIteratorOfListOfShape anItLF(aLF); for (; anItLF.More(); anItLF.Next()) { const TopoDS_Shape& aFR = anItLF.Value(); if (aFR.ShapeType()==TopAbs_FACE) { const TopoDS_Face& aFaceResult=TopoDS::Face(aFR); // Standard_Boolean bIsValidIn2D = Standard_False; Standard_Boolean bNegativeFlag = Standard_False; bIsValidIn2D = BOPTools_Tools3D::IsValidArea (aFaceResult, bNegativeFlag); if (bIsValidIn2D) { // if(CheckSameDomainFaceInside(aFaceResult, aF2)) { Standard_Boolean bfound = Standard_True; TopExp_Explorer anExp(aFaceResult, TopAbs_EDGE); for(; anExp.More(); anExp.Next()) { if(!aMapOfWESEdges.Contains(anExp.Current())) { bfound = Standard_False; break; } } if(bfound) aListOfSDFaces.Append(aFaceResult); // } } } } } } // end for (j = 1; j <= aNbj... TopTools_ListIteratorOfListOfShape anItSD(aListOfSDFaces); for(; anItSD.More(); anItSD.Next()) { const TopoDS_Shape& aShape = anItSD.Value(); TopoDS_Face aFx = TopoDS::Face(aShape); TopExp_Explorer anExp(aFx, TopAbs_EDGE); for(; anExp.More(); anExp.Next()) { aMapOfSDFaceEdges.Add(anExp.Current()); } aFx.Orientation(anOriF1); bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation); if (bToReverseFace) { aFx.Reverse(); } aListOfNewFaces.Append(aFx); } } // Build Common Zone faces, based on intersection lines and // splits with state ON (see BuildWESForCommonZone()). TopTools_ListOfShape aListOfCommonZoneFace; Standard_Integer awesit = 0; for(awesit = 0; awesit < 2; awesit++) { BOP_WireEdgeSet& aCurWEStmp = (awesit == 0) ? atmpWES : atmpWESAvoid; BOP_WireEdgeSet aCurWES(myFace); for(aCurWEStmp.InitStartElements(); aCurWEStmp.MoreStartElements(); aCurWEStmp.NextStartElement()) { if(!aMapOfSDFaceEdges.Contains(aCurWEStmp.StartElement())) { aCurWES.AddStartElement(aCurWEStmp.StartElement()); } } if(!aCurWES.StartElements().IsEmpty()) { BOP_FaceBuilder aFB; aFB.SetTreatment(0); // 0 -Do internal edges, 1 -No Internal Edges aFB.SetTreatSDScales(1); aFB.Do(aCurWES); const TopTools_ListOfShape& aLF = aFB.NewFaces(); anIt.Initialize(aLF); for (; anIt.More(); anIt.Next()) { TopoDS_Shape& aFx=anIt.Value(); aFx.Orientation(anOriF1); if(awesit == 0) { bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation); if (bToReverseFace) { aFx.Reverse(); } aListOfNewFaces.Append(aFx); } aListOfCommonZoneFace.Append(aFx); } } } // end for(awesit = ... // Construct WES to build faces out of common zone BOP_WireEdgeSet aWES2 (myFace); AddSplitPartsINOUT (nF1, aWES2); // if(!bIsTouchCase) { AddSplitPartsONSo (nF1, aMEFObj, aMEFTool, aWES2); } // for (j=1; j<=aNbj; j++) { iFF=aFFIndicesMap(j); AddSectionPartsSo(nF1, iFF, aWES2); } anEMap.Clear(); if(bIsTouchCase) { for(aSDWES.InitStartElements(); aSDWES.MoreStartElements(); aSDWES.NextStartElement()) { aWES2.AddStartElement(aSDWES.StartElement()); } for(aWES2.InitStartElements(); aWES2.MoreStartElements(); aWES2.NextStartElement()) { anEMap.Add(aWES2.StartElement()); } } for (j=1; j<=aNbj; j++) { iFF = aFFIndicesMap(j); if(!bIsTouchCase) { LocalAddPartsEFSo(nF1, iFF, aMEFObj, aMEFTool, myDSFiller, myOperation, aListOfCommonZoneFace, anEMap, aWES2); } else { BOPTools_SSInterference& aFF = aFFs(iFF); bIsTouch = aFF.IsTangentFaces(); if (!bIsTouch) { AddPartsEFNonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES2); AddPartsEENonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES2); } } } aWES.ClearContents(); aWES2.InitStartElements(); for (; aWES2.MoreStartElements(); aWES2.NextStartElement()) { if(aMapOfSDFaceEdges.Contains(aWES2.StartElement())) continue; Standard_Boolean bisequal = Standard_False; Standard_Integer wesit = 0; for(wesit = 0; wesit < 2; wesit++) { BOP_WireEdgeSet& acurwes = (wesit == 0) ? atmpWES : atmpWESAvoid; acurwes.InitStartElements(); for (; !bisequal && acurwes.MoreStartElements(); acurwes.NextStartElement()) { const TopoDS_Shape& anE = acurwes.StartElement(); bisequal = anE.IsEqual(aWES2.StartElement()); } } if(!bisequal) { aWES.AddStartElement(aWES2.StartElement()); } } //end for (; aWES2.MoreStartElements... } // modified by NIZHNY-MKK Tue Sep 16 11:11:33 2003.END // //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Display the WES if (myDraw) { const TopTools_ListOfShape& aWESL=aWES.StartElements(); BOP_Draw::DrawListOfEdgesWithPC (myFace, aWESL, i, "ew_"); BOP_Draw::Wait(); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // d. Build new Faces from myFace BOP_FaceBuilder aFB; aFB.SetTreatment(0); // 0 -Do internal edges, 1 -No Internal Edges aFB.SetTreatSDScales(1); aFB.Do(aWES); const TopTools_ListOfShape& aLF=aFB.NewFaces(); // // e. Do Internal Vertices DoInternalVertices(nF1, aLF); // // f. Orient new faces TopTools_ListOfShape aLFx; anIt.Initialize(aLF); for (; anIt.More(); anIt.Next()) { TopoDS_Shape& aFx=anIt.Value(); aFx.Orientation(anOriF1); bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation); if (bToReverseFace) { aFx.Reverse(); } aListOfNewFaces.Append(aFx); aLFx.Append(aFx); if(!myHistory.IsNull()) { Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory); aSolidHistory->AddNewShape(aF1, aFx, myDSFiller); } } // // Fill "Modified" FillModified(aF1, aLFx); // }// for (i=1; i<=aNb; i++) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Display the new Faces if (myDraw) { BOP_Draw::DrawListOfShape(aListOfNewFaces, "fn_"); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! myNewFaces.Clear(); myNewFaces.Append(aListOfNewFaces); } //================================================================================= // function: PrepareSFS // purpose: //================================================================================= void BOP_SolidSolid::PrepareSFS(const TopTools_ListOfShape& theNewFaces, BOP_ShellFaceSet& theSFS) { const BooleanOperations_ShapesDataStructure& theDS=myDSFiller->DS(); Standard_Integer iRank, lastindex, firstindex, i, a; BooleanOperations_StateOfShape aChoosenState; for(iRank = 1; iRank <= 2; iRank++) { aChoosenState = BOP_BuilderTools::StateToCompare(iRank, myOperation); // const TopoDS_Shape& aSolid = (iRank==1) ? myShape1 : myShape2; firstindex=1; lastindex=theDS.NumberOfShapesOfTheObject(); if (iRank==2) { firstindex=lastindex+1; lastindex=theDS.NumberOfSourceShapes(); } for(i = firstindex; i <= lastindex; i++) { if((theDS.GetShapeType(i) != TopAbs_FACE) || (theDS.GetState(i) != aChoosenState)) continue; // compute orientation TopoDS_Shape aFace=theDS.Shape(i); TopAbs_Orientation anOri = TopAbs_FORWARD; for(a = 1; a <= theDS.NumberOfAncestors(i); a++) { const TopoDS_Shape& aShell = theDS.GetShape(theDS.GetAncestor(i, a)); TopAbs_Orientation anAncestorOrientation = aShell.Orientation(); Standard_Boolean found = Standard_False; TopExp_Explorer aSolidExp(aSolid, TopAbs_SHELL); for(; !found && aSolidExp.More(); aSolidExp.Next()) { if(aShell.IsSame(aSolidExp.Current())) { anAncestorOrientation = aSolidExp.Current().Orientation(); found = Standard_True; } } if(!found) { // raise the exception: programming error BOPTColStd_Dump::PrintMessage ("BOP_SolidSolid::PrepareSFS(). Raises the exception: programming error...\n"); continue; } TopoDS_Shape anOrientedShell = aShell; anOrientedShell.Orientation(anAncestorOrientation); TopExp_Explorer aShellExp(anOrientedShell, TopAbs_FACE); for(; aShellExp.More(); aShellExp.Next()) { if(!aFace.IsSame(aShellExp.Current())) continue; anOri = aShellExp.Current().Orientation(); if(BOP_BuilderTools::ToReverseFace(iRank, myOperation)) { anOri = TopAbs::Complement(anOri); } aFace.Orientation(anOri); theSFS.AddStartElement(aFace); } // end shell explorer } } // end source shapes explorer } TopTools_ListIteratorOfListOfShape anIt(theNewFaces); for(;anIt.More(); anIt.Next()) { theSFS.AddStartElement(anIt.Value()); } } // -------------------------------------------------------------------------------------------------------- // static function: CheckFaceIntersection // purpose: Returns Standard_True if there are no any common zone for given face, // Returns Standard_False if there are common zones or probability of existance of the common zone // is high. // -------------------------------------------------------------------------------------------------------- Standard_Boolean CheckFaceIntersection(const Standard_Integer theFaceIndex, const BOPTools_DSFiller* theDSFiller) { const BooleanOperations_ShapesDataStructure& aDS = theDSFiller->DS(); const BOPTools_PaveFiller& aPaveFiller = theDSFiller->PaveFiller(); BOPTools_PaveFiller* pPaveFiller = (BOPTools_PaveFiller*)&aPaveFiller; BOPTools_CommonBlockPool& aCBPool = pPaveFiller->ChangeCommonBlockPool(); // const BOPTools_SplitShapesPool& aSplitShapesPool = aPaveFiller.SplitShapesPool(); BOPTools_InterferencePool* pIntrPool= (BOPTools_InterferencePool*)&theDSFiller->InterfPool(); BOPTools_CArray1OfSSInterference& aFFs = pIntrPool->SSInterferences(); Standard_Integer i = 0; for(i = 1; i <= aFFs.Length(); i++) { BOPTools_SSInterference& aFF = aFFs(i); if((aFF.Index1() != theFaceIndex) && (aFF.Index2() != theFaceIndex)) continue; Standard_Integer otherindex = aFF.OppositeIndex(theFaceIndex); BOPTools_SequenceOfCurves& aSC = aFF.Curves(); Standard_Integer aNbCurves = aSC.Length(); if(aNbCurves > 0) { TopoDS_Shape aF1 = aDS.Shape(theFaceIndex); TopoDS_Shape aF2 = aDS.Shape(otherindex); TopExp_Explorer anExp; for(Standard_Integer j = 0; j < 2; j++) { Standard_Integer afaceindextocompare = (j == 0) ? otherindex : theFaceIndex; Standard_Integer aFaceRank = 1; if(j == 0) { anExp.Init(aF1, TopAbs_EDGE); aFaceRank = aDS.Rank(theFaceIndex); } else { anExp.Init(aF2, TopAbs_EDGE); aFaceRank = aDS.Rank(otherindex); } for(; anExp.More(); anExp.Next()) { const TopoDS_Edge& aEF = TopoDS::Edge(anExp.Current()); Standard_Integer nEF = aDS.ShapeIndex(aEF, aFaceRank); BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(nEF)); BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB); for (; anItCB.More(); anItCB.Next()) { BOPTools_CommonBlock& aCB=anItCB.Value(); Standard_Integer nFace = aCB.Face(); if(nFace == afaceindextocompare) return Standard_False; } } } } } return Standard_True; } // ---------------------------------------------------------------------------------------------------------------- // static function: BuildWESForCommonZone // purpose: Finds common zones which contains boundaries represented by new geometry // Fills theWES if zones could be included in result, // Fills theWESAvoid if zones could not be included in result. // Returns true if common zones are found, otherwise returns false. // ---------------------------------------------------------------------------------------------------------------- Standard_Boolean BuildWESForCommonZone(const Standard_Integer theFaceIndex, const TColStd_IndexedMapOfInteger& theFFIndicesMap, const BOPTools_DSFiller* theDSFiller, const BOP_Operation& theOperation, BOP_WireEdgeSet& theWES, BOP_WireEdgeSet& theWESAvoid) { const BooleanOperations_ShapesDataStructure& aDS = theDSFiller->DS(); // const BOPTools_PaveFiller& aPaveFiller = theDSFiller->PaveFiller(); // BOPTools_PaveFiller* pPaveFiller = (BOPTools_PaveFiller*)&aPaveFiller; // BOPTools_CommonBlockPool& aCBPool = pPaveFiller->ChangeCommonBlockPool(); // const BOPTools_SplitShapesPool& aSplitShapesPool = aPaveFiller.SplitShapesPool(); BOPTools_InterferencePool* pIntrPool= (BOPTools_InterferencePool*)&theDSFiller->InterfPool(); BOPTools_CArray1OfSSInterference& aFFs = pIntrPool->SSInterferences(); TopoDS_Face aFace = TopoDS::Face(aDS.Shape(theFaceIndex)); TopoDS_Face myFace = aFace; myFace.Orientation(TopAbs_FORWARD); // Standard_Integer iFaceRank = aDS.Rank(theFaceIndex); TopTools_IndexedDataMapOfShapeListOfShape aMapFCommonZones, aMapFCommonZones2; Standard_Integer j = 0, k = 0; for (j = 1; j <= theFFIndicesMap.Extent(); j++) { BOP_WireEdgeSet atmpWES(myFace); Standard_Integer iFF= theFFIndicesMap(j); BOPTools_SSInterference& aFF = aFFs(iFF); Standard_Integer aFaceIndex2 = aFF.OppositeIndex(theFaceIndex); TopoDS_Face aFace2 = TopoDS::Face(aDS.Shape(aFaceIndex2)); // Standard_Integer iFaceRank2 = aDS.Rank(aFaceIndex2); BOPTools_SequenceOfCurves& aSC = aFF.Curves(); Standard_Integer aNbCurves = aSC.Length(); Standard_Integer i = 0; for (i = 1; i <= aNbCurves; i++) { const BOPTools_Curve& aBC = aSC(i); const BOPTools_ListOfPaveBlock& aLPB = aBC.NewPaveBlocks(); BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB); for (; anIt.More(); anIt.Next()) { const BOPTools_PaveBlock& aPB=anIt.Value(); Standard_Integer nE = aPB.Edge(); const TopoDS_Edge& aE = TopoDS::Edge(aDS.Shape(nE)); TopoDS_Edge aES=aE; atmpWES.AddStartElement(aES); aES.Reverse(); atmpWES.AddStartElement(aES); } } BOP_SDFWESFiller aWESFiller(theFaceIndex, aFaceIndex2, *theDSFiller); Standard_Integer iSenseFlag = 0; Standard_Integer iRankF1 = aDS.Rank(theFaceIndex); // compute iSenseFlag. begin gp_Dir aDNF1, aDNF2; const BOPTools_ListOfPaveBlock& aLPB = aFF.PaveBlocks(); if (aLPB.IsEmpty()) { continue; } const BOPTools_PaveBlock& aPB = aLPB.First(); const TopoDS_Edge& aSpE = TopoDS::Edge(aDS.Shape(aPB.Edge())); BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpE, aFace, aDNF1); BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpE, aFace2, aDNF2); Standard_Real aScPr = aDNF1*aDNF2; if (aScPr<0.) { iSenseFlag = -1; } else if (aScPr>0.) { iSenseFlag = 1; } // compute iSenseFlag. end aWESFiller.SetSenseFlag(iSenseFlag); aWESFiller.SetOperation(BOP_COMMON); aWESFiller.Do(atmpWES); BOP_FaceBuilder aFB; aFB.Do(atmpWES); const TopTools_ListOfShape& aLF = aFB.NewFaces(); if(aLF.IsEmpty()) { continue; } TopTools_ListIteratorOfListOfShape anIt(aLF); for(; anIt.More(); anIt.Next()) { const TopoDS_Face& aCurFace = TopoDS::Face(anIt.Value()); // check common zone.begin Standard_Boolean IsSameDomain = Standard_True; Standard_Boolean bIsValidIn2D = Standard_False, bNegativeFlag = Standard_False; bIsValidIn2D = BOPTools_Tools3D::IsValidArea (aCurFace, bNegativeFlag); if(bIsValidIn2D) { Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aCurFace); Standard_Real aTolerance = BRep_Tool::Tolerance(aFace) + BRep_Tool::Tolerance(aFace2); IntTools_Context aContext; Standard_Real umin, umax, vmin, vmax; BRepTools::UVBounds(aCurFace, umin, umax, vmin, vmax); Standard_Real deltau = (umax - umin) * 0.1; Standard_Real deltav = (vmax - vmin) * 0.1; for(Standard_Integer uit = 1; IsSameDomain && (uit < 9); uit++) { Standard_Real U = umin + uit * deltau; for(Standard_Integer vit = 1; vit < 9; vit++) { Standard_Real V = vmin + vit * deltav; if(aContext.IsPointInOnFace(aCurFace, gp_Pnt2d(U, V))) { gp_Pnt aCurPoint = aSurface->Value(U, V); if(!aContext.IsValidPointForFace(aCurPoint, aFace2, aTolerance)) { IsSameDomain = Standard_False; break; } } } } } // check common zone.end if(IsSameDomain) { Standard_Integer addcommonzone = Standard_False; if (iSenseFlag==1) { switch (theOperation) { case BOP_FUSE: if (iRankF1==1) { addcommonzone = Standard_True; } break; case BOP_COMMON: if (iRankF1==1) { addcommonzone = Standard_True; } break; case BOP_CUT: case BOP_CUT21: break; default: break; } } else if (iSenseFlag==-1) { // iSenseFlag<0 switch (theOperation) { case BOP_FUSE: case BOP_COMMON: break; case BOP_CUT: if (iRankF1==1) { addcommonzone = Standard_True; } break; case BOP_CUT21: if (iRankF1==2) { addcommonzone = Standard_True; } default: break; } } TopTools_ListOfShape thelist; if(addcommonzone) { if(!aMapFCommonZones.Contains(aFace2)) aMapFCommonZones.Add(aFace2, thelist); aMapFCommonZones.ChangeFromKey(aFace2).Append(aCurFace); } else { if(!aMapFCommonZones2.Contains(aFace2)) aMapFCommonZones2.Add(aFace2, thelist); aMapFCommonZones2.ChangeFromKey(aFace2).Append(aCurFace); } } } } if(aMapFCommonZones.IsEmpty() && aMapFCommonZones2.IsEmpty()) { return Standard_False; } Standard_Integer amapit = 0; for(amapit = 0; amapit < 2; amapit++) { const TopTools_IndexedDataMapOfShapeListOfShape& aMap = (amapit == 0) ? aMapFCommonZones : aMapFCommonZones2; BOP_WireEdgeSet& aWES = (amapit == 0) ? theWES : theWESAvoid; for(k = 1; k <= aMap.Extent(); k++) { const TopTools_ListOfShape& alf = aMap(k); TopTools_ListIteratorOfListOfShape anIt(alf); for(; anIt.More(); anIt.Next()) { TopExp_Explorer anExp(anIt.Value(), TopAbs_EDGE); for(; anExp.More(); anExp.Next()) { aWES.AddStartElement(anExp.Current()); } } } } //end for(amapit = ... return Standard_True; } // ---------------------------------------------------------------------------------------------------------------- // static function: LocalAddPartsEFSo // purpose: Adds split parts of edges, which lay on face nF1, to theWES. // It uses found common zones (theListOfSDFace) to check // if a split part should be represented in theWES twice or not. // ---------------------------------------------------------------------------------------------------------------- void LocalAddPartsEFSo (const Standard_Integer nF1, const Standard_Integer iFF, const TopTools_IndexedDataMapOfShapeListOfShape& theMEFObj, const TopTools_IndexedDataMapOfShapeListOfShape& theMEFTool, const BOPTools_DSFiller* theDSFiller, const BOP_Operation& theOperation, const TopTools_ListOfShape& theListOfSDFace, TopTools_IndexedMapOfShape& theEMap, BOP_WireEdgeSet& theWES) { const BooleanOperations_ShapesDataStructure& aDS = theDSFiller->DS(); BOPTools_InterferencePool* pIntrPool=(BOPTools_InterferencePool*)&theDSFiller->InterfPool(); BOPTools_CArray1OfSSInterference& aFFs=pIntrPool->SSInterferences(); const BOPTools_PaveFiller& aPF = theDSFiller->PaveFiller(); BOPTools_PaveFiller* pPaveFiller =(BOPTools_PaveFiller*)&aPF; BOPTools_CommonBlockPool& aCBPool = pPaveFiller->ChangeCommonBlockPool(); BOPTools_SSInterference& aFF=aFFs(iFF); Standard_Integer nF2 = aFF.OppositeIndex(nF1); const TopoDS_Face& aFace =TopoDS::Face(aDS.Shape(nF1)); const TopoDS_Face& aFace2 =TopoDS::Face(aDS.Shape(nF2)); Standard_Integer anindextocompare = nF1; Standard_Integer iFaceRank1, iFaceRank2; iFaceRank1 = aDS.Rank(nF1); iFaceRank2 = aDS.Rank(nF2); Standard_Integer aFaceRank = iFaceRank2; const TopTools_IndexedDataMapOfShapeListOfShape& aMEF = (aFaceRank == 1) ? theMEFObj : theMEFTool; TopExp_Explorer anExp(aFace2, TopAbs_EDGE); for(; anExp.More(); anExp.Next()) { const TopoDS_Edge& aEF = TopoDS::Edge(anExp.Current()); Standard_Integer nEF = aDS.ShapeIndex(aEF, aFaceRank); BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(nEF)); BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB); for (; anItCB.More(); anItCB.Next()) { BOPTools_CommonBlock& aCB=anItCB.Value(); Standard_Integer nFace = aCB.Face(); if (nFace == anindextocompare) { BOPTools_PaveBlock& aPB = aCB.PaveBlock1(nEF); Standard_Integer nSplit = aPB.Edge(); const TopoDS_Shape& aSplit = aDS.Shape(nSplit); if (theEMap.Contains(aSplit)) { continue;// next CB } theEMap.Add(aSplit); TopoDS_Edge aSS = TopoDS::Edge(aSplit); // TopoDS_Face aFAdj; Standard_Boolean bIsAdjExists = Standard_False; bIsAdjExists = BOPTools_Tools3D::GetAdjacentFace(aFace2, aEF, aMEF, aFAdj); Standard_Boolean bIsKeepTwice = Standard_False; if(bIsAdjExists) { bIsKeepTwice = LocalIsKeepTwice(aFace, aFace2, aFAdj, aSS, theListOfSDFace, theListOfSDFace); } else { bIsKeepTwice = BOPTools_Tools3D::IsTouchCase(aSS, aFace, aFace2); } if(bIsKeepTwice) { theWES.AddStartElement(aSS); aSS.Reverse(); theWES.AddStartElement(aSS); } else { aSS.Orientation(TopAbs_FORWARD); TopoDS_Face myFace = aFace; myFace.Orientation(TopAbs_FORWARD); BOP_BuilderTools::OrientSectionEdgeOnF1 (myFace, aFace2, iFaceRank1, theOperation, aSS); theWES.AddStartElement(aSS); } } } } } // -------------------------------------------------------------------------------------------------------- // static function: LocalIsKeepTwice // purpose: // -------------------------------------------------------------------------------------------------------- Standard_Boolean LocalIsKeepTwice(const TopoDS_Face& aF1, const TopoDS_Face& aF2, const TopoDS_Face& aF2Adj, const TopoDS_Edge& aSpEF2, const TopTools_ListOfShape& theFacesToAvoid2, const TopTools_ListOfShape& theFacesToAvoidAdj) { Standard_Real aT1, aT2, aT, dt=1.e-7, A, B, C, D, d2, d2Adj; gp_Dir aDNF1, aDNF2, DBF2, aDNF2Adj, DBF2Adj; gp_Vec aD1Sp; gp_Pnt aP, aPF2, aPF2Adj; Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aSpEF2, aT1, aT2); aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2); BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF1, aT, aDNF1); // aC3D->D1(aT, aP, aD1Sp); gp_Dir aDD1Sp(aD1Sp); if (aSpEF2.Orientation()==TopAbs_REVERSED) { aDD1Sp.Reverse(); } // Split Normal on F2 BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2, aT, aDNF2); if (aF2.Orientation()==TopAbs_REVERSED) { aDNF2.Reverse(); } // Binormal on F2 DBF2=aDNF2^aDD1Sp; TopTools_ListIteratorOfListOfShape anIt; IntTools_Context aContext; Standard_Boolean dtfound = Standard_False; Standard_Real acurdt = dt; while(!dtfound) { dtfound = Standard_True; aPF2.SetCoord(aP.X() + acurdt*DBF2.X(), aP.Y() + acurdt*DBF2.Y(), aP.Z() + acurdt*DBF2.Z()); for(anIt.Initialize(theFacesToAvoid2); anIt.More(); anIt.Next()) { const TopoDS_Face& aFace = TopoDS::Face(anIt.Value()); if(aContext.IsValidPointForFace(aPF2, aFace, BRep_Tool::Tolerance(aFace))) { dtfound = Standard_False; break; } } if(!aContext.IsValidPointForFace(aPF2, aF2, BRep_Tool::Tolerance(aF2))) { acurdt = dt; break; } acurdt *= 2.; } if(!dtfound) { dt = 1.e-07; // Point near aP aPF2.SetCoord(aP.X()+dt*DBF2.X(), aP.Y()+dt*DBF2.Y(), aP.Z()+dt*DBF2.Z()); } // aDD1Sp.Reverse(); // Split Normal on F2Adj BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2Adj, aT, aDNF2Adj); if (aF2Adj.Orientation()==TopAbs_REVERSED) { aDNF2Adj.Reverse(); } // Binormal on F2Adj DBF2Adj=aDNF2Adj^aDD1Sp; dt = 1.e-07; acurdt = dt; dtfound = Standard_False; while(!dtfound) { dtfound = Standard_True; aPF2Adj.SetCoord(aP.X() + acurdt*DBF2Adj.X(), aP.Y() + acurdt*DBF2Adj.Y(), aP.Z() + acurdt*DBF2Adj.Z()); for(anIt.Initialize(theFacesToAvoidAdj); anIt.More(); anIt.Next()) { const TopoDS_Face& aFace = TopoDS::Face(anIt.Value()); if(aContext.IsValidPointForFace(aPF2Adj, aFace, BRep_Tool::Tolerance(aFace))) { dtfound = Standard_False; break; } } if(!aContext.IsValidPointForFace(aPF2Adj, aF2Adj, BRep_Tool::Tolerance(aF2Adj))) { acurdt = dt; break; } acurdt *= 2.; } if(!dtfound) { dt = 1.e-07; aPF2Adj.SetCoord(aP.X()+dt*DBF2Adj.X(), aP.Y()+dt*DBF2Adj.Y(), aP.Z()+dt*DBF2Adj.Z()); } // // Tangent Plane on F1 gp_Pln aPlnN1(aP, aDNF1); aPlnN1.Coefficients(A, B, C, D); // d2 = A*aPF2.X() + B*aPF2.Y() + C*aPF2.Z() + D; d2Adj= A*aPF2Adj.X() + B*aPF2Adj.Y()+ C*aPF2Adj.Z() + D; // if (fabs(d2)<1.e-10) { d2=0.; } if (fabs(d2Adj)<1.e-10) { d2Adj=0.; } // aT=d2*d2Adj; // return (aT >= 0.); } //================================================================================= // function: SetHistoryCollector // purpose: //================================================================================= void BOP_SolidSolid::SetHistoryCollector(const Handle(BOP_HistoryCollector)& theHistory) { if(theHistory.IsNull() || !theHistory->IsKind(STANDARD_TYPE(BOP_SolidSolidHistoryCollector))) myHistory.Nullify(); else myHistory = theHistory; }