0030270: Modeling Algorithms - BRepBndLib should provide an option for skipping infin...
authorkgv <kgv@opencascade.com>
Tue, 23 Oct 2018 14:39:36 +0000 (17:39 +0300)
committerapn <apn@opencascade.com>
Wed, 24 Oct 2018 19:53:26 +0000 (22:53 +0300)
Bnd_Box now keeps calculating of finite part of bounding box after specifying it to be Open in some direction.
The finite part can be retrieved using new method Bnd_Box::FinitePart().

Prs3d::GetDeflection() now uses Bnd_Box::FinitePart() when applying relative deflection.

Draw Harness command bounding has been extended with option -finite returing a finite part of AABB.

src/BRepTest/BRepTest_BasicCommands.cxx
src/Bnd/Bnd_Box.cxx
src/Bnd/Bnd_Box.hxx
src/BndLib/BndLib.cxx
src/Prs3d/Prs3d.cxx
tests/bugs/modalg_7/bug30270 [new file with mode: 0644]

index 69f7d1f..7e7b36a 100644 (file)
@@ -503,6 +503,7 @@ static Standard_Integer BoundBox(Draw_Interpretor& theDI,
   Standard_Boolean isTriangulationReq = Standard_True;
   Standard_Boolean isOptimal = Standard_False;
   Standard_Boolean isTolerUsed = Standard_False;
+  Standard_Boolean isFinitePart = Standard_False;
   Standard_Boolean hasToDraw = Standard_True;
   
   TCollection_AsciiString anOutVars[6];
@@ -557,6 +558,11 @@ static Standard_Integer BoundBox(Draw_Interpretor& theDI,
     {
       hasToDraw = Standard_False;
     }
+    else if (anArgCase == "-finite"
+          || anArgCase == "-finitepart")
+    {
+      isFinitePart = Standard_True;
+    }
     else if (aShape.IsNull()
          && !DBRep::Get (theArgVal[anArgIter]).IsNull())
     {
@@ -662,6 +668,10 @@ static Standard_Integer BoundBox(Draw_Interpretor& theDI,
     }
     else
     {
+      if (isFinitePart && anAABB.IsOpen())
+      {
+        anAABB = anAABB.FinitePart();
+      }
       const gp_Pnt aMin = anAABB.CornerMin();
       const gp_Pnt aMax = anAABB.CornerMax();
 
@@ -670,15 +680,26 @@ static Standard_Integer BoundBox(Draw_Interpretor& theDI,
       {
         if (useOldSyntax)
         {
-          theDI << aMin.X () << " " << aMin.Y () << " " << aMin.Z () << " "
-                << aMax.X () << " " << aMax.Y () << " " << aMax.Z () << "\n";
+          theDI << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
+                << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
         }
         else
         {
           theDI << "Axes-aligned bounding box\n";
-          theDI << "X-range: " << aMin.X () << " " << aMax.X () << "\n" <<
-                   "Y-range: " << aMin.Y() << " " << aMax.Y() << "\n" <<
-                   "Z-range: " << aMin.Z () << " " << aMax.Z () << "\n";
+          theDI << "X-range: " << aMin.X() << " " << aMax.X() << "\n"
+                << "Y-range: " << aMin.Y() << " " << aMax.Y() << "\n"
+                << "Z-range: " << aMin.Z() << " " << aMax.Z() << "\n";
+          if (anAABB.IsOpen()
+           && anAABB.HasFinitePart())
+          {
+            Bnd_Box aFinitAabb = anAABB.FinitePart();
+            const gp_Pnt aFinMin = aFinitAabb.CornerMin();
+            const gp_Pnt aFinMax = aFinitAabb.CornerMax();
+            theDI << "Finite part\n";
+            theDI << "X-range: " << aFinMin.X() << " " << aFinMax.X() << "\n"
+                  << "Y-range: " << aFinMin.Y() << " " << aFinMax.Y() << "\n"
+                  << "Z-range: " << aFinMin.Z() << " " << aFinMax.Z() << "\n";
+          }
         }
       }
 
@@ -1454,7 +1475,7 @@ void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
   theCommands.Add ("bounding",
                    "bounding {shape | xmin ymin zmin xmax ymax zmax}"
          "\n\t\t:            [-obb] [-noTriangulation] [-optimal] [-extToler]"
-         "\n\t\t:            [-dump] [-shape name] [-nodraw]"
+         "\n\t\t:            [-dump] [-shape name] [-nodraw] [-finitePart]"
          "\n\t\t:            [-save xmin ymin zmin xmax ymax zmax]"
          "\n\t\t:"
          "\n\t\t: Computes a bounding box. Two types of the source data are supported:"
@@ -1474,7 +1495,8 @@ void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
          "\n\t\t:           if neither -shape nor -save is specified."
          "\n\t\t:  -shape   Stores computed box as solid in DRAW variable with specified name."
          "\n\t\t:  -save    Stores min and max coordinates of AABB in specified variables."
-         "\n\t\t:  -noDraw  Avoid drawing resulting Bounding Box in DRAW viewer.",
+         "\n\t\t:  -noDraw  Avoid drawing resulting Bounding Box in DRAW viewer."
+         "\n\t\t:  -finite  Return finite part of infinite box.",
                   __FILE__, BoundBox, g);
 
  //
index 62451ef..3f9ea99 100644 (file)
 //function : Bnd_Box
 //purpose  : 
 //=======================================================================
-
 Bnd_Box::Bnd_Box()
-     : Xmin(0.), Xmax(0.), Ymin(0.), Ymax(0.),  Zmin(0.), Zmax(0.), Gap(0.)
+: Xmin (RealLast()), Xmax (-RealLast()),
+  Ymin (RealLast()), Ymax (-RealLast()),
+  Zmin (RealLast()), Zmax (-RealLast()),
+  Gap (0.0)
 {
   SetVoid();
 }
@@ -86,13 +88,14 @@ void Bnd_Box::Update (const Standard_Real x,
     Zmax = Z;
     ClearVoidFlag();
   }
-  else {
-    if (!IsOpenXmin() && (x < Xmin)) Xmin = x;
-    if (!IsOpenXmax() && (X > Xmax)) Xmax = X;
-    if (!IsOpenYmin() && (y < Ymin)) Ymin = y;
-    if (!IsOpenYmax() && (Y > Ymax)) Ymax = Y;
-    if (!IsOpenZmin() && (z < Zmin)) Zmin = z;
-    if (!IsOpenZmax() && (Z > Zmax)) Zmax = Z;
+  else
+  {
+    if (x < Xmin) Xmin = x;
+    if (X > Xmax) Xmax = X;
+    if (y < Ymin) Ymin = y;
+    if (Y > Ymax) Ymax = Y;
+    if (z < Zmin) Zmin = z;
+    if (Z > Zmax) Zmax = Z;
   }
 }
 
@@ -116,12 +119,12 @@ void Bnd_Box::Update (const Standard_Real X,
     ClearVoidFlag();
   }
   else {
-    if      (!IsOpenXmin() && (X < Xmin)) Xmin = X;
-    else if (!IsOpenXmax() && (X > Xmax)) Xmax = X;
-    if      (!IsOpenYmin() && (Y < Ymin)) Ymin = Y;
-    else if (!IsOpenYmax() && (Y > Ymax)) Ymax = Y;
-    if      (!IsOpenZmin() && (Z < Zmin)) Zmin = Z;
-    else if (!IsOpenZmax() && (Z > Zmax)) Zmax = Z;
+    if      (X < Xmin) Xmin = X;
+    else if (X > Xmax) Xmax = X;
+    if      (Y < Ymin) Ymin = Y;
+    else if (Y > Ymax) Ymax = Y;
+    if      (Z < Zmin) Zmin = Z;
+    else if (Z > Zmax) Zmax = Z;
   }
 }
 
@@ -293,89 +296,92 @@ Standard_Boolean Bnd_Box::IsThin (const Standard_Real tol) const
 
 Bnd_Box Bnd_Box::Transformed (const gp_Trsf& T) const
 {
-  gp_TrsfForm F = T.Form();
-  Bnd_Box newb(*this);
-  if ( IsVoid() ) return newb;
-
-  if      (F == gp_Identity) {}
-  else if (F == gp_Translation) {
-    Standard_Real DX,DY,DZ;
-    (T.TranslationPart()).Coord(DX,DY,DZ);
-    if (!IsOpenXmin()) newb.Xmin += DX;
-    if (!IsOpenXmax()) newb.Xmax += DX;
-    if (!IsOpenYmin()) newb.Ymin += DY;
-    if (!IsOpenYmax()) newb.Ymax += DY;
-    if (!IsOpenZmin()) newb.Zmin += DZ;
-    if (!IsOpenZmax()) newb.Zmax += DZ;
+  if (IsVoid())
+  {
+    return Bnd_Box();
   }
-  else {
-    gp_Pnt P[8];
-    Standard_Boolean Vertex[8];
-    Standard_Integer i;
-    for (i=0;i<8;i++) Vertex[i] = Standard_True;
-    gp_Dir D[6];
-//    Standard_Integer vertices = 0;
-    Standard_Integer directions = 0;
-
-    if (IsOpenXmin())
-    {
-      directions++;
-      D[directions-1].SetCoord(-1., 0., 0.);
-      Vertex[0] = Vertex[2] = Vertex[4] = Vertex[6] = Standard_False;
-    }
-    if (IsOpenXmax())
-    {
-      directions++;
-      D[directions-1].SetCoord( 1., 0., 0.);
-      Vertex[1] = Vertex[3] = Vertex[5] = Vertex[7] = Standard_False;
-    }
-    if (IsOpenYmin())
-    {
-      directions++;
-      D[directions-1].SetCoord( 0.,-1., 0.);
-      Vertex[0] = Vertex[1] = Vertex[4] = Vertex[5] = Standard_False;
-    }
-    if (IsOpenYmax())
+  else if (T.Form() == gp_Identity)
+  {
+    return *this;
+  }
+  else if (T.Form() == gp_Translation)
+  {
+    if (!HasFinitePart())
     {
-      directions++;
-      D[directions-1].SetCoord( 0., 1., 0.);
-      Vertex[2] = Vertex[3] = Vertex[6] = Vertex[7] = Standard_False;
+      return *this;
     }
-    if (IsOpenZmin())
+
+    const gp_XYZ& aDelta = T.TranslationPart();
+    Bnd_Box aNewBox (*this);
+    aNewBox.Xmin += aDelta.X();
+    aNewBox.Xmax += aDelta.X();
+    aNewBox.Ymin += aDelta.Y();
+    aNewBox.Ymax += aDelta.Y();
+    aNewBox.Zmin += aDelta.Z();
+    aNewBox.Zmax += aDelta.Z();
+    return aNewBox;
+  }
+
+  Bnd_Box aNewBox;
+  if (HasFinitePart())
+  {
+    gp_Pnt aCorners[8] =
     {
-      directions++;
-      D[directions-1].SetCoord( 0., 0.,-1.);
-      Vertex[0] = Vertex[1] = Vertex[2] = Vertex[3] = Standard_False;
-    }
-    if (IsOpenZmax())
+      gp_Pnt (Xmin, Ymin, Zmin),
+      gp_Pnt (Xmax, Ymin, Zmin),
+      gp_Pnt (Xmin, Ymax, Zmin),
+      gp_Pnt (Xmax, Ymax, Zmin),
+      gp_Pnt (Xmin, Ymin, Zmax),
+      gp_Pnt (Xmax, Ymin, Zmax),
+      gp_Pnt (Xmin, Ymax, Zmax),
+      gp_Pnt (Xmax, Ymax, Zmax),
+    };
+    for (Standard_Integer aCornerIter = 0; aCornerIter < 8; ++aCornerIter)
     {
-      directions++;
-      D[directions-1].SetCoord( 0., 0., 1.);
-      Vertex[4] = Vertex[5] = Vertex[6] = Vertex[7] = Standard_False;
+      aCorners[aCornerIter].Transform (T);
+      aNewBox.Add (aCorners[aCornerIter]);
     }
+  }
+  aNewBox.Gap = Gap;
+  if (!IsOpen())
+  {
+    return aNewBox;
+  }
 
-    newb.SetVoid();
-    for (i=0;i<directions;i++) {
-      D[i].Transform(T);
-      newb.Add(D[i]);
-    }
-    P[0].SetCoord(Xmin,Ymin,Zmin);
-    P[1].SetCoord(Xmax,Ymin,Zmin);
-    P[2].SetCoord(Xmin,Ymax,Zmin);
-    P[3].SetCoord(Xmax,Ymax,Zmin);
-    P[4].SetCoord(Xmin,Ymin,Zmax);
-    P[5].SetCoord(Xmax,Ymin,Zmax);
-    P[6].SetCoord(Xmin,Ymax,Zmax);
-    P[7].SetCoord(Xmax,Ymax,Zmax);
-    for (i=0;i<8;i++) {
-      if (Vertex[i]) {
-       P[i].Transform(T);
-       newb.Add(P[i]);
-      }
-    }
-    newb.Gap=Gap;
+  gp_Dir aDirs[6];
+  Standard_Integer aNbDirs = 0;
+  if (IsOpenXmin())
+  {
+    aDirs[aNbDirs++].SetCoord(-1., 0., 0.);
+  }
+  if (IsOpenXmax())
+  {
+    aDirs[aNbDirs++].SetCoord( 1., 0., 0.);
+  }
+  if (IsOpenYmin())
+  {
+    aDirs[aNbDirs++].SetCoord( 0.,-1., 0.);
   }
-  return newb;
+  if (IsOpenYmax())
+  {
+    aDirs[aNbDirs++].SetCoord( 0., 1., 0.);
+  }
+  if (IsOpenZmin())
+  {
+    aDirs[aNbDirs++].SetCoord( 0., 0.,-1.);
+  }
+  if (IsOpenZmax())
+  {
+    aDirs[aNbDirs++].SetCoord( 0., 0., 1.);
+  }
+
+  for (Standard_Integer aDirIter = 0; aDirIter < aNbDirs; ++aDirIter)
+  {
+    aDirs[aDirIter].Transform (T);
+    aNewBox.Add (aDirs[aDirIter]);
+  }
+
+  return aNewBox;
 }
 
 //=======================================================================
@@ -385,44 +391,40 @@ Bnd_Box Bnd_Box::Transformed (const gp_Trsf& T) const
 
 void Bnd_Box::Add (const Bnd_Box& Other)
 {
-  if (IsWhole()) return;
-  else if (Other.IsVoid()) return; 
-  else if (Other.IsWhole()) SetWhole();
-  else if (IsVoid()) (*this) = Other;
-  else
+  if (Other.IsVoid())
   {
-    if ( ! IsOpenXmin() )
-    {
-      if (Other.IsOpenXmin()) OpenXmin();
-      else if (Xmin > Other.Xmin) Xmin = Other.Xmin;
-    }
-    if ( ! IsOpenXmax() )
-    {
-      if (Other.IsOpenXmax()) OpenXmax();
-      else if (Xmax < Other.Xmax) Xmax = Other.Xmax;
-    }
-    if ( ! IsOpenYmin() )
-    {
-      if (Other.IsOpenYmin()) OpenYmin();
-      else if (Ymin > Other.Ymin) Ymin = Other.Ymin;
-    }
-    if ( ! IsOpenYmax() )
-    {
-      if (Other.IsOpenYmax()) OpenYmax();
-      else if (Ymax < Other.Ymax) Ymax = Other.Ymax;
-    }
-    if ( ! IsOpenZmin() )
-    {
-      if (Other.IsOpenZmin()) OpenZmin();
-      else if (Zmin > Other.Zmin) Zmin = Other.Zmin;
-    }
-    if ( ! IsOpenZmax() )
-    {
-      if (Other.IsOpenZmax()) OpenZmax();
-      else if (Zmax < Other.Zmax) Zmax = Other.Zmax;
-    }
-    Gap = Max (Gap, Other.Gap);
+    return;
+  }
+  else if (IsVoid())
+  {
+    *this = Other;
+    return;
+  }
+
+  if (Xmin > Other.Xmin) Xmin = Other.Xmin;
+  if (Xmax < Other.Xmax) Xmax = Other.Xmax;
+  if (Ymin > Other.Ymin) Ymin = Other.Ymin;
+  if (Ymax < Other.Ymax) Ymax = Other.Ymax;
+  if (Zmin > Other.Zmin) Zmin = Other.Zmin;
+  if (Zmax < Other.Zmax) Zmax = Other.Zmax;
+  Gap = Max (Gap, Other.Gap);
+
+  if (IsWhole())
+  {
+    return;
+  }
+  else if (Other.IsWhole())
+  {
+    SetWhole();
+    return;
   }
+
+  if (Other.IsOpenXmin()) OpenXmin();
+  if (Other.IsOpenXmax()) OpenXmax();
+  if (Other.IsOpenYmin()) OpenYmin();
+  if (Other.IsOpenYmax()) OpenYmax();
+  if (Other.IsOpenZmin()) OpenZmin();
+  if (Other.IsOpenZmax()) OpenZmax();
 }
 
 //=======================================================================
index 06e198c..301d9ad 100644 (file)
@@ -76,6 +76,12 @@ public:
   //! Sets this bounding box so that it is empty. All points are outside a void box.
   void SetVoid()
   {
+    Xmin =  RealLast();
+    Xmax = -RealLast();
+    Ymin =  RealLast();
+    Ymax = -RealLast();
+    Zmin =  RealLast();
+    Zmax = -RealLast();
     Flags = VoidMask;
     Gap   = 0.0;
   }
@@ -161,6 +167,9 @@ public:
   //! direction.
   void OpenZmax() { Flags |= ZmaxMask; }
 
+  //! Returns true if this bounding box has at least one open direction.
+  Standard_Boolean IsOpen() const { return (Flags & WholeMask) != 0; }
+
   //! Returns true if this bounding box is open in the  Xmin direction.
   Standard_Boolean IsOpenXmin() const { return (Flags & XminMask) != 0; }
 
@@ -264,6 +273,29 @@ public:
     return aDx * aDx + aDy * aDy + aDz * aDz;
   }
 
+  //! Returns a finite part of an infinite bounding box (returns self if this is already finite box).
+  //! This can be a Void box in case if its sides has been defined as infinite (Open) without adding any finite points.
+  //! WARNING! This method relies on Open flags, the infinite points added using Add() method will be returned as is.
+  Bnd_Box FinitePart() const
+  {
+    if (!HasFinitePart())
+    {
+      return Bnd_Box();
+    }
+
+    Bnd_Box aBox;
+    aBox.Update (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+    aBox.SetGap (Gap);
+    return aBox;
+  }
+
+  //! Returns TRUE if this box has finite part.
+  Standard_Boolean HasFinitePart() const
+  {
+    return !IsVoid()
+         && Xmax >= Xmin;
+  }
+
 protected:
 
   //! Bit flags.
index 5b67936..18e1b39 100644 (file)
@@ -518,7 +518,7 @@ void BndLib::Add(const gp_Circ& C,
     P = ElCLib::CircleValue(utrim2, pos, R);
     B.Add(P);
     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
-    B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+    B.FinitePart().Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
     Standard_Real gap = B.GetGap();
     Xmin += gap;
     Ymin += gap;
@@ -703,7 +703,7 @@ void BndLib::Add(const gp_Elips& C,
     P = ElCLib::EllipseValue(utrim2, pos, MajR, MinR);
     B.Add(P);
     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
-    B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+    B.FinitePart().Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
     Standard_Real gap = B.GetGap();
     Xmin += gap;
     Ymin += gap;
index 54b7869..33f33fe 100644 (file)
@@ -62,24 +62,34 @@ Standard_Boolean Prs3d::MatchSegment
 Standard_Real Prs3d::GetDeflection (const TopoDS_Shape&         theShape,
                                     const Handle(Prs3d_Drawer)& theDrawer)
 {
-#define MAX2(X, Y)    (Abs(X) > Abs(Y) ? Abs(X) : Abs(Y))
-#define MAX3(X, Y, Z) (MAX2 (MAX2 (X, Y), Z))
+  if (theDrawer->TypeOfDeflection() != Aspect_TOD_RELATIVE)
+  {
+    return theDrawer->MaximalChordialDeviation();
+  }
 
-  Standard_Real aDeflection = theDrawer->MaximalChordialDeviation();
-  if (theDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE)
+  Bnd_Box aBndBox;
+  BRepBndLib::Add (theShape, aBndBox, Standard_False);
+  if (aBndBox.IsVoid())
+  {
+    return theDrawer->MaximalChordialDeviation();
+  }
+  else if (aBndBox.IsOpen())
   {
-    Bnd_Box aBndBox;
-    BRepBndLib::Add (theShape, aBndBox, Standard_False);
-    if (!aBndBox.IsVoid())
+    if (!aBndBox.HasFinitePart())
     {
-      Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
-      aBndBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
-      aDeflection = MAX3 (aXmax-aXmin, aYmax-aYmin, aZmax-aZmin) * theDrawer->DeviationCoefficient() * 4.0;
-      // we store computed relative deflection of shape as absolute deviation coefficient
-      // in case relative type to use it later on for sub-shapes.
-      theDrawer->SetMaximalChordialDeviation (aDeflection);
+      return theDrawer->MaximalChordialDeviation();
     }
+    aBndBox = aBndBox.FinitePart();
   }
+
+  Graphic3d_Vec3d aVecMin, aVecMax;
+  aBndBox.Get (aVecMin.x(), aVecMin.y(), aVecMin.z(), aVecMax.x(), aVecMax.y(), aVecMax.z());
+  const Graphic3d_Vec3d aDiag = aVecMax - aVecMin;
+  const Standard_Real aDeflection = aDiag.maxComp() * theDrawer->DeviationCoefficient() * 4.0;
+
+  // we store computed relative deflection of shape as absolute deviation coefficient
+  // in case relative type to use it later on for sub-shapes.
+  theDrawer->SetMaximalChordialDeviation (aDeflection);
   return aDeflection;
 }
 
diff --git a/tests/bugs/modalg_7/bug30270 b/tests/bugs/modalg_7/bug30270
new file mode 100644 (file)
index 0000000..a722927
--- /dev/null
@@ -0,0 +1,15 @@
+puts "========"
+puts "0030270: Modeling Algorithms - BRepBndLib should provide an option for skipping infinite entities"
+puts "========"
+puts ""
+
+pload MODELING VISUALIZATION
+restore [locate_data_file bug27448_b1255.brep] s
+bounding s -print
+bounding s -finite -shape b
+smallview
+donly b
+fit
+display s
+
+xwd ${imagedir}/${casename}.png