From 9bf0740bed3bf7a33ed2f2c3357d458739eb9aa9 Mon Sep 17 00:00:00 2001 From: aml Date: Thu, 29 Jan 2015 15:09:51 +0300 Subject: [PATCH] 0025631: Bounding box is too big for the face. Fixed start and finish indexes of poles in case of trimmed bspline surface. Test case for issue CR25631 --- src/BndLib/BndLib_AddSurface.cxx | 206 ++++++++++++++++++++++++++----- tests/bugs/moddata_3/bug25631 | 37 ++++++ 2 files changed, 211 insertions(+), 32 deletions(-) create mode 100755 tests/bugs/moddata_3/bug25631 diff --git a/src/BndLib/BndLib_AddSurface.cxx b/src/BndLib/BndLib_AddSurface.cxx index 52a326273b..4f6b4c0fa2 100644 --- a/src/BndLib/BndLib_AddSurface.cxx +++ b/src/BndLib/BndLib_AddSurface.cxx @@ -23,10 +23,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -178,13 +181,44 @@ static void TreatInfinitePlane(const gp_Pln &aPlane, aB.Enlarge(aTol); } -// Modified by skv - Fri Aug 27 12:29:04 2004 OCC6503 End +// Compute start and finish indexes used in convex hull. +// theMinIdx - minimum poles index, that can be used. +// theMaxIdx - maximum poles index, that can be used. +// theShiftCoeff - shift between flatknots array and poles array. +// This vaule should be equal to 1 in case of non periodic BSpline, +// and (degree + 1) - mults(the lowest index). +void ComputePolesIndexes(const TColStd_Array1OfReal &theFlatKnots, + const Standard_Integer theDegree, + const Standard_Real theMin, + const Standard_Real theMax, + const Standard_Integer theMinIdx, + const Standard_Integer theMaxIdx, + const Standard_Integer theShiftCoeff, + Standard_Integer &theOutMinIdx, + Standard_Integer &theOutMaxIdx) +{ + // Compute first and last used flat knots. + for(Standard_Integer aKnotIdx = theFlatKnots.Lower(); + aKnotIdx < theFlatKnots.Upper(); + aKnotIdx++) + { + if (theFlatKnots(aKnotIdx) <= theMin) + theOutMinIdx = aKnotIdx; + + if (theFlatKnots(theFlatKnots.Upper() - aKnotIdx + theFlatKnots.Lower()) >= theMax) + theOutMaxIdx = theFlatKnots.Upper() - aKnotIdx + theFlatKnots.Lower(); + } + + theOutMinIdx = Max(theOutMinIdx - 2 * theDegree + 2 - theShiftCoeff, theMinIdx); + theOutMaxIdx = Min(theOutMaxIdx - 2 + theDegree + 1 - theShiftCoeff, theMaxIdx); +} + +// Modified by skv - Fri Aug 27 12:29:04 2004 OCC6503 End //======================================================================= //function : Add //purpose : //======================================================================= - void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, const Standard_Real UMin, const Standard_Real UMax, @@ -220,7 +254,7 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, // GeomAbs_SurfaceType Type = S.GetType(); // skv OCC6503 switch (Type) { - + case GeomAbs_Plane: { gp_Pln Plan = S.Plane(); @@ -249,12 +283,12 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, case GeomAbs_Sphere: { if (Abs(UMin) < Precision::Angular() && - Abs(UMax - 2.*M_PI) < Precision::Angular() && - Abs(VMin + M_PI/2.) < Precision::Angular() && - Abs(VMax - M_PI/2.) < Precision::Angular()) // a whole sphere - BndLib::Add(S.Sphere(),Tol,B); + Abs(UMax - 2.*M_PI) < Precision::Angular() && + Abs(VMin + M_PI/2.) < Precision::Angular() && + Abs(VMax - M_PI/2.) < Precision::Angular()) // a whole sphere + BndLib::Add(S.Sphere(),Tol,B); else - BndLib::Add(S.Sphere(),UMin,UMax,VMin,VMax,Tol,B); + BndLib::Add(S.Sphere(),UMin,UMax,VMin,VMax,Tol,B); break; } case GeomAbs_OffsetSurface: @@ -268,25 +302,133 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, case GeomAbs_BezierSurface: case GeomAbs_BSplineSurface: { + Standard_Boolean isUseConvexHullAlgorithm = Standard_True; Standard_Real PTol = Precision::Parametric(Precision::Confusion()); - if (Abs(UMin-S.FirstUParameter()) < PTol && - Abs(VMin-S.FirstVParameter()) < PTol && - Abs(UMax-S.LastUParameter ()) < PTol && - Abs(VMax-S.LastVParameter ()) < PTol ) { - TColgp_Array2OfPnt Tp(1,S.NbUPoles(),1,S.NbVPoles()); - if (Type == GeomAbs_BezierSurface) { - S.Bezier()->Poles(Tp); - } - else { - S.BSpline()->Poles(Tp); - } - for (Standard_Integer i = Tp.LowerRow();i<=Tp.UpperRow();i++) { - for (Standard_Integer j = Tp.LowerCol();j<=Tp.UpperCol();j++) { - B.Add(Tp(i,j)); - } - } - B.Enlarge(Tol); - break; + // Borders of underlying geometry. + Standard_Real anUMinParam = UMin, anUMaxParam = UMax,// BSpline case. + aVMinParam = VMin, aVMaxParam = VMax; + if (Type == GeomAbs_BezierSurface) + { + // Bezier surface: + // All of poles used for any parameter, + // thats why in case of trimmed parameters handled by grid algorithm. + + if (Abs(UMin-S.FirstUParameter()) > PTol || + Abs(VMin-S.FirstVParameter()) > PTol || + Abs(UMax-S.LastUParameter ()) > PTol || + Abs(VMax-S.LastVParameter ()) > PTol ) + { + // Borders not equal to topology borders. + isUseConvexHullAlgorithm = Standard_False; + } + } + else + { + // BSpline: + // If Umin, Vmin, Umax, Vmax lies inside geometry bounds then: + // use convex hull algorithm, + // if Umin, VMin, Umax, Vmax lies outside then: + // use grid algorithm on analytic continuation (default case). + S.BSpline()->Bounds(anUMinParam, anUMaxParam, aVMinParam, aVMaxParam); + + if ( (UMin - anUMinParam) < -PTol || + (VMin - aVMinParam) < -PTol || + (UMax - anUMaxParam) > PTol || + (VMax - aVMaxParam) > PTol ) + { + // Out of geometry borders. + isUseConvexHullAlgorithm = Standard_False; + } + } + + if (isUseConvexHullAlgorithm) + { + TColgp_Array2OfPnt Tp(1,S.NbUPoles(),1,S.NbVPoles()); + Standard_Integer UMinIdx = 0, UMaxIdx = 0; + Standard_Integer VMinIdx = 0, VMaxIdx = 0; + if (Type == GeomAbs_BezierSurface) + { + S.Bezier()->Poles(Tp); + + UMinIdx = Tp.LowerRow(); + UMaxIdx = Tp.UpperRow(); + VMinIdx = Tp.LowerCol(); + VMaxIdx = Tp.UpperCol(); + } + else + { + S.BSpline()->Poles(Tp); + + UMinIdx = Tp.LowerRow(); + UMaxIdx = Tp.UpperRow(); + VMinIdx = Tp.LowerCol(); + VMaxIdx = Tp.UpperCol(); + + if (UMin > anUMinParam || + UMax < anUMaxParam) + { + Standard_Integer anUFlatKnotsCount = S.BSpline()->NbUPoles() + S.BSpline()->UDegree() + 1; + Standard_Integer aShift = 1; + + if (S.BSpline()->IsUPeriodic()) + { + TColStd_Array1OfInteger aMults(1, S.BSpline()->NbUKnots()); + S.BSpline()->UMultiplicities(aMults); + anUFlatKnotsCount = BSplCLib::KnotSequenceLength(aMults, S.BSpline()->UDegree(), Standard_True); + + aShift = S.BSpline()->UDegree() + 1 - S.BSpline()->UMultiplicity(1); + } + + TColStd_Array1OfReal anUFlatKnots(1, anUFlatKnotsCount); + S.BSpline()->UKnotSequence(anUFlatKnots); + + ComputePolesIndexes(anUFlatKnots, + S.BSpline()->UDegree(), + UMin, UMax, + UMinIdx, UMaxIdx, // Min and Max Indexes + aShift, + UMinIdx, UMaxIdx); // the Output indexes + } + + if (VMin > aVMinParam || + VMax < aVMaxParam) + { + Standard_Integer anVFlatKnotsCount = S.BSpline()->NbVPoles() + S.BSpline()->VDegree() + 1; + Standard_Integer aShift = 1; + + if (S.BSpline()->IsVPeriodic()) + { + TColStd_Array1OfInteger aMults(1, S.BSpline()->NbVKnots()); + S.BSpline()->VMultiplicities(aMults); + anVFlatKnotsCount = BSplCLib::KnotSequenceLength(aMults, S.BSpline()->VDegree(), Standard_True); + + aShift = S.BSpline()->VDegree() + 1 - S.BSpline()->VMultiplicity(1); + } + + TColStd_Array1OfReal anVFlatKnots(1, anVFlatKnotsCount); + S.BSpline()->VKnotSequence(anVFlatKnots); + + ComputePolesIndexes(anVFlatKnots, + S.BSpline()->VDegree(), + VMin, VMax, + VMinIdx, VMaxIdx, // Min and Max Indexes + aShift, + VMinIdx, VMaxIdx); // the Output indexes + } + + } + + // Use poles to build convex hull. + for (Standard_Integer i = UMinIdx; i <= UMaxIdx; i++) + { + for (Standard_Integer j = VMinIdx; j <= VMaxIdx; j++) + { + B.Add(Tp(i,j)); + } + } + + B.Enlarge(Tol); + break; } } default: @@ -295,12 +437,12 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S, Standard_Integer Nv = NbVSamples(S); gp_Pnt P; for (Standard_Integer i =1 ;i<=Nu;i++){ - Standard_Real U = UMin + ((UMax-UMin)*(i-1)/(Nu-1)); - for (Standard_Integer j=1 ;j<=Nv;j++){ - Standard_Real V = VMin + ((VMax-VMin)*(j-1)/(Nv-1)); - S.D0(U,V,P); - B.Add(P); - } + Standard_Real U = UMin + ((UMax-UMin)*(i-1)/(Nu-1)); + for (Standard_Integer j=1 ;j<=Nv;j++){ + Standard_Real V = VMin + ((VMax-VMin)*(j-1)/(Nv-1)); + S.D0(U,V,P); + B.Add(P); + } } B.Enlarge(Tol); } diff --git a/tests/bugs/moddata_3/bug25631 b/tests/bugs/moddata_3/bug25631 new file mode 100755 index 0000000000..2fc93b29bc --- /dev/null +++ b/tests/bugs/moddata_3/bug25631 @@ -0,0 +1,37 @@ +puts "=========" +puts "OCC25631" +puts "=========" +puts "" +##################################################################### +## Bounding box is too big for the face. +##################################################################### + +restore [locate_data_file bug25631_fbx.brep] sh1 + +set rr [bounding sh1] +regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $rr full v1_x v1_y v1_z v2_x v2_y v2_z + +set tol_abs 1.0e-4 +set tol_rel 0.0001 + +set expected_v1_x 102.04999989999993 +checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel} + +set expected_v1_y -12.576503364721431 +checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel} + +set expected_v1_z -12.267407382031644 +checkreal "v1_z" ${v1_z} ${expected_v1_z} ${tol_abs} ${tol_rel} + +set expected_v2_x 145.65000009999983 +checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel} + +set expected_v2_y 1.0883692081680807 +checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel} + +set expected_v2_z 1.4146362604116396 +checkreal "v2_z" ${v2_z} ${expected_v2_z} ${tol_abs} ${tol_rel} + +smallview +fit +set only_screen_axo 1 -- 2.20.1