0025631: Bounding box is too big for the face.
authoraml <aml@opencascade.com>
Thu, 29 Jan 2015 12:09:51 +0000 (15:09 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 29 Jan 2015 12:10:41 +0000 (15:10 +0300)
Fixed start and finish indexes of poles in case of trimmed bspline surface.

Test case for issue CR25631

src/BndLib/BndLib_AddSurface.cxx
tests/bugs/moddata_3/bug25631 [new file with mode: 0755]

index 52a3262..4f6b4c0 100644 (file)
 #include <Adaptor3d_HSurface.hxx>
 #include <GeomAbs_SurfaceType.hxx>
 #include <BndLib.hxx>
+#include <BSplCLib.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Pln.hxx>
 #include <ElSLib.hxx>
 #include <TColgp_Array2OfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfInteger.hxx>
 #include <Geom_BSplineSurface.hxx>
 #include <Geom_BezierSurface.hxx>
 
@@ -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 (executable)
index 0000000..2fc93b2
--- /dev/null
@@ -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