// File: BOPTools_DEProcessor.cxx // Created: Wed Sep 12 12:10:52 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 //======================================================================= // function: BOPTools_DEProcessor::BOPTools_DEProcessor // purpose: //======================================================================= BOPTools_DEProcessor::BOPTools_DEProcessor(const BOPTools_PaveFiller& aFiller, const Standard_Integer aDim) : myIsDone(Standard_False) { myFiller=(BOPTools_PaveFiller*) &aFiller; myDS=myFiller->DS(); myDim=aDim; if (aDim<2 || aDim>3) { myDim=3; } } //======================================================================= // function: IsDone // purpose: //======================================================================= Standard_Boolean BOPTools_DEProcessor::IsDone() const { return myIsDone; } //======================================================================= // function: Do // purpose: //======================================================================= void BOPTools_DEProcessor::Do() { Standard_Integer aNbE; myIsDone=Standard_False; FindDegeneratedEdges(); aNbE=myDEMap.Extent(); if (!aNbE) { myIsDone=Standard_True; return; } DoPaves(); } //======================================================================= // function: FindDegeneratedEdges // purpose: //======================================================================= void BOPTools_DEProcessor::FindDegeneratedEdges() { const BooleanOperations_ShapesDataStructure& aDS=*myDS; const BOPTools_PaveFiller& aPaveFiller=*myFiller; Standard_Integer i, aNbSourceShapes, nV, nF, nVx, ip, iRankE; TopAbs_ShapeEnum aType; const TopoDS_Shape& anObj=aDS.Object(); const TopoDS_Shape& aTool=aDS.Tool(); TopTools_IndexedDataMapOfShapeListOfShape aMEF; TopExp::MapShapesAndAncestors (anObj, TopAbs_EDGE, TopAbs_FACE, aMEF); TopExp::MapShapesAndAncestors (aTool, TopAbs_EDGE, TopAbs_FACE, aMEF); aNbSourceShapes=aDS.NumberOfSourceShapes(); for (i=1; i<=aNbSourceShapes; i++) { const TopoDS_Shape& aS=aDS.Shape(i); aType=aS.ShapeType(); if (aType==TopAbs_EDGE) { const TopoDS_Edge& aE=TopoDS::Edge(aS); if (BRep_Tool::Degenerated(aE)) { iRankE=aDS.Rank(i); TopoDS_Vertex aV=TopExp::FirstVertex(aE); nVx=aDS.ShapeIndex(aV, iRankE); // nV=nVx; ip=aPaveFiller.FindSDVertex(nV); if (ip) { nV=ip; } // TColStd_ListOfInteger aLFn; const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE); TopTools_ListIteratorOfListOfShape anIt(aLF); for (; anIt.More(); anIt.Next()) { const TopoDS_Shape& aF=anIt.Value(); nF=aDS.ShapeIndex(aF, iRankE); aLFn.Append(nF); } BOPTools_DEInfo aDEInfo; aDEInfo.SetVertex(nV); aDEInfo.SetFaces(aLFn); myDEMap.Add (i, aDEInfo); } } } } //======================================================================= // function: DoPaves // purpose: //======================================================================= void BOPTools_DEProcessor::DoPaves() { Standard_Integer i, aNbE, nED, nVD, nFD=0; aNbE=myDEMap.Extent(); for (i=1; i<=aNbE; i++) { nED=myDEMap.FindKey(i); const BOPTools_DEInfo& aDEInfo=myDEMap(i); nVD=aDEInfo.Vertex(); // Fill PaveSet for the edge nED const TColStd_ListOfInteger& nLF=aDEInfo.Faces(); TColStd_ListIteratorOfListOfInteger anIt(nLF); for (; anIt.More(); anIt.Next()) { nFD=anIt.Value(); BOPTools_ListOfPaveBlock aLPB; FindPaveBlocks(nED, nVD, nFD, aLPB); FillPaveSet (nED, nVD, nFD, aLPB); } // // Fill aSplitEdges for the edge nED FillSplitEdgesPool(nED); // // MakeSplitEdges MakeSplitEdges(nED, nFD); // // Compute States for Split parts if (myDim==3) { DoStates(nED, nFD); } if (myDim==2) { DoStates2D(nED, nFD); } }// next nED } //======================================================================= // function: DoStates // purpose: //======================================================================= void BOPTools_DEProcessor::DoStates (const Standard_Integer nED, const Standard_Integer nFD) { const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool(); const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED)); const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED)); const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD)); Standard_Integer nSp, iRank; Standard_Real aT, aT1, aT2, aTol=1e-7; TopoDS_Face aF; gp_Pnt2d aPx2DNear; gp_Pnt aPxNear; iRank=myDS->Rank(nED); const TopoDS_Shape& aReference=(iRank==1) ? myDS->Tool() : myDS->Object(); BRepExtrema_DistShapeShape aDSS; aDSS.LoadS1(aReference); aF=aDF; aF.Orientation(TopAbs_FORWARD); BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges); for (; aPBIt.More(); aPBIt.Next()) { BOPTools_PaveBlock& aPB=aPBIt.Value(); nSp=aPB.Edge(); const TopoDS_Edge& aSp=TopoDS::Edge(myDS->Shape(nSp)); aPB.Parameters(aT1, aT2); aT=IntTools_Tools::IntermediatePoint(aT1, aT2); TopoDS_Edge aDERight, aSpRight; aDERight=aDE; aSpRight=aSp; BOPTools_Tools3D::OrientEdgeOnFace (aDE, aF, aDERight); aSpRight.Orientation(aDERight.Orientation()); // { BRepAdaptor_Surface aBAS; aBAS.Initialize (aDF, Standard_False); if (aBAS.GetType()==GeomAbs_Sphere) { Standard_Real aDt2D, aR, aDelta=1.e-14; gp_Sphere aSphere=aBAS.Sphere(); aR=aSphere.Radius(); // aDt2D=acos (1.-4.*aTol/aR)+aDelta ; // BOPTools_Tools3D::PointNearEdge(aSpRight, aF, aT, aDt2D, aPx2DNear, aPxNear); } else { BOPTools_Tools3D::PointNearEdge(aSpRight, aF, aT, aPx2DNear, aPxNear); } } // TopAbs_State aState; // TopAbs_ShapeEnum aTypeReference; aTypeReference=aReference.ShapeType(); if (aTypeReference==TopAbs_SOLID) { // ... \ Solid processing IntTools_Context& aContext=myFiller->ChangeContext(); const TopoDS_Solid& aReferenceSolid=TopoDS::Solid(aReference); BRepClass3d_SolidClassifier& SC=aContext.SolidClassifier(aReferenceSolid); // SC.Perform(aPxNear, aTol); // aState=SC.State(); } // else if (aTypeReference==TopAbs_SHELL || aTypeReference==TopAbs_FACE) { // ... \ Shell processing TopoDS_Vertex aVxNear; BRep_Builder BB; BB.MakeVertex(aVxNear, aPxNear, aTol); aDSS.LoadS2(aVxNear); aDSS.Perform(); aState=TopAbs_OUT; if (aDSS.IsDone()) { Standard_Real aDist=aDSS.Value(); if (aDist < aTol) { aState=TopAbs_ON; } } } else { // unknown aTypeReference aState=TopAbs_OUT; } // BooleanOperations_StateOfShape aSt; aSt=BOPTools_StateFiller::ConvertState(aState); myDS->SetState(nSp, aSt); } } //======================================================================= // function: DoStates2D // purpose: //======================================================================= void BOPTools_DEProcessor::DoStates2D (const Standard_Integer nED, const Standard_Integer nFD) { const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool(); const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED)); const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED)); const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD)); Standard_Integer nSp, iRank; Standard_Real aT, aT1, aT2; TopoDS_Face aF; gp_Pnt2d aPx2DNear; gp_Pnt aPxNear; iRank=myDS->Rank(nED); const TopoDS_Shape& aReference=(iRank==1) ? myDS->Tool() : myDS->Object(); const TopoDS_Face& aFaceReference=TopoDS::Face(aReference); aF=aDF; aF.Orientation(TopAbs_FORWARD); BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges); for (; aPBIt.More(); aPBIt.Next()) { BOPTools_PaveBlock& aPB=aPBIt.Value(); nSp=aPB.Edge(); const TopoDS_Edge& aSp=TopoDS::Edge(myDS->Shape(nSp)); aPB.Parameters(aT1, aT2); aT=IntTools_Tools::IntermediatePoint(aT1, aT2); TopoDS_Edge aDERight, aSpRight; aDERight=aDE; aSpRight=aSp; BOPTools_Tools3D::OrientEdgeOnFace (aDE, aF, aDERight); aSpRight.Orientation(aDERight.Orientation()); // BOPTools_Tools3D::PointNearEdge(aSpRight, aDF, aT, aPx2DNear, aPxNear); // Standard_Boolean bIsValidPoint; TopAbs_State aState=TopAbs_OUT; // IntTools_Context& aContext=myFiller->ChangeContext(); bIsValidPoint=aContext.IsValidPointForFace(aPxNear, aFaceReference, 1.e-3); // if (bIsValidPoint) { aState=TopAbs_IN; } // BooleanOperations_StateOfShape aSt; aSt=BOPTools_StateFiller::ConvertState(aState); myDS->SetState(nSp, aSt); } } //======================================================================= // function: FillSplitEdgesPool // purpose: //======================================================================= void BOPTools_DEProcessor::FillSplitEdgesPool (const Standard_Integer nED) { BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->ChangeSplitShapesPool(); // BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool.ChangeValue(myDS->RefEdge(nED)); // aSplitEdges.Clear(); // const BOPTools_PavePool& aPavePool=myFiller->PavePool(); BOPTools_PavePool* pPavePool=(BOPTools_PavePool*) &aPavePool; BOPTools_PaveSet& aPaveSet= pPavePool->ChangeValue(myDS->RefEdge(nED)); BOPTools_PaveBlockIterator aPBIt(nED, aPaveSet); for (; aPBIt.More(); aPBIt.Next()) { BOPTools_PaveBlock& aPB=aPBIt.Value(); aSplitEdges.Append(aPB); } } //======================================================================= // function: MakeSplitEdges // purpose: //======================================================================= void BOPTools_DEProcessor::MakeSplitEdges (const Standard_Integer nED, const Standard_Integer nFD) { const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool(); const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED)); Standard_Integer nV1, nV2, aNewShapeIndex; Standard_Real t1, t2; TopoDS_Edge aE, aESplit; TopoDS_Vertex aV1, aV2; const TopoDS_Edge aDE=TopoDS::Edge(myDS->Shape(nED)); const TopoDS_Face aDF=TopoDS::Face(myDS->Shape(nFD)); BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges); for (; aPBIt.More(); aPBIt.Next()) { BOPTools_PaveBlock& aPB=aPBIt.Value(); const BOPTools_Pave& aPave1=aPB.Pave1(); nV1=aPave1.Index(); t1=aPave1.Param(); aV1=TopoDS::Vertex(myDS->GetShape(nV1)); aV1.Orientation(TopAbs_FORWARD); const BOPTools_Pave& aPave2=aPB.Pave2(); nV2=aPave2.Index(); t2=aPave2.Param(); aV2=TopoDS::Vertex(myDS->GetShape(nV2)); aV2.Orientation(TopAbs_REVERSED); MakeSplitEdge(aDE, aDF, aV1, t1, aV2, t2, aESplit); // // Add Split Part of the Original Edge to the DS BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq; anASSeq.SetNewSuccessor(nV1); anASSeq.SetNewOrientation(aV1.Orientation()); anASSeq.SetNewSuccessor(nV2); anASSeq.SetNewOrientation(aV2.Orientation()); myDS->InsertShapeAndAncestorsSuccessors(aESplit, anASSeq); aNewShapeIndex=myDS->NumberOfInsertedShapes(); myDS->SetState(aNewShapeIndex, BooleanOperations_UNKNOWN); // // Fill Split Set for the Original Edge aPB.SetEdge(aNewShapeIndex); // } } //======================================================================= // function: MakeSplitEdge // purpose: //======================================================================= void BOPTools_DEProcessor::MakeSplitEdge (const TopoDS_Edge& aE, const TopoDS_Face& aF, const TopoDS_Vertex& aV1, const Standard_Real aP1, const TopoDS_Vertex& aV2, const Standard_Real aP2, TopoDS_Edge& aNewEdge) { Standard_Real aTol=1.e-7; TopoDS_Edge E=aE; E.EmptyCopy(); BRep_Builder BB; BB.Add (E, aV1); BB.Add (E, aV2); BB.Range(E, aF, aP1, aP2); BB.Degenerated(E, Standard_True); BB.UpdateEdge(E, aTol); aNewEdge=E; } //======================================================================= // function: FillPaveSet // purpose: //======================================================================= void BOPTools_DEProcessor::FillPaveSet (const Standard_Integer nED, const Standard_Integer nVD, const Standard_Integer nFD, BOPTools_ListOfPaveBlock& aLPB) { Standard_Boolean bIsDone, bXDir; Standard_Integer nE, aNbPoints, j; Standard_Real aTD1, aTD2, aT1, aT2, aTolInter, aX, aDT; // aDT=Precision::PConfusion(); // BOPTools_PaveSet& aPaveSet= (myFiller->ChangePavePool()).ChangeValue(myDS->RefEdge(nED)); // // Clear aPaveSet, aSplitEdges aPaveSet.ChangeSet().Clear(); // const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED)); const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD)); // // 2D Curve of degenerated edge on the face aDF Handle(Geom2d_Curve) aC2DDE=BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2); // // Choose direction for Degenerated Edge gp_Pnt2d aP2d1, aP2d2; aC2DDE->D0(aTD1, aP2d1); aC2DDE->D0(aTD2, aP2d2); bXDir=Standard_False; if (fabs(aP2d1.Y()-aP2d2.Y()) < aDT){ bXDir=!bXDir; } // // Prepare bounding Paves BOPTools_Pave aPave1 (nVD, aTD1, BooleanOperations_UnknownInterference); aPaveSet.Append(aPave1); BOPTools_Pave aPave2 (nVD, aTD2, BooleanOperations_UnknownInterference); aPaveSet.Append(aPave2); // // Fill other paves BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB); for (; anIt.More(); anIt.Next()) { const BOPTools_PaveBlock& aPB=anIt.Value(); nE=aPB.Edge(); const TopoDS_Edge& aE=TopoDS::Edge(myDS->Shape(nE)); Handle(Geom2d_Curve) aC2D=BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2); // // Intersection aTolInter=0.001; Geom2dAdaptor_Curve aGAC1, aGAC2; aGAC1.Load(aC2DDE, aTD1, aTD2); Handle(Geom2d_Line) aL2D= Handle(Geom2d_Line)::DownCast(aC2D); if (!aL2D.IsNull()) { aGAC2.Load(aC2D); } else { aGAC2.Load(aC2D, aT1, aT2); } Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInter, aTolInter); bIsDone=aGInter.IsDone(); if(bIsDone) { aNbPoints=aGInter.NbPoints(); if (aNbPoints) { for (j=1; j<=aNbPoints; ++j) { gp_Pnt2d aP2D=aGInter.Point(j).Value(); // aX=(bXDir) ? aP2D.X(): aP2D.Y(); // if (fabs (aX-aTD1) < aDT || fabs (aX-aTD2) < aDT) { continue; } if (aX < aTD1 || aX > aTD2) { continue; } // Standard_Boolean bRejectFlag=Standard_False; const BOPTools_ListOfPave& aListOfPave=aPaveSet.Set(); BOPTools_ListIteratorOfListOfPave aPaveIt(aListOfPave); for (; aPaveIt.More(); aPaveIt.Next()) { const BOPTools_Pave& aPavex=aPaveIt.Value(); Standard_Real aXx=aPavex.Param(); if (fabs (aX-aXx) < aDT) { bRejectFlag=Standard_True; break; } } if (bRejectFlag) { continue; } // BOPTools_Pave aPave(nVD, aX, BooleanOperations_UnknownInterference); aPaveSet.Append(aPave); } } } } } //======================================================================= // function: FindPaveBlocks // purpose: //======================================================================= void BOPTools_DEProcessor::FindPaveBlocks(const Standard_Integer , const Standard_Integer nVD, const Standard_Integer nFD, BOPTools_ListOfPaveBlock& aLPBOut) { BOPTools_CArray1OfSSInterference& aFFs=(myFiller->InterfPool())->SSInterferences(); BOPTools_ListIteratorOfListOfPaveBlock anIt; Standard_Integer i, aNb, nF2, nV; //ZZ const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED)); aNb=aFFs.Extent(); for (i=1; i<=aNb; i++) { BOPTools_SSInterference& aFF=aFFs(i); // nF2=aFF.OppositeIndex(nFD); if (!nF2) { continue; } // // Split Parts const BOPTools_ListOfPaveBlock& aLPBSplits=aFF.PaveBlocks(); anIt.Initialize(aLPBSplits); for (; anIt.More(); anIt.Next()) { const BOPTools_PaveBlock& aPBSp=anIt.Value(); const BOPTools_Pave& aPave1=aPBSp.Pave1(); nV=aPave1.Index(); if (nV==nVD) { aLPBOut.Append(aPBSp); continue; } const BOPTools_Pave& aPave2=aPBSp.Pave2(); nV=aPave2.Index(); if (nV==nVD) { aLPBOut.Append(aPBSp); continue; } } // // Section Parts Standard_Integer j, aNbCurves; BOPTools_SequenceOfCurves& aSC=aFF.Curves(); aNbCurves=aSC.Length(); for (j=1; j<=aNbCurves; j++) { const BOPTools_Curve& aBC=aSC(j); const BOPTools_ListOfPaveBlock& aLPBSe=aBC.NewPaveBlocks(); anIt.Initialize(aLPBSe); for (; anIt.More(); anIt.Next()) { const BOPTools_PaveBlock& aPBSe=anIt.Value(); const BOPTools_Pave& aPv1=aPBSe.Pave1(); nV=aPv1.Index(); if (nV==nVD) { aLPBOut.Append(aPBSe); continue; } const BOPTools_Pave& aPv2=aPBSe.Pave2(); nV=aPv2.Index(); if (nV==nVD) { aLPBOut.Append(aPBSe); continue; } } } } // for (i=1; i<=aNb; i++) Next FF interference }