// File: BOP_WireSplitter.cxx // Created: Mon Apr 9 11:00:15 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 static void Path (const GeomAdaptor_Surface& aGAS, const TopoDS_Face& myFace, const TopoDS_Vertex& aVa, const TopoDS_Edge& aEOuta, BOP_EdgeInfo& anEdgeInfo, TopTools_SequenceOfShape& aLS, TopTools_SequenceOfShape& aVertVa, TColgp_SequenceOfPnt2d& aCoordVa, BOPTColStd_ListOfListOfShape& myShapes, BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap); static Standard_Real Angle (const gp_Dir2d& aDir2D); static void GetNextVertex(const TopoDS_Vertex& aV, const TopoDS_Edge& aE, TopoDS_Vertex& aV1); static Standard_Real ClockWiseAngle(const Standard_Real aAngleIn, const Standard_Real aAngleOut); static Standard_Real AngleIn(const TopoDS_Edge& aEIn, const BOP_ListOfEdgeInfo& aLEInfo); static Standard_Real Angle2D (const TopoDS_Vertex& aV, const TopoDS_Edge& anEdge, const TopoDS_Face& myFace, const GeomAdaptor_Surface& aGAS, const Standard_Boolean aFlag); static gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1, const TopoDS_Edge& aE1, const TopoDS_Face& aF); static gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE, const TopoDS_Face& aF); static Standard_Real Tolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); static Standard_Real UTolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); static Standard_Real VTolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS); static Standard_Boolean RecomputeAngles(const BOP_ListOfEdgeInfo& aLEInfo, const TopoDS_Face& theFace, const gp_Pnt2d& thePb, const TopoDS_Vertex& theVb, const GeomAdaptor_Surface& theGAS, const TopoDS_Edge& theEOuta, const Standard_Boolean& bHasClosed, const Standard_Real& theTol2D, TColStd_SequenceOfReal& theRecomputedAngles); // static Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& ); // //======================================================================= // function: DoWithFace // purpose: //======================================================================= void BOP_WireSplitter::DoWithFace() { myEdges.Clear(); TopExp_Explorer anExpEdges (myFace, TopAbs_EDGE); for (; anExpEdges.More(); anExpEdges.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anExpEdges.Current()); // if (anEdge.Orientation()==TopAbs_INTERNAL){ continue; } // myEdges.Append(anEdge); } Do(); } //======================================================================= // function: DoWithListOfEdges // purpose: //======================================================================= void BOP_WireSplitter::DoWithListOfEdges(const TopTools_ListOfShape& aLE) { myEdges.Clear(); TopTools_ListIteratorOfListOfShape anItList; anItList.Initialize(aLE); for (; anItList.More(); anItList.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); // if (anEdge.Orientation()==TopAbs_INTERNAL){ continue; } // myEdges.Append(anEdge); } Do(); } //======================================================================= // function: Do // purpose: //======================================================================= void BOP_WireSplitter::Do() { myIsDone=Standard_False; myNothingToDo=Standard_True; Standard_Integer index, i, aNb, aCntIn, aCntOut; Standard_Boolean anIsIn; Standard_Real anAngle; BOP_ListOfEdgeInfo emptyInfo; TopTools_ListIteratorOfListOfShape anItList; // // 1.Filling mySmartMap mySmartMap.Clear(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); // if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) { continue; } // TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX); for (; anExpVerts.More(); anExpVerts.Next()) { const TopoDS_Shape& aVertex= anExpVerts.Current(); index = mySmartMap.FindIndex(aVertex); if (!index) { index=mySmartMap.Add(aVertex, emptyInfo); } BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index); BOP_EdgeInfo aEInfo; aEInfo.SetEdge(anEdge); TopAbs_Orientation anOr=aVertex.Orientation(); if (anOr==TopAbs_FORWARD) { aEInfo.SetInFlag(Standard_False); } else if (anOr==TopAbs_REVERSED) { aEInfo.SetInFlag(Standard_True); } aListOfEInfo.Append(aEInfo); } } // aNb=mySmartMap.Extent(); // // 2. myNothingToDo myNothingToDo=Standard_True; for (i=1; i<=aNb; i++) { aCntIn=0; aCntOut=0; const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { aCntIn++; } else { aCntOut++; } } if (aCntIn!=1 || aCntOut!=1) { myNothingToDo=Standard_False; break; } } // // Each vertex has one edge In and one - Out. Good. But it is not enought // to consider that nothing to do with this. We must check edges on TShape // coinsidence. If there are such edges there is something to do with. // if (myNothingToDo) { Standard_Integer aNbE, aNbMapEE; TopTools_IndexedDataMapOfShapeListOfShape aMapEE; aNbE=myEdges.Extent(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Shape& aE = anItList.Value(); if (!aMapEE.Contains(aE)) { TopTools_ListOfShape aLEx; aLEx.Append(aE); aMapEE.Add(aE, aLEx); } else { TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE); aLEx.Append(aE); } } Standard_Boolean bFlag; bFlag=Standard_True; aNbMapEE=aMapEE.Extent(); for (i=1; i<=aNbMapEE; i++) { const TopTools_ListOfShape& aLEx=aMapEE(i); aNbE=aLEx.Extent(); if (aNbE==1) { // usual case continue; } else if (aNbE==2){ const TopoDS_Shape& aE1=aLEx.First(); const TopoDS_Shape& aE2=aLEx.Last(); if (aE1.IsSame(aE2)) { bFlag=Standard_False; break; } } else { bFlag=Standard_False; break; } } myNothingToDo=myNothingToDo && bFlag; } // // if (myNothingToDo) { myIsDone=Standard_True; return; } // // 3. Angles in mySmartMap BRepAdaptor_Surface aBAS(myFace); const GeomAdaptor_Surface& aGAS=aBAS.Surface(); for (i=1; i<=aNb; i++) { const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aE=anEdgeInfo.Edge(); // TopoDS_Vertex aVV=aV; // anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { // aVV.Orientation(TopAbs_REVERSED); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True); } // else { // OUT // aVV.Orientation(TopAbs_FORWARD); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False); } anEdgeInfo.SetAngle(anAngle); } } // // 4. Do // Standard_Boolean anIsOut, anIsNotPassed; TopTools_SequenceOfShape aLS, aVertVa; TColgp_SequenceOfPnt2d aCoordVa; BOP_ListIteratorOfListOfEdgeInfo anIt; for (i=1; i<=aNb; i++) { const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i); anIt.Initialize(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aEOuta=anEdgeInfo.Edge(); anIsOut=!anEdgeInfo.IsIn(); anIsNotPassed=!anEdgeInfo.Passed(); if (anIsOut && anIsNotPassed) { // aLS.Clear(); aVertVa.Clear(); aCoordVa.Clear(); // Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, aVertVa, aCoordVa, myShapes, mySmartMap); } } } // { Standard_Integer aNbV, aNbE; TopoDS_Vertex aV1, aV2; BOPTColStd_ListOfListOfShape aShapes; BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes); for (; anItW.More(); anItW.Next()) { TopTools_IndexedMapOfShape aMV, aME; const TopTools_ListOfShape& aLE=anItW.Value(); TopTools_ListIteratorOfListOfShape anItE(aLE); for (; anItE.More(); anItE.Next()) { const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value()); aME.Add(aE); TopExp::Vertices(aE, aV1, aV2); aMV.Add(aV1); aMV.Add(aV2); } aNbV=aMV.Extent(); aNbE=aME.Extent(); if (aNbV<=aNbE) { aShapes.Append(aLE); } } // myShapes.Clear(); anItW.Initialize(aShapes); for (; anItW.More(); anItW.Next()) { const TopTools_ListOfShape& aLE=anItW.Value(); myShapes.Append(aLE); } } // myIsDone=Standard_True; } //======================================================================= // function: Path // purpose: //======================================================================= void Path (const GeomAdaptor_Surface& aGAS, const TopoDS_Face& myFace, const TopoDS_Vertex& aVa, const TopoDS_Edge& aEOuta, BOP_EdgeInfo& anEdgeInfo, TopTools_SequenceOfShape& aLS, TopTools_SequenceOfShape& aVertVa, TColgp_SequenceOfPnt2d& aCoordVa, BOPTColStd_ListOfListOfShape& myShapes, BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap) { Standard_Integer i,j, aNb, aNbj; Standard_Real aD, aTol=1.e-7, anAngleIn, anAngleOut, anAngle, aMinAngle; Standard_Real aTol2D, aTolVb, aTolVPrev; Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed; BOP_ListIteratorOfListOfEdgeInfo anIt; TopoDS_Vertex aVb; TopoDS_Edge aEOutb; // // append block // // Do not escape through edge from which you enter aNb=aLS.Length(); if (aNb==1) { const TopoDS_Shape& anEPrev=aLS(aNb); if (anEPrev.IsSame(aEOuta)) { return; } } // // anEdgeInfo.SetPassed(Standard_True); aLS.Append(aEOuta); aVertVa.Append(aVa); TopoDS_Vertex pVa=aVa; pVa.Orientation(TopAbs_FORWARD); gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace); aCoordVa.Append(aPa); GetNextVertex (pVa, aEOuta, aVb); gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace); const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb); TopoDS_Vertex aV1, aV2; TopExp::Vertices(aEOuta, aV1, aV2); Standard_Boolean bHasClosedEdge = aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2); Standard_Boolean bHasDegenerated = BRep_Tool::Degenerated(aEOuta); Standard_Boolean bHasSeam = BRep_Tool::IsClosed(aEOuta, myFace); anIt.Initialize(aLEInfoVb); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEI=anIt.Value(); const TopoDS_Edge& aE=anEI.Edge(); bHasDegenerated = bHasDegenerated || BRep_Tool::Degenerated(aE); bHasSeam = bHasSeam || BRep_Tool::IsClosed(aE, myFace); aV1.Nullify(); aV2.Nullify(); TopExp::Vertices(aE, aV1, aV2); bHasClosedEdge = bHasClosedEdge || aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2); } aNb=aLS.Length(); if (aNb>0) { // TopTools_ListOfShape aBuf; for (i=aNb; i>0; i--) { const TopoDS_Shape& aVPrev=aVertVa(i); const gp_Pnt2d& aPaPrev=aCoordVa(i); const TopoDS_Shape& aEPrev=aLS(i); aBuf.Append(aEPrev); anIsSameV=aVPrev.IsSame(aVb); anIsSameV2d = Standard_False; if (anIsSameV) { anIsSameV2d = Standard_True; if(bHasDegenerated || bHasSeam || bHasClosedEdge) { aTolVb =BRep_Tool::Tolerance(TopoDS::Vertex(aVb)); aTolVPrev=BRep_Tool::Tolerance(TopoDS::Vertex(aVPrev)); aTol=aTolVb+aTolVPrev; // aTol=2.*Tolerance2D(aVb, aGAS); aD=aPaPrev.Distance(aPb); anIsSameV2d = (aD < aTol); if(anIsSameV2d) { Standard_Real udist = fabs(aPaPrev.X() - aPb.X()); Standard_Real vdist = fabs(aPaPrev.Y() - aPb.Y()); Standard_Real aTolU = 2. * UTolerance2D(aVb, aGAS); Standard_Real aTolV = 2. * VTolerance2D(aVb, aGAS); if((udist > aTolU) || (vdist > aTolV)) { anIsSameV2d = Standard_False; } } } } // if (anIsSameV && anIsSameV2d) { myShapes.Append(aBuf); // TopTools_SequenceOfShape aLSt, aVertVat; TColgp_SequenceOfPnt2d aCoordVat; // aNbj=i-1; if (aNbj<1) { // aLS.Clear(); aVertVa.Clear(); aCoordVa.Clear(); // return; } aVb=TopoDS::Vertex(aVertVa(i)); for (j=1; j<=aNbj; j++) { aLSt.Append(aLS(j)); aVertVat.Append(aVertVa(j)); aCoordVat.Append(aCoordVa(j)); } // aLS.Clear(); aVertVa.Clear(); aCoordVa.Clear(); aLS=aLSt; aVertVa=aVertVat; aCoordVa=aCoordVat; // break; } } } // aTol2D=2.*Tolerance2D(aVb, aGAS); // // anAngleIn in Vb from edge aEOuta const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb); // anAngleIn=AngleIn(aEOuta, aLEInfo); // // aEOutb BOP_EdgeInfo *pEdgeInfo=NULL; aMinAngle=100.; anIsFound=Standard_False; TColStd_SequenceOfReal aRecomputedAngles; Standard_Boolean bRecomputeAngle = RecomputeAngles(aLEInfo, myFace, aPb, aVb, aGAS, aEOuta, (bHasDegenerated || bHasSeam || bHasClosedEdge), aTol2D, aRecomputedAngles); Standard_Integer aCurIndexE = 0; anIt.Initialize(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEI=anIt.Value(); const TopoDS_Edge& aE=anEI.Edge(); anIsOut=!anEI.IsIn(); anIsNotPassed=!anEI.Passed(); if (anIsOut && anIsNotPassed) { aCurIndexE++; // // Is there one way to go out of the vertex // we have to use it only. Standard_Integer iCnt; iCnt=NbWaysOut (aLEInfo); // if (!iCnt) { // no way to go . (Error) return ; } // if (iCnt==1) { // the one and only way to go out . pEdgeInfo=&anEI; anIsFound=Standard_True; break; } // // Look for minimal angle and make the choice. gp_Pnt2d aP2Dx; // aP2Dx=Coord2dVf(aE, myFace); // aD=aP2Dx.Distance(aPb); if (aD > aTol2D){ continue; } // // anAngleOut=anEI.Angle(); // if(bRecomputeAngle) { if(aCurIndexE <= aRecomputedAngles.Length()) { anAngleOut = aRecomputedAngles.Value(aCurIndexE); } } // anAngle=ClockWiseAngle(anAngleIn, anAngleOut); if (anAngle < aMinAngle) { aMinAngle=anAngle; pEdgeInfo=&anEI; anIsFound=Standard_True; } } } // for (; anIt.More(); anIt.Next()) // if (!anIsFound) { // no way to go . (Error) return; } aEOutb=pEdgeInfo->Edge(); Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS, aVertVa, aCoordVa, myShapes, mySmartMap); } //======================================================================= // function: Coord2dVf // purpose: //======================================================================= gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE, const TopoDS_Face& aF) { TopExp_Explorer anExp(aE, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); if (aVx.Orientation()==TopAbs_FORWARD) return Coord2d(aVx, aE, aF); } const Standard_Real aCoord=99.; const gp_Pnt2d aP2D1(aCoord, aCoord); return aP2D1; } //======================================================================= // function: Tolerance2D // purpose: //======================================================================= Standard_Real Tolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) { const GeomAbs_SurfaceType aType=aGAS.GetType(); const Standard_Real aTolV3D=BRep_Tool::Tolerance(aV); const Standard_Real aUr=aGAS.UResolution(aTolV3D); const Standard_Real aVr=aGAS.VResolution(aTolV3D); // Standard_Real aTol2D=(aVr>aUr) ? aVr : aUr; // if (aType==GeomAbs_BSplineSurface || aType==GeomAbs_Sphere) { if (aTol2D < aTolV3D) aTol2D=aTolV3D; } //modified by NIZNHY-PKV Wed Jul 5 16:44:59 2006f else if (aType==GeomAbs_BSplineSurface) { aTol2D=1.1*aTol2D; } //modified by NIZNHY-PKV Wed Jul 5 16:45:02 2006t // return aTol2D; } //======================================================================= // function: Coord2d // purpose: //======================================================================= gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1, const TopoDS_Edge& aE1, const TopoDS_Face& aF) { const Standard_Real t=BRep_Tool::Parameter (aV1, aE1, aF); Standard_Real aFirst, aLast, aToler; Handle(Geom2d_Curve) aC2D; BOPTools_Tools2D::CurveOnSurface (aE1, aF, aC2D, aFirst, aLast, aToler, Standard_True); gp_Pnt2d aP2D1; aC2D->D0 (t, aP2D1); return aP2D1; } //======================================================================= // function: AngleIn // purpose: //======================================================================= Standard_Real AngleIn(const TopoDS_Edge& aEIn, const BOP_ListOfEdgeInfo& aLEInfo) { BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aE=anEdgeInfo.Edge(); const Standard_Boolean anIsIn=anEdgeInfo.IsIn(); // if (anIsIn && aE==aEIn) return anEdgeInfo.Angle(); } return 0.; } //======================================================================= // function: ClockWiseAngle // purpose: //======================================================================= Standard_Real ClockWiseAngle(const Standard_Real aAngleIn, const Standard_Real aAngleOut) { const Standard_Real aTwoPi=Standard_PI+Standard_PI; Standard_Real dA, A1, A2, AIn, AOut ; AIn=aAngleIn; AOut=aAngleOut; if (AIn >= aTwoPi) { AIn=AIn-aTwoPi; } if (AOut >= aTwoPi) { AOut=AOut-aTwoPi; } A1=AIn+Standard_PI; if (A1 >= aTwoPi) { A1=A1-aTwoPi; } A2=AOut; dA=A1-A2; if (dA <= 0.) { dA=aTwoPi+dA; } //xx //else if (dA <= 1.e-15) { else if (dA <= 1.e-14) { dA=aTwoPi; } return dA; } //======================================================================= // function: GetNextVertex // purpose: //======================================================================= void GetNextVertex(const TopoDS_Vertex& aV, const TopoDS_Edge& aE, TopoDS_Vertex& aV1) { TopExp_Explorer anExp(aE, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); if (!aVx.IsEqual(aV)) { aV1=aVx; return ; } } aV1=aV; } //======================================================================= // function: Angle2D // purpose: //======================================================================= Standard_Real Angle2D (const TopoDS_Vertex& aV, const TopoDS_Edge& anEdge, const TopoDS_Face& myFace, const GeomAdaptor_Surface& aGAS, const Standard_Boolean aFlag) { const Standard_Real aTV=BRep_Tool::Parameter (aV, anEdge, myFace); if (Precision::IsInfinite(aTV)) return 0.; Handle(Geom2d_Curve) aC2D; Standard_Real aFirst, aLast, aToler; BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D, aFirst, aLast, aToler, Standard_True); if (aC2D.IsNull()) return 0.; //dt=1.e-7; Standard_Real dt=Tolerance2D(aV, aGAS); const Standard_Real dtmax=(aLast - aFirst) * 0.25; if(dt > dtmax) { // to save direction of the curve as much as it possible // in the case of big tolerances dt = dtmax; } const Standard_Real aTV1 = (fabs (aTV-aFirst) < fabs(aTV - aLast))? aTV + dt : aTV - dt; // gp_Pnt2d aPV, aPV1; aC2D->D0 (aTV, aPV); aC2D->D0 (aTV1, aPV1); const gp_XY aV2D( aFlag? (aPV.XY()-aPV1.XY()) : (aPV1.XY()-aPV.XY()) ); //See http://www.opencascade.org/org/forum/thread_17712/ if (aV2D.SquareModulus() <= gp::Resolution()*gp::Resolution()) return 0.; const gp_Dir2d aDir2D(aV2D); return Angle(aDir2D); } //======================================================================= // function: Angle // purpose: //======================================================================= Standard_Real Angle (const gp_Dir2d& aDir2D) { const Standard_Real anAngle = gp_Dir2d(1.,0.).Angle(aDir2D); return ((anAngle < 0.)? anAngle + Standard_PI + Standard_PI : anAngle); } //======================================================================= // function: NbWaysOut // purpose: //======================================================================= Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo) { Standard_Integer iCnt=0; // BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { const BOP_EdgeInfo& anEI=anIt.Value(); // //const TopoDS_Edge& aE=anEI.Edge(); const Standard_Boolean bIsOut=!anEI.IsIn(); const Standard_Boolean bIsNotPassed=!anEI.Passed(); if (bIsOut && bIsNotPassed) iCnt++; } return iCnt; } //======================================================================= //function : UTolerance2D //purpose : //======================================================================= Standard_Real UTolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) { const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV); const Standard_Real anUr = aGAS.UResolution(aTolV3D); // return anUr; } //======================================================================= //function : VTolerance2D //purpose : //======================================================================= Standard_Real VTolerance2D (const TopoDS_Vertex& aV, const GeomAdaptor_Surface& aGAS) { const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV); const Standard_Real anVr = aGAS.VResolution(aTolV3D); // return anVr; } //======================================================================= // function: RecomputeAngles // purpose: //======================================================================= Standard_Boolean RecomputeAngles(const BOP_ListOfEdgeInfo& aLEInfo, const TopoDS_Face& theFace, const gp_Pnt2d& thePb, const TopoDS_Vertex& theVb, const GeomAdaptor_Surface& theGAS, const TopoDS_Edge& theEOuta, const Standard_Boolean& bHasClosed, const Standard_Real& theTol2D, TColStd_SequenceOfReal& theRecomputedAngles) { Standard_Boolean bRecomputeAngle = Standard_False; BOP_ListIteratorOfListOfEdgeInfo anIt; anIt.Initialize(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEI=anIt.Value(); const TopoDS_Edge& aE=anEI.Edge(); Standard_Boolean anIsOut=!anEI.IsIn(); Standard_Boolean anIsNotPassed=!anEI.Passed(); if (anIsOut && anIsNotPassed) { theRecomputedAngles.Append(anEI.Angle()); Standard_Integer acurindex = theRecomputedAngles.Length(); Standard_Boolean bRecomputeAngleLocal = Standard_False; TopExp_Explorer anExp1(aE, TopAbs_VERTEX); for(; anExp1.More(); anExp1.Next()) { TopExp_Explorer anExp2(theEOuta, TopAbs_VERTEX); Standard_Boolean existsInEdge = Standard_False; for(; anExp2.More(); anExp2.Next()) { if(anExp1.Current().IsSame(anExp2.Current())) { existsInEdge = Standard_True; break; } } if(!existsInEdge) { bRecomputeAngleLocal = Standard_False; break; } bRecomputeAngleLocal = Standard_True; } bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; if(!bRecomputeAngle) { BOP_ListIteratorOfListOfEdgeInfo anIt2(aLEInfo); for(; anIt2.More(); anIt2.Next()) { BOP_EdgeInfo& anEI2=anIt2.Value(); const TopoDS_Edge& aE2=anEI2.Edge(); if(aE2.IsSame(aE)) continue; Standard_Boolean anIsOut2=!anEI2.IsIn(); Standard_Boolean anIsNotPassed2=!anEI2.Passed(); if (anIsOut2 && anIsNotPassed2) { anExp1.Init(aE, TopAbs_VERTEX); for(; anExp1.More(); anExp1.Next()) { TopExp_Explorer anExp2(aE2, TopAbs_VERTEX); Standard_Boolean existsInEdge = Standard_False; for(; anExp2.More(); anExp2.Next()) { if(anExp1.Current().IsSame(anExp2.Current())) { existsInEdge = Standard_True; break; } } if(!existsInEdge) { bRecomputeAngleLocal = Standard_False; break; } bRecomputeAngleLocal = Standard_True; } bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; } } } bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; if(bRecomputeAngle) { gp_Pnt2d aP2Dx; // aP2Dx=Coord2dVf(aE, theFace); Standard_Real aD = aP2Dx.Distance(thePb); TopoDS_Vertex aVf; TopExp_Explorer anExp(aE, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); if (aVx.Orientation()==TopAbs_FORWARD) { aVf = aVx; } } Standard_Boolean bIgnore = Standard_False; if(bHasClosed || aVf.IsNull() || !aVf.IsSame(theVb)) { bIgnore = (aD > theTol2D); } if(!bIgnore && (theTol2D > PI)) { Standard_Real udist = fabs(aP2Dx.X() - thePb.X()); Standard_Real vdist = fabs(aP2Dx.Y() - thePb.Y()); Standard_Real aTolU = 2. * UTolerance2D(theVb, theGAS); Standard_Real aTolV = 2. * VTolerance2D(theVb, theGAS); if((udist > aTolU) || (vdist > aTolV)) { bIgnore = Standard_True; } } if((aD > Precision::Confusion()) && !bIgnore) { Standard_Real f1, l1; Handle(Geom2d_Curve) ac1 = BRep_Tool::CurveOnSurface(aE, theFace, f1, l1); Standard_Real aTV1 = BRep_Tool::Parameter (aVf, aE, theFace); Standard_Real aTV12 = 0.; Standard_Real dt1 = (l1 - f1) * 0.5; if (fabs (aTV1-f1) < fabs(aTV1 - l1)) { aTV12 = aTV1 + dt1; } else { aTV12 = aTV1 - dt1; } gp_Pnt2d aPointNew = ac1->Value(aTV12); gp_Vec2d aV2DOut(thePb, aPointNew); gp_Dir2d aDir2D(aV2DOut); Standard_Real anAngleOut = Angle(aDir2D); theRecomputedAngles.ChangeValue(acurindex) = anAngleOut; } } } } return bRecomputeAngle; }