From e491cf27dfc5c4af9e763f36578c106460284c92 Mon Sep 17 00:00:00 2001 From: emv Date: Fri, 22 Dec 2017 12:57:04 +0300 Subject: [PATCH] 0029387: Incorrect result of cut a face with several shapes Eliminate normalization of the section curve while making approximation. Remove section edges having no valid range. Test case for the issue. --- src/ApproxInt/ApproxInt_Approx.gxx | 569 +++++++++++++++------------ src/BOPAlgo/BOPAlgo_PaveFiller.cdl | 21 +- src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx | 89 ++++- tests/bugs/modalg_7/bug29387 | 27 ++ 4 files changed, 445 insertions(+), 261 deletions(-) create mode 100644 tests/bugs/modalg_7/bug29387 diff --git a/src/ApproxInt/ApproxInt_Approx.gxx b/src/ApproxInt/ApproxInt_Approx.gxx index 6b90d71292..f9fde47d51 100644 --- a/src/ApproxInt/ApproxInt_Approx.gxx +++ b/src/ApproxInt/ApproxInt_Approx.gxx @@ -26,120 +26,125 @@ const Standard_Integer LimRajout = 5; const Standard_Integer NbPntMaxDecoupage = 30 ; const Standard_Real RatioTol = 1.5 ; -static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c) { - if(a<0.0) a=-a; - if(b<0.0) b=-b; - if(c<0.0) c=-c; - if(a>c) a=c; - if(a>b) a=b; - return(a); -} - -static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d) { - if(a<0.0) a=-a; - if(b<0.0) b=-b; - if(c<0.0) c=-c; - if(d<0.0) d=-d; - if(a>c) a=c; - if(a>b) a=b; - if(a>d) a=d; - return(a); -} - -static void ComputeTrsf3d(const Handle(TheWLine)& theline, - Standard_Real& Xo, Standard_Real& Ax, - Standard_Real& Yo, Standard_Real& Ay, - Standard_Real& Zo, Standard_Real& Az) { - - Standard_Integer nbp = theline->NbPnts(); - Standard_Real z0,z1,x0,x1,y0,y1; - z0=y0=x0=RealLast(); - z1=y1=x1=RealFirst(); - for(Standard_Integer i=1;i<=nbp;i++) { - const gp_Pnt& P = theline->Point(i).Value(); - Standard_Real X = P.X(); - Standard_Real Y = P.Y(); - Standard_Real Z = P.Z(); - if(Xx1) x1=X; - if(Yy1) y1=Y; - if(Zz1) z1=Z; - } -//-deb- cout << "ComputeTrsf3d -- NbPnt = " << nbp << endl ; -//-deb- cout << "ComputeTrsf3d -- Xm = " << x0 << " Ym = " << y0 << " Zm = " << z0 << endl ; -//-deb- cout << "ComputeTrsf3d -- XM = " << x1 << " YM = " << y1 << " ZM = " << z1 << endl ; - Standard_Real dx = x1-x0; - Standard_Real dy = y1-y0; - Standard_Real dz = z1-z0; - Standard_Real MaxD = dx; - if(MaxD < dy) MaxD=dy; - if(MaxD < dz) MaxD=dz; - Standard_Real MaxDF = 0.01*MaxD; - - //-- lbr le 22 fev99 : FPE - if(MaxDF<1e-12) - MaxDF=1.0; - - - if(dx > MaxDF) { Ax = 1.0 / dx; Xo = -Ax * x0; } - else { Ax = 1.0/( MaxDF) ; Xo = -Ax*x0; } - if(dy > MaxDF) { Ay = 1.0 / dy; Yo = -Ay * y0; } - else { Ay = 1.0/( MaxDF); Yo = -Ay*y0; } - if(dz > MaxDF) { Az = 1.0 / dz; Zo = -Az * z0; } - else { Az = 1.0/(MaxDF); Zo = -Az*z0; } -} - -static void ComputeTrsf2d(const Handle(TheWLine)& theline, - Standard_Real& Uo, Standard_Real& Au, - Standard_Real& Vo, Standard_Real& Av, - const Standard_Boolean onFirst, - const Standard_Real UVResRatio = 1.) { - Standard_Integer nbp = theline->NbPnts(); - Standard_Real u0,u1,v0,v1; - u0 = v0 = RealLast(); - u1 = v1 = RealFirst(); - // pointer to a member-function - void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const; - if (onFirst) - pfunc = &IntSurf_PntOn2S::ParametersOnS1; - else - pfunc = &IntSurf_PntOn2S::ParametersOnS2; - for(Standard_Integer i=1;i<=nbp;i++) { - const IntSurf_PntOn2S& POn2S = theline->Point(i); - Standard_Real U,V; - (POn2S.*pfunc)(U,V); - if(Uu1) u1=U; - if(Vv1) v1=V; - } - - Standard_Real du = (u1-u0); - Standard_Real dv = (v1-v0); - - if (UVResRatio > 1.) - du *= UVResRatio; - else if (UVResRatio < 1.) - dv /= UVResRatio; - - Standard_Real MaxUV=du; - if(MaxUV MaxUVF) { Au = 1.0 / du; Uo = -Au * u0; } - else { Au = 1.0/(MaxUVF); Uo = -Au*u0; } - if(dv > MaxUVF) { Av = 1.0 / dv; Vo = -Av * v0; } - else { Av = 1.0/(MaxUVF); Vo = -Av*v0; } -} +//static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c) { +// if(a<0.0) a=-a; +// if(b<0.0) b=-b; +// if(c<0.0) c=-c; +// if(a>c) a=c; +// if(a>b) a=b; +// return(a); +//} +// +//static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d) { +// if(a<0.0) a=-a; +// if(b<0.0) b=-b; +// if(c<0.0) c=-c; +// if(d<0.0) d=-d; +// if(a>c) a=c; +// if(a>b) a=b; +// if(a>d) a=d; +// return(a); +//} +// +//static void ComputeTrsf3d(const Handle(TheWLine)& theline, +// Standard_Real& Xo, Standard_Real& Ax, +// Standard_Real& Yo, Standard_Real& Ay, +// Standard_Real& Zo, Standard_Real& Az) { +// +// Standard_Integer nbp = theline->NbPnts(); +// Standard_Real z0,z1,x0,x1,y0,y1; +// z0=y0=x0=RealLast(); +// z1=y1=x1=RealFirst(); +// for(Standard_Integer i=1;i<=nbp;i++) { +// const gp_Pnt& P = theline->Point(i).Value(); +// Standard_Real X = P.X(); +// Standard_Real Y = P.Y(); +// Standard_Real Z = P.Z(); +// if(Xx1) x1=X; +// if(Yy1) y1=Y; +// if(Zz1) z1=Z; +// } +////-deb- cout << "ComputeTrsf3d -- NbPnt = " << nbp << endl ; +////-deb- cout << "ComputeTrsf3d -- Xm = " << x0 << " Ym = " << y0 << " Zm = " << z0 << endl ; +////-deb- cout << "ComputeTrsf3d -- XM = " << x1 << " YM = " << y1 << " ZM = " << z1 << endl ; +// Standard_Real dx = x1-x0; +// Standard_Real dy = y1-y0; +// Standard_Real dz = z1-z0; +// Standard_Real MaxD = dx; +// if(MaxD < dy) MaxD=dy; +// if(MaxD < dz) MaxD=dz; +// Standard_Real MaxDF = 0.01*MaxD; +// +// //-- lbr le 22 fev99 : FPE +// if(MaxDF<1e-12) +// MaxDF=1.0; +// +// +// if(dx > MaxDF) { Ax = 1.0 / dx; Xo = -Ax * x0; } +// else { Ax = 1.0/( MaxDF) ; Xo = -Ax*x0; } +// if(dy > MaxDF) { Ay = 1.0 / dy; Yo = -Ay * y0; } +// else { Ay = 1.0/( MaxDF); Yo = -Ay*y0; } +// if(dz > MaxDF) { Az = 1.0 / dz; Zo = -Az * z0; } +// else { Az = 1.0/(MaxDF); Zo = -Az*z0; } +//} +// +//static void ComputeTrsf2d(const Handle(TheWLine)& theline, +// Standard_Real& Uo, Standard_Real& Au, +// Standard_Real& Vo, Standard_Real& Av, +// const Standard_Boolean onFirst, +// const Standard_Real UVResRatio = 1.) { +// Standard_Integer nbp = theline->NbPnts(); +// Standard_Real u0,u1,v0,v1; +// u0 = v0 = RealLast(); +// u1 = v1 = RealFirst(); +// // pointer to a member-function +// void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const; +// if (onFirst) +// pfunc = &IntSurf_PntOn2S::ParametersOnS1; +// else +// pfunc = &IntSurf_PntOn2S::ParametersOnS2; +// for(Standard_Integer i=1;i<=nbp;i++) { +// const IntSurf_PntOn2S& POn2S = theline->Point(i); +// Standard_Real U,V; +// (POn2S.*pfunc)(U,V); +// if(Uu1) u1=U; +// if(Vv1) v1=V; +// } +// +// Standard_Real du = (u1-u0); +// Standard_Real dv = (v1-v0); +// +// if (UVResRatio > 1.) +// du *= UVResRatio; +// else if (UVResRatio < 1.) +// dv /= UVResRatio; +// +// Standard_Real MaxUV=du; +// if(MaxUV MaxUVF) { Au = 1.0 / du; Uo = -Au * u0; } +// else { Au = 1.0/(MaxUVF); Uo = -Au*u0; } +// if(dv > MaxUVF) { Av = 1.0 / dv; Vo = -Av * v0; } +// else { Av = 1.0/(MaxUVF); Vo = -Av*v0; } +//} +//-------------------------------------------------------------------------------- +static Standard_Integer CorrectFinishIdx(const Standard_Integer theMinIdx, + const Standard_Integer theMaxIdx, + const Handle(TheWLine)& theline); +//---------------------------------------------------------------------------------- ApproxInt_Approx::ApproxInt_Approx(): myComputeLine(4, @@ -174,8 +179,8 @@ void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline, const Standard_Integer indicemin, const Standard_Integer indicemax) { - myMinFactorXYZ = 0.0; - myMinFactorUV = 0.0; + myMinFactorXYZ = 1.0; + myMinFactorUV = 1.0; myTolReached3d = myTolReached2d = 0.; @@ -198,24 +203,24 @@ void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline, myTolReached = Standard_True; Standard_Real Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v; - if(ApproxXYZ) { - ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az); - } - else { + //if(ApproxXYZ) { + // ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az); + //} + //else { Xo=Yo=Zo=0.0; Ax=Ay=Az=1.0;; - } - if(ApproxU1V1) { - ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True); - } - else { + //} + //if(ApproxU1V1) { + // ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True); + //} + //else { U1o=V1o=0.0; A1u=A1v=1.0; - } - if(ApproxU2V2) { - ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False); - } - else { + //} + //if(ApproxU2V2) { + // ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False); + //} + //else { U2o=V2o=0.0; A2u=A2v=1.0; - } + //} //-deb- cout << "ApproxInt_Approx -- NbPntMax = " << myNbPntMax << endl ; //-deb- cout << "ApproxInt_Approx -- Tol3D = " << myTol3d << endl ; @@ -226,15 +231,15 @@ void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline, //-deb- cout << "ApproxInt_Approx -- U1o = " << U1o << " V1o = " << V1o << " A1u = " << A1u << " A1v = " << A1v << endl ; //-deb- cout << "ApproxInt_Approx -- U2o = " << U2o << " V2o = " << V2o << " A2u = " << A2u << " A2v = " << A2v << endl ; - Standard_Real A3d = MINABS3(Ax,Ay,Az); - if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { - myMinFactorXYZ = A3d; - } - - Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v); - if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { - myMinFactorUV = A2d; - } + //Standard_Real A3d = MINABS3(Ax,Ay,Az); + //if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { + // myMinFactorXYZ = A3d; + //} + // + //Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v); + //if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { + // myMinFactorUV = A2d; + //} Standard_Boolean cut=Standard_True; Approx_ParametrizationType parametrization; @@ -332,13 +337,16 @@ void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline, nbmc++) { myBezToBSpl.Append(myComputeLineBezier.Value(nbmc)); } - if(imaxShapeInfo(aPB->OriginalEdge()).HasFlag()) { // skip degenerated edges + continue; + } // nE = aPB->Edge(); const BOPDS_ShapeInfo& aSIE = myDS->ShapeInfo(nE); @@ -2478,3 +2484,84 @@ Standard_Boolean BOPAlgo_PaveFiller::EstimatePaveOnCurve bIsVertexOnLine=myContext->IsVertexOnLine(aV, aIC, aTolR3D, aT); return bIsVertexOnLine; } + +//======================================================================= +//function : RemoveMicroSectionEdges +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::RemoveMicroSectionEdges + (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB, + BOPCol_DataMapOfIntegerListOfInteger& theDMVLV) +{ + if (theMSCPB.IsEmpty()) + // no section edges + return; + + // Get all F/F interferences + BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF(); + + // Build the new map of section edges avoiding the micro edges + BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aSEPBMap; + // Analyze all section edges + Standard_Integer aNbCPB = theMSCPB.Extent(); + for (Standard_Integer i = 1; i <= aNbCPB; ++i) + { + const TopoDS_Shape& aSI = theMSCPB.FindKey(i); + const BOPDS_CoupleOfPaveBlocks& aCPB = theMSCPB(i); + + if (aSI.ShapeType() != TopAbs_EDGE) + { + // Not an edge + aSEPBMap.Add(aSI, aCPB); + continue; + } + + // Get pave block for analysis + const Handle(BOPDS_PaveBlock)& aPB = aCPB.PaveBlock1(); + if (aPB->HasEdge()) + { + // Not a real section edge + aSEPBMap.Add(aSI, aCPB); + continue; + } + + if (!BOPTools_AlgoTools::IsMicroEdge(*(TopoDS_Edge*)&aSI, myContext)) + { + // Normal edge + aSEPBMap.Add(aSI, aCPB); + continue; + } + + // Micro edge is found + // Unify its vertices by linking its indices + Standard_Integer nV1, nV2; + aPB->Indices(nV1, nV2); + BOPCol_ListOfInteger* pList = theDMVLV.ChangeSeek(nV1); + if (!pList) + pList = theDMVLV.Bound(nV1, BOPCol_ListOfInteger()); + pList->Append(nV2); + + // Avoid the edge in the map and remove it + // from the F/F Intersection info structure + + // Get F/F interference which created this micro edge + BOPDS_InterfFF& aFF = aFFs(aCPB.IndexInterf()); + // Get curve from which this edge has been created + BOPDS_Curve& aCurve = aFF.ChangeCurves().ChangeValue(aCPB.Index()); + // Get all section pave blocks created from this curve + BOPDS_ListOfPaveBlock& aLPBC = aCurve.ChangePaveBlocks(); + // Remove pave block from the list + for (BOPDS_ListIteratorOfListOfPaveBlock it(aLPBC); it.More(); it.Next()) + { + if (it.Value() == aPB) + { + aLPBC.Remove(it); + break; + } + } + } + + // Overwrite the old map if necessary + if (aSEPBMap.Extent() != theMSCPB.Extent()) + theMSCPB = aSEPBMap; +} diff --git a/tests/bugs/modalg_7/bug29387 b/tests/bugs/modalg_7/bug29387 new file mode 100644 index 0000000000..150668ae1b --- /dev/null +++ b/tests/bugs/modalg_7/bug29387 @@ -0,0 +1,27 @@ +puts "========" +puts "OCC29387" +puts "========" +puts "" +################################################# +# Incorrect result of cut a face with several shapes +################################################# + +restore [locate_data_file bug29387_obj.brep] s +restore [locate_data_file bug29387_tools.brep] t +bclearobjects +bcleartools +baddobjects s +baddctools t +bfillds + +# perform GF operation +bbuild rgf +checkshape rgf +checknbshapes rgf -wire 289 -face 288 -shell 14 -solid 14 + +# perform CUT operation +bbop result 2 +checkshape result +checknbshapes result -wire 2 -face 1 + +set area 470.719 -- 2.39.5