0027352: Optimal axis-aligned bounding box for a shape
authorifv <ifv@opencascade.com>
Tue, 26 Apr 2016 12:00:29 +0000 (15:00 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 1 Jul 2016 09:40:40 +0000 (12:40 +0300)
Add method for exact calculation of bounding boxes

Modifications made according to remarks.

Small correction of test case for issue CR27352

Small correction of test cases for issue CR27352

Avoid warning on VS2015

19 files changed:
src/BOPAlgo/BOPAlgo_WireSplitter_1.cxx
src/BRepBndLib/BRepBndLib.cxx
src/BRepBndLib/BRepBndLib.hxx
src/BRepTest/BRepTest_BasicCommands.cxx
src/BndLib/BndLib.cxx
src/BndLib/BndLib_Add2dCurve.cxx
src/BndLib/BndLib_Add2dCurve.hxx
src/BndLib/BndLib_Add3dCurve.cxx
src/BndLib/BndLib_Add3dCurve.hxx
src/BndLib/BndLib_AddSurface.cxx
src/BndLib/BndLib_AddSurface.hxx
tests/boolean/volumemaker/A8
tests/boolean/volumemaker/E4
tests/boolean/volumemaker/E6
tests/boolean/volumemaker/H4
tests/bugs/modalg_2/bug264_7
tests/bugs/modalg_2/bug291
tests/bugs/step/bug24595
tests/bugs/vis/bug23012

index 2147bec..316f596 100644 (file)
@@ -48,6 +48,7 @@
 #include <TopoDS_Vertex.hxx>
 #include <TopoDS_Wire.hxx>
 #include <TopTools_ShapeMapHasher.hxx>
+#include <Geom2dLProp_CLProps2d.hxx>
 typedef NCollection_DataMap \
   <TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> \
   BOPCol_DataMapOfShapeBoolean; 
@@ -292,7 +293,6 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
   for (i=1; i<=aNb; i++) {
     const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&mySmartMap.FindKey(i))); 
     const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
-
     aItLEI.Initialize(aLEI);
     for (; aItLEI.More(); aItLEI.Next()) {
       BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
@@ -365,6 +365,7 @@ void Path (const GeomAdaptor_Surface& aGAS,
   TopoDS_Vertex aVa, aVb;
   TopoDS_Edge aEOuta;
   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
+  Standard_Real eps = Epsilon(1.);
   //
   aVa = aVFirst;
   aEOuta = aEFirst;
@@ -536,7 +537,7 @@ void Path (const GeomAdaptor_Surface& aGAS,
           anAngleOut=anEI.Angle();
           anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
         }
-        if (anAngle < aMinAngle) {
+        if (anAngle < aMinAngle - eps) {
           aMinAngle=anAngle;
           pEdgeInfo=&anEI;
           anIsFound=Standard_True;
@@ -725,10 +726,30 @@ Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
   //
   BOPTools_AlgoTools2D::CurveOnSurface (anEdge, myFace, aC2D, 
                                         aFirst, aLast, aToler);
-  dt=2.*Tolerance2D(aV, aGAS);
+  Standard_Real tol2d =2.*Tolerance2D(aV, aGAS);
+  //
+  GeomAbs_CurveType aType;
+  Geom2dAdaptor_Curve aGAC2D(aC2D);
+  //
+  dt = Max(aGAC2D.Resolution(tol2d), Precision::PConfusion());
   //
+  aType=aGAC2D.GetType();
+  if (aType != GeomAbs_Line ) 
+  {
+    Geom2dLProp_CLProps2d LProp(aC2D,  aTV, 2, Precision::PConfusion());
+    if(LProp.IsTangentDefined())
+    {
+      Standard_Real R = LProp.Curvature();
+      if(R > Precision::PConfusion())
+      {
+        R = 1./R;
+        Standard_Real cosphi = R / (R + tol2d);
+        dt = Max(dt, ACos(cosphi)); //to avoid small dt for big R.
+      }
+    }
+  }
   //for case chl/927/r9
-  aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
+  aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);  
   if (aTX < 5.e-5) {
     aTX = 5.e-5;
   }
@@ -737,14 +758,7 @@ Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
     // in the case of big tolerances
     dt = aTX; 
   }
-  //
-  GeomAbs_CurveType aType;
-  Geom2dAdaptor_Curve aGAC2D(aC2D);
-  aType=aGAC2D.GetType();
-  if (aType==GeomAbs_BSplineCurve || 
-      aType==GeomAbs_BezierCurve) {
-    dt=1.1*dt;
-  }
+
   if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
     aTV1=aTV + dt;
   }
@@ -752,25 +766,10 @@ Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
     aTV1=aTV - dt;
   }
   //
-  if (aType==GeomAbs_Circle) {
-    Standard_Real aTM;
-    TopAbs_Orientation aOrE;
-    gp_Pnt2d aPM;
-    //
-    aTM=0.5*(aTV1+aTV);
-    //
-    aGAC2D.D1(aTM, aPM, aV2D);
-    aOrE=anEdge.Orientation();
-    if (aOrE==TopAbs_REVERSED) {
-      aV2D.Reverse();
-    }
-  }
-  else {
-    aGAC2D.D0 (aTV1, aPV1);
-    aGAC2D.D0 (aTV, aPV);
-    //
-    aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
-  }
+  aGAC2D.D0 (aTV1, aPV1);
+  aGAC2D.D0 (aTV, aPV);
+  //
+  aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
   //
   gp_Dir2d aDir2D(aV2D);
   anAngle=Angle(aDir2D);
index 62ecfe3..6e3f6e2 100644 (file)
 #include <TopLoc_Location.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Shape.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
+#include <BRepTools.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BndLib_Add2dCurve.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
+#include <ElSLib.hxx>
+#include <ElCLib.hxx>
+#include <Geom_Plane.hxx>
+#include <Extrema_ExtSS.hxx>
+#include <GeomAdaptor_Surface.hxx>
+//
+static Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS);
+//
+static void FindExactUVBounds(const TopoDS_Face F, 
+                              Standard_Real& umin, Standard_Real& umax, 
+                              Standard_Real& vmin, Standard_Real& vmax,
+                              const Standard_Real Tol, 
+                              Standard_Boolean& isNaturalRestriction);
+//
+static void AdjustFaceBox(const BRepAdaptor_Surface& BS, 
+                          const Standard_Real umin, const Standard_Real umax, 
+                          const Standard_Real vmin, const Standard_Real vmax,
+                          Bnd_Box& FaceBox,
+                          const Bnd_Box& EdgeBox, const Standard_Real Tol);
+//
+static Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, 
+                                     const gp_Pln& thePln, const gp_Pnt& theP,
+                                     const Standard_Real umin, const Standard_Real umax,
+                                     const Standard_Real vmin, const Standard_Real vmax,
+                                     const BRepTopAdaptor_FClass2d& theFClass,
+                                     const Standard_Real theTolU, const Standard_Real theTolV);
 
+//
 //=======================================================================
 //function : Add
 //purpose  : Add a shape bounding to a box
@@ -175,3 +210,582 @@ void BRepBndLib::AddClose(const TopoDS_Shape& S, Bnd_Box& B)
   }
 }
 
+//=======================================================================
+//function : AddOptimal
+//purpose  : Add a shape bounding to a box
+//=======================================================================
+void BRepBndLib::AddOptimal(const TopoDS_Shape& S, Bnd_Box& B, 
+                            const Standard_Boolean useTriangulation, 
+                            const Standard_Boolean useShapeTolerance)
+{
+  TopExp_Explorer ex;
+
+  // Add the faces
+  BRepAdaptor_Surface BS;
+  Handle(Poly_Triangulation) T;
+  TopLoc_Location l;
+  Standard_Integer i, nbNodes;
+  BRepAdaptor_Curve BC;
+
+  for (ex.Init(S,TopAbs_FACE); ex.More(); ex.Next()) {
+    const TopoDS_Face& F = TopoDS::Face(ex.Current());
+    T = BRep_Tool::Triangulation(F, l);
+    Bnd_Box aLocBox;
+    if (useTriangulation && !T.IsNull())
+    {
+      nbNodes = T->NbNodes();
+      const TColgp_Array1OfPnt& Nodes = T->Nodes();
+      for (i = 1; i <= nbNodes; i++) {
+        if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+        else aLocBox.Add(Nodes(i).Transformed(l));
+      }
+      //       B.Enlarge(T->Deflection());
+      aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
+      Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+      aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+      B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+    } 
+    else
+    {
+      const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l);
+      if (!GS.IsNull()) {
+        BS.Initialize(F, Standard_False);
+        if (CanUseEdges(BS)) {
+          TopExp_Explorer ex2(F, TopAbs_EDGE);
+          if (!ex2.More()) {
+            BS.Initialize(F);
+            Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
+            BndLib_AddSurface::AddOptimal(BS, Tol, aLocBox);
+          }
+          else
+          {
+            Standard_Real Tol;
+            for (;ex2.More();ex2.Next()) {
+              Bnd_Box anEBox;
+              const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+              if(BRep_Tool::Degenerated(anE))
+              {
+                continue;
+              }
+              BC.Initialize(anE);
+              Tol = useShapeTolerance?  BRep_Tool::Tolerance(anE) : 0.;
+              BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+              aLocBox.Add(anEBox);
+            }
+          }
+        }
+        else
+        {
+          Standard_Real umin, umax, vmin, vmax;
+          Standard_Boolean isNaturalRestriction = Standard_False;
+          Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
+          FindExactUVBounds(F, umin, umax, vmin, vmax, Tol, isNaturalRestriction);
+          BndLib_AddSurface::AddOptimal(BS, umin, umax, vmin, vmax, 
+                                        Tol, aLocBox);
+          //
+          if(!isNaturalRestriction)
+          {
+            TopExp_Explorer ex2(F, TopAbs_EDGE);
+            Bnd_Box EBox;
+            for (;ex2.More();ex2.Next()) {
+              Bnd_Box anEBox;
+              const TopoDS_Edge& anE = TopoDS::Edge(ex2.Current());
+              if(BRep_Tool::Degenerated(anE))
+              {
+                continue;
+              }
+              BC.Initialize(anE);
+              Tol = useShapeTolerance?  BRep_Tool::Tolerance(anE) : 0.;
+              BndLib_Add3dCurve::AddOptimal(BC, Tol, anEBox);
+              EBox.Add(anEBox);
+            }
+            Tol = useShapeTolerance?  BRep_Tool::Tolerance(F) : 0.;
+            AdjustFaceBox(BS, umin, umax, vmin, vmax, aLocBox, EBox, 
+                          Tol);
+          }
+        }
+        Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+        aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+        B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+      }
+    }
+  }
+
+  // Add the edges not in faces
+  Handle(TColStd_HArray1OfInteger) HIndices;
+  Handle(Poly_PolygonOnTriangulation) Poly;
+
+  for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE); ex.More(); ex.Next())
+  {
+    const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
+    Bnd_Box aLocBox;
+    Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
+    if (useTriangulation && (!P3d.IsNull()))
+    {
+      const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
+      nbNodes = P3d->NbNodes();
+      for (i = 1; i <= nbNodes; i++)
+      {
+        if (l.IsIdentity()) aLocBox.Add(Nodes(i));
+        else aLocBox.Add(Nodes(i).Transformed(l));
+      }
+      Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
+      aLocBox.Enlarge(P3d->Deflection() + Tol);
+    }
+    else
+    {
+      BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
+      if (useTriangulation && !Poly.IsNull())
+      {
+        const TColStd_Array1OfInteger& Indices = Poly->Nodes();
+        const TColgp_Array1OfPnt& Nodes = T->Nodes();
+        nbNodes = Indices.Length();
+        for (i = 1; i <= nbNodes; i++)
+        {
+          if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i)));
+          else aLocBox.Add(Nodes(Indices(i)).Transformed(l));
+        }
+        Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
+        aLocBox.Enlarge(Poly->Deflection() + Tol);
+      }
+      else {
+        if (BRep_Tool::IsGeometric(E))
+        {
+          BC.Initialize(E);
+          Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(E) : 0.;
+          BndLib_Add3dCurve::AddOptimal(BC, Tol, aLocBox);
+        }
+      }
+    }
+    if (!aLocBox.IsVoid())
+    {
+      Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+      aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+      B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+    }
+  }
+
+  // Add the vertices not in edges
+
+  for (ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ex.More(); ex.Next()) {
+    Bnd_Box aLocBox;
+    const TopoDS_Vertex& aV = TopoDS::Vertex(ex.Current());
+    aLocBox.Add(BRep_Tool::Pnt(aV));
+    Standard_Real Tol = useShapeTolerance?  BRep_Tool::Tolerance(aV) : 0.;
+    aLocBox.Enlarge(Tol);
+    Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+    aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
+    B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+  }
+}
+
+//=======================================================================
+//function : CanUseEdges
+//purpose  : Define is it possible using only edges bnd boxes 
+//           to get face bnd box
+//=======================================================================
+Standard_Boolean CanUseEdges(const Adaptor3d_Surface& BS)
+{
+  GeomAbs_SurfaceType aST = BS.GetType();
+  if(aST == GeomAbs_Plane ||
+     aST == GeomAbs_Cylinder ||
+     aST == GeomAbs_Cone ||
+     aST == GeomAbs_SurfaceOfExtrusion)
+  {
+    return Standard_True;
+  }
+  else if(aST == GeomAbs_SurfaceOfRevolution)
+  {
+    const Handle(Adaptor3d_HCurve)& aBC = BS.BasisCurve();
+    if(aBC->GetType() == GeomAbs_Line)
+    {
+      return Standard_True;
+    }
+    else
+    {
+      return Standard_False;
+    }
+  }
+  else if(aST == GeomAbs_OffsetSurface)
+  {
+    const Handle(Adaptor3d_HSurface)& aS = BS.BasisSurface();
+    return CanUseEdges(aS->Surface());
+  }
+  else if(aST == GeomAbs_BSplineSurface)
+  {
+    Handle(Geom_BSplineSurface) aBSpl = BS.BSpline();
+    if((aBSpl->UDegree() == 1 && aBSpl->NbUKnots() == 2) ||
+       (aBSpl->VDegree() == 1 && aBSpl->NbVKnots() == 2))
+    {
+      return Standard_True;
+    }
+    else
+    {
+      return Standard_False;
+    }
+  }
+  else if(aST == GeomAbs_BezierSurface)
+  {
+    Handle(Geom_BezierSurface) aBz = BS.Bezier();
+    if((aBz->UDegree() == 1 ) ||
+       (aBz->VDegree() == 1 ))
+    {
+      return Standard_True;
+    }
+    else
+    {
+      return Standard_False;
+    }
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : FindExactUVBounds
+//purpose  : 
+//=======================================================================
+void FindExactUVBounds(const TopoDS_Face FF, 
+                       Standard_Real& umin, Standard_Real& umax, 
+                       Standard_Real& vmin, Standard_Real& vmax,
+                       const Standard_Real Tol, 
+                       Standard_Boolean& isNaturalRestriction)
+{
+  TopoDS_Face F = FF;
+  F.Orientation(TopAbs_FORWARD);
+  TopExp_Explorer ex(F,TopAbs_EDGE);
+  //
+  //Check Natural restriction
+  isNaturalRestriction = BRep_Tool::NaturalRestriction(F); //Can we trust this flag?
+  BRepAdaptor_Surface aBAS(F, Standard_False);
+  if(!isNaturalRestriction)
+  {
+    //Check by comparing pcurves and surface boundaries
+    umin = aBAS.FirstUParameter();
+    umax = aBAS.LastUParameter();
+    vmin = aBAS.FirstVParameter();
+    vmax = aBAS.LastVParameter();
+    Standard_Boolean isUperiodic = aBAS.IsUPeriodic(), isVperiodic = aBAS.IsVPeriodic();
+    Standard_Real aT1, aT2;
+    Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+    Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+    Standard_Integer Nu = 0, Nv = 0, NbEdges = 0;
+    gp_Vec2d Du(1, 0), Dv(0, 1);
+    gp_Pnt2d aP;
+    gp_Vec2d aV;
+    for (;ex.More();ex.Next()) {
+      NbEdges++;
+      if(NbEdges > 4)
+      {
+        break;
+      }
+      const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+      const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+      if (aC2D.IsNull()) 
+      {
+        break;
+      }
+      //
+      aC2D->D1((aT1 + aT2)/2., aP, aV);
+      Standard_Real magn = aV.SquareMagnitude();
+      if(magn < gp::Resolution())
+      {
+        break;
+      }
+      else
+      {
+        aV /= Sqrt(magn);
+      }
+      Standard_Real u = aP.X(), v = aP.Y();
+      if(isUperiodic)
+      {
+        ElCLib::InPeriod(u, umin, umax);
+      }
+      if(isVperiodic)
+      {
+        ElCLib::InPeriod(v, vmin, vmax);
+      }
+      //
+      if(Abs(u - umin) <= TolU || Abs(u - umax) <= TolU)
+      {
+        Standard_Real d = Dv * aV;
+        if(1. - Abs(d) <= Precision::PConfusion())
+        {
+          Nu++;
+          if(Nu > 2)
+          {
+            break;
+          }
+        }
+        else
+        {
+          break;
+        }
+      }
+      else if(Abs(v - vmin) <= TolV || Abs(v - vmax) <= TolV)
+      {
+        Standard_Real d = Du * aV;
+        if(1. - Abs(d) <= Precision::PConfusion())
+        {
+          Nv++;
+          if(Nv > 2)
+          {
+            break;
+          }
+        }
+        else
+        {
+          break;
+        }
+      }
+      else
+      {
+        break;
+      }
+    }
+    if(Nu == 2 && Nv == 2)
+    {
+      isNaturalRestriction = Standard_True;
+    }
+  }
+  //
+  if(isNaturalRestriction)
+  {
+    umin = aBAS.FirstUParameter();
+    umax = aBAS.LastUParameter();
+    vmin = aBAS.FirstVParameter();
+    vmax = aBAS.LastVParameter();
+    return;
+  }
+
+  // fill box for the given face
+  Standard_Real aT1, aT2;
+  Standard_Real TolU = Max(aBAS.UResolution(Tol), Precision::PConfusion());
+  Standard_Real TolV = Max(aBAS.VResolution(Tol), Precision::PConfusion());
+  Standard_Real TolUV = Max(TolU, TolV);
+  Bnd_Box2d aBox;
+  ex.Init(F,TopAbs_EDGE);
+  for (;ex.More();ex.Next()) {
+    const TopoDS_Edge& aE = TopoDS::Edge(ex.Current());
+    const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, F, aT1, aT2);
+    if (aC2D.IsNull()) 
+    {
+      continue;
+    }
+    //
+    BndLib_Add2dCurve::AddOptimal(aC2D, aT1, aT2, TolUV, aBox);
+    //
+  }
+  //
+  aBox.Get(umin, vmin, umax, vmax);
+  //
+  TopLoc_Location aLoc;
+  Handle(Geom_Surface) aS = BRep_Tool::Surface(FF, aLoc);
+  Standard_Real aUmin, aUmax, aVmin, aVmax;
+  aS->Bounds(aUmin, aUmax, aVmin, aVmax);
+  if(!aS->IsUPeriodic())
+  {
+    umin = Max(aUmin, umin);
+    umax = Min(aUmax, umax);
+  }
+  else
+  {
+    if(umax - umin > aS->UPeriod())
+    {
+      Standard_Real delta = umax - umin - aS->UPeriod();
+      umin += delta/2.;
+      umax -= delta/2;
+    }
+  }
+  //
+  if(!aS->IsVPeriodic())
+  {
+    vmin = Max(aVmin, vmin);
+    vmax = Min(aVmax, vmax);
+  }
+  else
+  {
+    if(vmax - vmin > aS->VPeriod())
+    {
+      Standard_Real delta = vmax - vmin - aS->VPeriod();
+      vmin += delta/2.;
+      vmax -= delta/2;
+    }
+  }
+}
+//=======================================================================
+//function : Reorder
+//purpose  : 
+//=======================================================================
+inline void Reorder(Standard_Real& a, Standard_Real& b)
+{
+  if(a > b)
+  {
+    Standard_Real t = a;
+    a = b;
+    b = t;
+  }
+}
+//=======================================================================
+//function : IsModifySize
+//purpose  : 
+//=======================================================================
+Standard_Boolean IsModifySize(const BRepAdaptor_Surface& theBS, 
+                              const gp_Pln& thePln, const gp_Pnt& theP,
+                              const Standard_Real umin, const Standard_Real umax,
+                              const Standard_Real vmin, const Standard_Real vmax,
+                              const BRepTopAdaptor_FClass2d& theFClass,
+                              const Standard_Real theTolU, const Standard_Real theTolV)
+{
+  Standard_Real pu1 = 0, pu2, pv1 = 0, pv2;
+  ElSLib::PlaneParameters(thePln.Position(), theP, pu2, pv2);
+  Reorder(pu1, pu2);
+  Reorder(pv1, pv2);
+  Handle(Geom_Plane) aPlane = new Geom_Plane(thePln);
+  GeomAdaptor_Surface aGAPln(aPlane, pu1, pu2, pv1, pv2);
+  Extrema_ExtSS anExtr(aGAPln, theBS, pu1, pu2, pv1, pv2, umin, umax, vmin, vmax, theTolU, theTolV);
+  if(anExtr.IsDone())
+  {
+    if(anExtr.NbExt() > 0)
+    {
+      Standard_Integer i, imin = 0;;
+      Standard_Real dmin = RealLast();
+      Standard_Real uextr = 0., vextr = 0.;
+      Extrema_POnSurf P1, P2;
+      for(i = 1; i <= anExtr.NbExt(); ++i)
+      {
+        Standard_Real d = anExtr.SquareDistance(i);
+        if(d < dmin)
+        {
+          imin = i;
+          dmin = d;
+        }
+      }
+      if(imin > 0)
+      {
+        anExtr.Points(imin, P1, P2);
+        P2.Parameter(uextr, vextr);
+      }
+      else
+      {
+        return Standard_False;
+      }
+      //
+      gp_Pnt2d aP2d(uextr, vextr);
+      TopAbs_State aSt = theFClass.Perform(aP2d);
+      if(aSt == TopAbs_OUT)
+      {
+        return Standard_True;
+      }
+    }
+    else
+    {
+      return Standard_True; //extrema point seems to be out of face UV bounds
+    }
+  }
+  //
+  return Standard_False;
+}
+//
+//=======================================================================
+//function : AdjustFaceBox
+//purpose  : 
+//=======================================================================
+void AdjustFaceBox(const BRepAdaptor_Surface& BS, 
+                   const Standard_Real umin, const Standard_Real umax, 
+                   const Standard_Real vmin, const Standard_Real vmax,
+                   Bnd_Box& FaceBox,
+                   const Bnd_Box& EdgeBox, const Standard_Real Tol)
+{
+  Standard_Real fxmin, fymin, fzmin, fxmax, fymax, fzmax;
+  Standard_Real exmin, eymin, ezmin, exmax, eymax, ezmax;
+  //
+  FaceBox.Get(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+  EdgeBox.Get(exmin, eymin, ezmin, exmax, eymax, ezmax);
+  //
+  Standard_Real TolU = Max(BS.UResolution(Tol), Precision::PConfusion());
+  Standard_Real TolV = Max(BS.VResolution(Tol), Precision::PConfusion());
+  BRepTopAdaptor_FClass2d FClass(BS.Face(), Max(TolU, TolV));
+  //
+  Standard_Boolean isModified = Standard_False;
+  if(exmin > fxmin)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DX()));
+    gp_Pnt aP(fxmin, fymax, fzmax);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fxmin = exmin;
+      isModified = Standard_True;
+    }
+  }
+  if(exmax < fxmax)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DX()));
+    gp_Pnt aP(fxmax, fymin, fzmin);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fxmax = exmax;
+      isModified = Standard_True;
+    }
+  }
+  //
+  if(eymin > fymin)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DY()));
+    gp_Pnt aP(fxmax, fymin, fzmax);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fymin = eymin;
+      isModified = Standard_True;
+    }
+  }
+  if(eymax < fymax)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DY()));
+    gp_Pnt aP(fxmin, fymax, fzmin);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fymax = eymax;
+      isModified = Standard_True;
+    }
+  }
+  //
+  if(ezmin > fzmin)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmin, fymin, fzmin), gp::DZ()));
+    gp_Pnt aP(fxmax, fymax, fzmin);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fzmin = ezmin;
+      isModified = Standard_True;
+    }
+  }
+  if(ezmax < fzmax)
+  {
+    //
+    gp_Pln pl(gp_Ax3(gp_Pnt(fxmax, fymax, fzmax), gp::DZ()));
+    gp_Pnt aP(fxmin, fymin, fzmax);
+    if(IsModifySize(BS, pl, aP,
+                    umin, umax, vmin, vmax, FClass, TolU, TolV))
+    {
+      fzmax = ezmax;
+      isModified = Standard_True;
+    }
+  }
+  //
+  if(isModified)
+  {
+    FaceBox.SetVoid();
+    FaceBox.Update(fxmin, fymin, fzmin, fxmax, fymax, fzmax);
+  }
+}
+
index 5d27717..1c0f8ed 100644 (file)
@@ -68,6 +68,18 @@ public:
   //! box is closer to the shape S.
   Standard_EXPORT static void AddClose (const TopoDS_Shape& S, Bnd_Box& B);
 
+  //! Adds the shape S to the bounding box B.
+  //! This algorith builds precise bounding box,
+  //! which differs from exact geometry boundaries of shape only on shape entities tolerances
+  //! Algorithm is the same as for method Add(..), but uses more precise methods for building boxes 
+  //! for geometry objects.
+  //! If useShapeTolerance = True, bounding box is enlardged by shape tolerances and 
+  //! these tolerances are used for numerical methods of bounding box size calculations, 
+  //! otherwise bounding box is built according to sizes of uderlined geometrical entities,
+  //! numerical calculation use tolerance Precision::Confusion().
+  Standard_EXPORT static void AddOptimal (const TopoDS_Shape& S, Bnd_Box& B, 
+                                          const Standard_Boolean useTriangulation = Standard_True,
+                                          const Standard_Boolean useShapeTolerance = Standard_False);
 
 
 
index 6f1d9af..87424fc 100644 (file)
@@ -440,6 +440,92 @@ static Standard_Integer bounding(Draw_Interpretor& di,Standard_Integer n,const c
   return 0;
 }
 //=======================================================================
+//function : optbounding
+//purpose  : 
+//=======================================================================
+static Standard_Integer optbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+{
+  if (n < 2)
+  {
+    di << "Usage: optbounding shape [usetri [usetol]]\n";
+    di << "usetri and usetol can be 0 or 1, by default usetri = 1, usetol = 0\n";
+    return 1;
+  }
+  Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
+  Bnd_Box B; Handle(Draw_Box) DB;
+  
+  TopoDS_Shape S = DBRep::Get(a[1]);
+  if (S.IsNull()) 
+  {
+    di << "Null shape\n";
+    return 1;
+  }
+  Standard_Boolean useTri = Standard_True;
+  Standard_Boolean useTol = Standard_False;
+  if(n > 2 )
+  {
+    Standard_Integer ii = atoi(a[2]);
+    useTri = ii > 0;
+  }
+  if(n > 3 )
+  {
+    Standard_Integer ii = atoi(a[3]);
+    useTol = ii > 0;
+  }
+  BRepBndLib::AddOptimal(S, B, useTri, useTol);
+  B.Get(axmin, aymin, azmin, axmax, aymax, azmax);
+  DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
+  dout<<DB;
+  di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+  return 0;
+}
+//=======================================================================
+//function : gbounding
+//purpose  : 
+//=======================================================================
+#include <GeomAdaptor_Surface.hxx>
+#include <BndLib_AddSurface.hxx>
+#include <BndLib_Add3dCurve.hxx>
+static Standard_Integer gbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
+{
+  if (n < 2) 
+  {
+    di << "Usage: gbounding surf/curve \n";
+    return 1;
+  }
+  Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
+  Bnd_Box B; Handle(Draw_Box) DB;
+  
+  if (n == 2) { 
+    Handle(Geom_Curve) C;
+    Handle(Geom_Surface) S;
+    S = DrawTrSurf::GetSurface(a[1]);
+    if (S.IsNull())
+    {
+      C = DrawTrSurf::GetCurve(a[1]);
+    }
+    if(!S.IsNull())
+    {
+      GeomAdaptor_Surface aGAS(S);
+      BndLib_AddSurface::AddOptimal(aGAS, Precision::Confusion(), B);
+    }
+    else if(!C.IsNull())
+    {
+      GeomAdaptor_Curve aGAC(C);
+      BndLib_Add3dCurve::AddOptimal(aGAC, Precision::Confusion(), B);
+    }
+    else
+    {
+      di << "Wrong argument \n";
+      return 1;
+    }
+    B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
+    DB = new Draw_Box(gp_Pnt(axmin,aymin,azmin),gp_Pnt(axmax,aymax,azmax),Draw_vert);
+    dout<<DB;
+    di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
+  }
+  return 0;
+}//=======================================================================
 //function : findplane
 //purpose  : 
 //=======================================================================
@@ -953,6 +1039,16 @@ void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
                  __FILE__,
                  bounding,g);
 
+  theCommands.Add("optbounding",
+                 "optbounding shape [usetri (0/1) [usetol (0/1)]] ; ",
+                 __FILE__,
+                 optbounding,g);
+ //
+  theCommands.Add("gbounding",
+                 "gbounding curve/surf ",
+                 __FILE__,
+                 gbounding,g);
+
   theCommands.Add("boundingstr",
                  "boundingstr shape [ xmin ymin zmin xmax ymax zmax] ; print bounding box",
                  __FILE__,
index e49caaa..b581764 100644 (file)
@@ -37,6 +37,7 @@
 #include <gp_XYZ.hxx>
 #include <Precision.hxx>
 #include <Standard_Failure.hxx>
+#include <ElSLib.hxx>
 
 static 
   Standard_Integer ComputeBox(const gp_Hypr& aHypr, 
@@ -389,25 +390,165 @@ void BndLib::Add( const gp_Lin2d& L,const Standard_Real P1,
   B.Enlarge(Tol);
 }
 
-void BndLib::Add( const gp_Circ& C,const Standard_Real Tol, Bnd_Box& B) {
+void BndLib::Add( const gp_Circ& C, const Standard_Real Tol, Bnd_Box& B) 
+{
+  Standard_Real U1 = 0., U2 = 2.*M_PI;
+  Add(C, U1, U2, Tol, B);
+}
 
+void BndLib::Add(const gp_Circ& C,
+                 const Standard_Real U1,
+                 const Standard_Real U2,
+                 const Standard_Real Tol, 
+                 Bnd_Box& B) 
+{
+  Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
+
+  Standard_Real utrim1 = U1, utrim2 = U2;
+  if(U2 - U1 > period)
+  {
+    utrim1 = 0.;
+    utrim2 = 2.*M_PI;
+  }
+  else
+  {
+    Standard_Real tol = Epsilon(1.);
+    ElCLib::AdjustPeriodic(0., 2.*M_PI,
+                           tol,
+                           utrim1, utrim2);
+  }
   Standard_Real R = C.Radius();
   gp_XYZ O  = C.Location().XYZ();
   gp_XYZ Xd = C.XAxis().Direction().XYZ();
   gp_XYZ Yd = C.YAxis().Direction().XYZ();
-  B.Add(gp_Pnt(O -R*Xd -R*Yd));
-  B.Add(gp_Pnt(O -R*Xd +R*Yd));
-  B.Add(gp_Pnt(O +R*Xd -R*Yd));
-  B.Add(gp_Pnt(O +R*Xd +R*Yd));
-  B.Enlarge(Tol);
-}
-
-void BndLib::Add( const gp_Circ& C,const Standard_Real P1,
-  const Standard_Real P2,
-  const Standard_Real Tol, Bnd_Box& B) {
-
-  Compute(P1,P2,C.Radius(),C.Radius(),gp_Pnt(C.XAxis().Direction().XYZ()), 
-          gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
+  const gp_Ax2& pos = C.Position();
+  //
+  Standard_Real tt;
+  Standard_Real xmin, xmax, txmin, txmax;
+  if(Abs(Xd.X()) > gp::Resolution())
+  {
+    txmin = ATan(Yd.X() / Xd.X());
+    txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
+  }
+  else
+  {
+    txmin = M_PI/ 2.;
+  }
+  txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
+  xmin = R * Cos(txmin) * Xd.X() + R * Sin(txmin) * Yd.X() + O.X();
+  xmax = R * Cos(txmax) * Xd.X() + R * Sin(txmax) * Yd.X() + O.X();
+  if(xmin > xmax)
+  {
+    tt = xmin;
+    xmin = xmax;
+    xmax = tt;
+    tt = txmin;
+    txmin = txmax;
+    txmax = tt;
+  }
+  //
+  Standard_Real ymin, ymax, tymin, tymax;
+  if(Abs(Xd.Y()) > gp::Resolution())
+  {
+    tymin = ATan(Yd.Y() / Xd.Y());
+    tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
+  }
+  else
+  {
+    tymin = M_PI/ 2.;
+  }
+  tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
+  ymin = R * Cos(tymin) * Xd.Y() + R * Sin(tymin) * Yd.Y() + O.Y();
+  ymax = R * Cos(tymax) * Xd.Y() + R * Sin(tymax) * Yd.Y() + O.Y();
+  if(ymin > ymax)
+  {
+    tt = ymin;
+    ymin = ymax;
+    ymax = tt;
+    tt = tymin;
+    tymin = tymax;
+    tymax = tt;
+  }
+  //
+  Standard_Real zmin, zmax, tzmin, tzmax;
+  if(Abs(Xd.Z()) > gp::Resolution())
+  {
+    tzmin = ATan(Yd.Z() / Xd.Z());
+    tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
+  }
+  else
+  {
+    tzmin = M_PI/ 2.;
+  }
+  tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
+  zmin = R * Cos(tzmin) * Xd.Z() + R * Sin(tzmin) * Yd.Z() + O.Z();
+  zmax = R * Cos(tzmax) * Xd.Z() + R * Sin(tzmax) * Yd.Z() + O.Z();
+  if(zmin > zmax)
+  {
+    tt = zmin;
+    zmin = zmax;
+    zmax = tt;
+    tt = tzmin;
+    tzmin = tzmax;
+    tzmax = tt;
+  }
+  //
+  if(utrim2 - utrim1 >= period)
+  {
+    B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+  }
+  else
+  {
+    gp_Pnt P = ElCLib::CircleValue(utrim1, pos, R);
+    B.Add(P);
+    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);
+    Standard_Real gap = B.GetGap();
+    Xmin += gap;
+    Ymin += gap;
+    Zmin += gap;
+    Xmax -= gap;
+    Ymax -= gap;
+    Zmax -= gap;
+    //
+    txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
+    if(txmin >= utrim1 && txmin <= utrim2)
+    {
+      Xmin = Min(xmin, Xmin);
+    }
+    txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
+    if(txmax >= utrim1 && txmax <= utrim2)
+    {
+      Xmax = Max(xmax, Xmax);
+   }
+    //
+    tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
+    if(tymin >= utrim1 && tymin <= utrim2)
+    {
+      Ymin = Min(ymin, Ymin);
+    }
+    tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
+    if(tymax >= utrim1 && tymax <= utrim2)
+    {
+      Ymax = Max(ymax, Ymax);
+    }
+    //
+    tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
+    if(tzmin >= utrim1 && tzmin <= utrim2)
+    {
+      Zmin = Min(zmin, Zmin);
+    }
+    tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
+    if(tzmax >= utrim1 && tzmax <= utrim2)
+    {
+      Zmax = Max(zmax, Zmax);
+    }
+    //
+    B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+  }
+  //
   B.Enlarge(Tol);
 }
 
@@ -433,26 +574,166 @@ void BndLib::Add(const gp_Circ2d& C,const Standard_Real P1,
   B.Enlarge(Tol);
 }
 
-void BndLib::Add( const gp_Elips& C,const Standard_Real Tol, Bnd_Box& B) {
-
-  Standard_Real Ra = C.MajorRadius();
-  Standard_Real Rb = C.MinorRadius();
-  gp_XYZ Xd = C.XAxis().Direction().XYZ();
-  gp_XYZ Yd = C.YAxis().Direction().XYZ();
-  gp_XYZ O  = C.Location().XYZ();
-  B.Add(gp_Pnt(O +Ra*Xd +Rb*Yd));
-  B.Add(gp_Pnt(O -Ra*Xd +Rb*Yd));
-  B.Add(gp_Pnt(O -Ra*Xd -Rb*Yd));
-  B.Add(gp_Pnt(O +Ra*Xd -Rb*Yd));
-  B.Enlarge(Tol);
+void BndLib::Add(const gp_Elips& C, const Standard_Real Tol, Bnd_Box& B) 
+{
+  Standard_Real U1 = 0., U2 = 2.*M_PI;
+  Add(C, U1, U2, Tol, B);
 }
 
-void BndLib::Add( const gp_Elips& C,const Standard_Real P1,
-                 const Standard_Real P2,
-                 const Standard_Real Tol, Bnd_Box& B) {
+void BndLib::Add(const gp_Elips& C,
+                 const Standard_Real U1,
+                 const Standard_Real U2,
+                 const Standard_Real Tol, 
+                 Bnd_Box& B) 
+{
+  Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
 
-  Compute(P1,P2,C.MajorRadius(),C.MinorRadius(),gp_Pnt(C.XAxis().Direction().XYZ()), 
-          gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
+  Standard_Real utrim1 = U1, utrim2 = U2;
+  if(U2 - U1 > period)
+  {
+    utrim1 = 0.;
+    utrim2 = 2.*M_PI;
+  }
+  else
+  {
+    Standard_Real tol = Epsilon(1.);
+    ElCLib::AdjustPeriodic(0., 2.*M_PI,
+                           tol,
+                           utrim1, utrim2);
+  }
+  Standard_Real MajR = C.MajorRadius();
+  Standard_Real MinR = C.MinorRadius();
+  gp_XYZ O  = C.Location().XYZ();
+  gp_XYZ Xd = C.XAxis().Direction().XYZ();
+  gp_XYZ Yd = C.YAxis().Direction().XYZ();
+  const gp_Ax2& pos = C.Position();
+  //
+  Standard_Real tt;
+  Standard_Real xmin, xmax, txmin, txmax;
+  if(Abs(Xd.X()) > gp::Resolution())
+  {
+    txmin = ATan((MinR*Yd.X()) / (MajR*Xd.X()));
+    txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
+  }
+  else
+  {
+    txmin = M_PI/ 2.;
+  }
+  txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
+  xmin = MajR * Cos(txmin) * Xd.X() + MinR * Sin(txmin) * Yd.X() + O.X();
+  xmax = MajR * Cos(txmax) * Xd.X() + MinR * Sin(txmax) * Yd.X() + O.X();
+  if(xmin > xmax)
+  {
+    tt = xmin;
+    xmin = xmax;
+    xmax = tt;
+    tt = txmin;
+    txmin = txmax;
+    txmax = tt;
+  }
+  //
+  Standard_Real ymin, ymax, tymin, tymax;
+  if(Abs(Xd.Y()) > gp::Resolution())
+  {
+    tymin = ATan((MinR*Yd.Y()) / (MajR*Xd.Y()));
+    tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
+  }
+  else
+  {
+    tymin = M_PI/ 2.;
+  }
+  tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
+  ymin = MajR * Cos(tymin) * Xd.Y() + MinR * Sin(tymin) * Yd.Y() + O.Y();
+  ymax = MajR * Cos(tymax) * Xd.Y() + MinR * Sin(tymax) * Yd.Y() + O.Y();
+  if(ymin > ymax)
+  {
+    tt = ymin;
+    ymin = ymax;
+    ymax = tt;
+    tt = tymin;
+    tymin = tymax;
+    tymax = tt;
+  }
+  //
+  Standard_Real zmin, zmax, tzmin, tzmax;
+  if(Abs(Xd.Z()) > gp::Resolution())
+  {
+    tzmin = ATan((MinR*Yd.Z()) / (MajR*Xd.Z()));
+    tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
+  }
+  else
+  {
+    tzmin = M_PI/ 2.;
+  }
+  tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
+  zmin = MajR * Cos(tzmin) * Xd.Z() + MinR * Sin(tzmin) * Yd.Z() + O.Z();
+  zmax = MajR * Cos(tzmax) * Xd.Z() + MinR * Sin(tzmax) * Yd.Z() + O.Z();
+  if(zmin > zmax)
+  {
+    tt = zmin;
+    zmin = zmax;
+    zmax = tt;
+    tt = tzmin;
+    tzmin = tzmax;
+    tzmax = tt;
+  }
+  //
+  if(utrim2 - utrim1 >= period)
+  {
+    B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+  }
+  else
+  {
+    gp_Pnt P = ElCLib::EllipseValue(utrim1, pos, MajR, MinR);
+    B.Add(P);
+    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);
+    Standard_Real gap = B.GetGap();
+    Xmin += gap;
+    Ymin += gap;
+    Zmin += gap;
+    Xmax -= gap;
+    Ymax -= gap;
+    Zmax -= gap;
+    //
+    txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
+    if(txmin >= utrim1 && txmin <= utrim2)
+    {
+      Xmin = Min(xmin, Xmin);
+    }
+    txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
+    if(txmax >= utrim1 && txmax <= utrim2)
+    {
+      Xmax = Max(xmax, Xmax);
+    }
+    //
+    tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
+    if(tymin >= utrim1 && tymin <= utrim2)
+    {
+      Ymin = Min(ymin, Ymin);
+    }
+    tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
+    if(tymax >= utrim1 && tymax <= utrim2)
+    {
+      Ymax = Max(ymax, Ymax);
+    }
+    //
+    tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
+    if(tzmin >= utrim1 && tzmin <= utrim2)
+    {
+      Zmin = Min(zmin, Zmin);
+    }
+    tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
+    if(tzmax >= utrim1 && tzmax <= utrim2)
+    {
+      Zmax = Max(zmax, Zmax);
+    }
+    //
+    B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+  }
+  //
   B.Enlarge(Tol);
 }
 
@@ -661,57 +942,70 @@ void BndLib::Add(const gp_Hypr2d& H,const Standard_Real P1,
   B.Enlarge(Tol);
 }
 
+static void ComputeCyl(const gp_Cylinder& Cyl, 
+                       const Standard_Real UMin, const Standard_Real UMax, 
+                       const Standard_Real VMin, const Standard_Real VMax, 
+                       Bnd_Box& B)
+{
+  gp_Circ aC = ElSLib::CylinderVIso(Cyl.Position(), Cyl.Radius(), VMin);
+  BndLib::Add(aC, UMin, UMax, 0., B);
+  //
+  gp_Vec aT = (VMax - VMin) * Cyl.Axis().Direction();
+  aC.Translate(aT);
+  BndLib::Add(aC, UMin, UMax, 0., B);
+}
+
 void BndLib::Add( const gp_Cylinder& S,const Standard_Real UMin,
                  const Standard_Real UMax,const Standard_Real VMin,
-                 const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
-
-  if (Precision::IsNegativeInfinite(VMin)) {
-    if (Precision::IsNegativeInfinite(VMax)) {
+                 const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B)
+{
+  if (Precision::IsNegativeInfinite(VMin))
+  {
+    if (Precision::IsNegativeInfinite(VMax))
+    {
       Standard_Failure::Raise("BndLib::bad parameter");
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
-       OpenMinMax(S.Axis().Direction(),B);
+    else if (Precision::IsPositiveInfinite(VMax))
+    {
+      OpenMinMax(S.Axis().Direction(),B);
     }
-    else {
-      Compute(UMin,UMax,S.Radius(),S.Radius(),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
+    else
+    {
+      ComputeCyl(S, UMin, UMax, 0., VMax,B);
       OpenMin(S.Axis().Direction(),B);
     }
   }
-  else if (Precision::IsPositiveInfinite(VMin)) {
-    if (Precision::IsNegativeInfinite(VMax)) {
+  else if (Precision::IsPositiveInfinite(VMin)) 
+  {
+    if (Precision::IsNegativeInfinite(VMax)) 
+    {
       OpenMinMax(S.Axis().Direction(),B);
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
+    else if (Precision::IsPositiveInfinite(VMax))
+    {
       Standard_Failure::Raise("BndLib::bad parameter");
     }
-    else {
-      Compute(UMin,UMax,S.Radius(),S.Radius(),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
+    else
+    {
+      ComputeCyl(S, UMin, UMax, 0., VMax, B);
       OpenMax(S.Axis().Direction(),B);
     }
-
   }
-  else {
-    Compute(UMin,UMax,S.Radius(),S.Radius(),
-     gp_Pnt(S.XAxis().Direction().XYZ()),
-     gp_Pnt(S.YAxis().Direction().XYZ()),
-     gp_Pnt(S.Location().XYZ() + VMin*S.Axis().Direction().XYZ()),B);
-    if (Precision::IsNegativeInfinite(VMax)) {
+  else
+  {
+    if (Precision::IsNegativeInfinite(VMax))
+    {
+      ComputeCyl(S, UMin, UMax, VMin, 0., B);
       OpenMin(S.Axis().Direction(),B);
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
+    else if (Precision::IsPositiveInfinite(VMax)) 
+    {
+      ComputeCyl(S, UMin, UMax, VMin, 0., B);
       OpenMax(S.Axis().Direction(),B); 
     }
-    else {
-      Compute(UMin,UMax,S.Radius(),S.Radius(),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
+    else 
+    {
+      ComputeCyl(S, UMin, UMax, VMin, VMax, B);
     }
   }
 
@@ -725,74 +1019,97 @@ void BndLib::Add( const gp_Cylinder& S,const Standard_Real VMin,
   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
 }
 
+static void ComputeCone (const gp_Cone& Cone, 
+                         const Standard_Real UMin, const Standard_Real UMax, 
+                         const Standard_Real VMin, const Standard_Real VMax, 
+                         Bnd_Box& B)
+{
+  const gp_Ax3& aPos = Cone.Position();
+  Standard_Real R = Cone.RefRadius();
+  Standard_Real sang = Cone.SemiAngle();
+  gp_Circ aC = ElSLib::ConeVIso(aPos, R, sang, VMin);
+  if(aC.Radius() > Precision::Confusion())
+  {
+    BndLib::Add(aC, UMin, UMax, 0., B);
+  }
+  else
+  {
+    B.Add(aC.Location());
+  }
+  //
+  aC = ElSLib::ConeVIso(aPos, R, sang, VMax);
+  if(aC.Radius() > Precision::Confusion())
+  {
+    BndLib::Add(aC, UMin, UMax, 0., B);
+  }
+  else
+  {
+    B.Add(aC.Location());
+  }
+}
+
 void BndLib::Add(const gp_Cone& S,const Standard_Real UMin,
                  const Standard_Real UMax,const Standard_Real VMin,
                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
 
-  Standard_Real R = S.RefRadius();
   Standard_Real A = S.SemiAngle();
-  if (Precision::IsNegativeInfinite(VMin)) {
-    if (Precision::IsNegativeInfinite(VMax)) {
+  if (Precision::IsNegativeInfinite(VMin)) 
+  {
+    if (Precision::IsNegativeInfinite(VMax)) 
+    {
       Standard_Failure::Raise("BndLib::bad parameter");
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
+    else if (Precision::IsPositiveInfinite(VMax)) 
+    {
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMinMax(D,B); 
     }
-    else {
-      Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + 
-       VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
+    else 
+    {
+      ComputeCone(S, UMin, UMax, 0., VMax, B);
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMin(D,B);     
     }
 
   }
-  else if (Precision::IsPositiveInfinite(VMin)) {
-    if (Precision::IsNegativeInfinite(VMax)) {
+  else if (Precision::IsPositiveInfinite(VMin)) 
+  {
+    if (Precision::IsNegativeInfinite(VMax))
+    {
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMinMax(D,B);
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
+    else if (Precision::IsPositiveInfinite(VMax)) 
+    {
       Standard_Failure::Raise("BndLib::bad parameter");
     }
-    else {
-      Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + 
-       VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
+    else 
+    {
+      ComputeCone(S, UMin, UMax, 0., VMax, B);
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMax(D,B);
     }
-
   }
-  else {
-    Compute(UMin,UMax,R+VMin*Sin(A),R+VMin*Sin(A),
-     gp_Pnt(S.XAxis().Direction().XYZ()),
-     gp_Pnt(S.YAxis().Direction().XYZ()),
-     gp_Pnt(S.Location().XYZ() + 
-     VMin*Cos(A)*S.Axis().Direction().XYZ()),B);
-    if (Precision::IsNegativeInfinite(VMax)) {
+  else 
+  {
+    if (Precision::IsNegativeInfinite(VMax)) 
+    {
+      ComputeCone(S, UMin, UMax, VMin, 0., B);
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMin(D,B);
     }
-    else if (Precision::IsPositiveInfinite(VMax)) {
+    else if (Precision::IsPositiveInfinite(VMax)) 
+    {
+      ComputeCone(S, UMin, UMax, VMin, 0., B);
       gp_Dir D(Cos(A)*S.Axis().Direction());
       OpenMax(D,B);
     }
-    else {
-      Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
-       gp_Pnt(S.XAxis().Direction().XYZ()),
-       gp_Pnt(S.YAxis().Direction().XYZ()),
-       gp_Pnt(S.Location().XYZ() + 
-       VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
+    else 
+    {
+      ComputeCone(S, UMin, UMax, VMin, VMax, B);
     }
   }
 
-
   B.Enlarge(Tol);
 }
 
@@ -802,102 +1119,118 @@ void BndLib::Add( const gp_Cone& S,const Standard_Real VMin,
   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
 }
 
+static void ComputeSphere (const gp_Sphere& Sphere, 
+                           const Standard_Real UMin, const Standard_Real UMax, 
+                           const Standard_Real VMin, const Standard_Real VMax, 
+                           Bnd_Box& B)
+{
+  gp_Pnt P = Sphere.Location();
+  Standard_Real R = Sphere.Radius();
+  Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+  xmin = P.X() - R;
+  xmax = P.X() + R;
+  ymin = P.Y() - R;
+  ymax = P.Y() + R;
+  zmin = P.Z() - R;
+  zmax = P.Z() + R;
+  
+  Standard_Real uper = 2. * M_PI - Precision::PConfusion();
+  Standard_Real vper = M_PI - Precision::PConfusion();
+  if (UMax - UMin >= uper && VMax - VMin >= vper)
+  {
+    // a whole sphere
+    B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
+  }
+  else
+  {
+    Standard_Real u, v;
+    Standard_Real umax = UMin + 2. * M_PI;
+    const gp_Ax3& Pos = Sphere.Position();
+    gp_Pnt PExt = P;
+    PExt.SetX(xmin);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    //
+    PExt.SetX(xmax);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    PExt.SetX(P.X());
+    //
+    PExt.SetY(ymin);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    //
+    PExt.SetY(ymax);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    PExt.SetY(P.Y());
+    //
+    PExt.SetZ(zmin);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    //
+    PExt.SetZ(zmax);
+    ElSLib::SphereParameters(Pos, R, PExt, u, v);
+    u = ElCLib::InPeriod(u, UMin, umax);
+    if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
+    {
+      B.Add(PExt);
+    }
+    //
+    // Add boundaries of patch
+    // UMin, UMax
+    gp_Circ aC = ElSLib::SphereUIso(Pos, R, UMin);
+    BndLib::Add(aC, VMin, VMax, 0., B);
+    aC = ElSLib::SphereUIso(Pos, R, UMax);
+    BndLib::Add(aC, VMin, VMax, 0., B);
+    // VMin, VMax
+    aC = ElSLib::SphereVIso(Pos, R, VMin);
+    BndLib::Add(aC, UMin, UMax, 0., B);
+    aC = ElSLib::SphereVIso(Pos, R, VMax);
+    BndLib::Add(aC, UMin, UMax, 0., B);
+  }
+}
+
 void BndLib::Add(const gp_Sphere& S,const Standard_Real UMin,
                  const Standard_Real UMax,const Standard_Real VMin,
-                 const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
-
-#if 0
- Standard_Real Fi1;
- Standard_Real Fi2;
- if (VMax<VMin) {
-   Fi1 = VMax;
-   Fi2 = VMin;
- }
- else {
-   Fi1 = VMin;
-   Fi2 = VMax;
- }
- if (-Fi1>Precision::Angular()) {
-   if (-Fi2>Precision::Angular()) {
-     Compute(UMin,UMax,S.Radius(),S.Radius(),
-        gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-        S.Location(),B);
-     Compute(UMin,UMax,S.Radius(),S.Radius(),
-        gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-     gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
-   }
-   else {
-     Compute(UMin,UMax,S.Radius(),S.Radius(),
-     gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-     gp_Pnt(S.Location().XYZ()+ S.Radius()*S.Position().Axis().Direction().XYZ()),B);
-     Compute(UMin,UMax,S.Radius(),S.Radius(),
-     gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-     gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
-   }
- }
- else {
-   Compute(UMin,UMax,S.Radius(),S.Radius(),
-      gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-      S.Location(),B);
-   Compute(UMin,UMax,S.Radius(),S.Radius(),
-   gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
-   gp_Pnt(S.Location().XYZ() +S.Radius()*S.Position().Axis().Direction().XYZ()),B);
- } 
- B.Enlarge(Tol);
-#else
- Standard_Real u,v,du,dv;
- Standard_Integer iu,iv;
- du = (UMax-UMin)/10;
- dv = (VMax-VMin)/10;
- Standard_Real COSV[11];
- Standard_Real SINV[11];
- for(iv=0,v=VMin;iv<=10;iv++) { 
-   COSV[iv]=cos(v);
-   SINV[iv]=sin(v);   
-   v+=dv;
- }
- for(u=UMin,iu=0; iu<=10 ; iu++) { 
-   Standard_Real Radiuscosu=S.Radius()*cos(u);
-   Standard_Real Radiussinu=S.Radius()*sin(u);
-   for(v=VMin,iv=0; iv<=10 ; iv++) { 
-     Standard_Real sinv=SINV[iv];
-     Standard_Real cosv=COSV[iv];
-     gp_XYZ M;
-     M.SetLinearForm (cosv*Radiuscosu, S.Position().XDirection().XYZ(),
-        cosv*Radiussinu, S.Position().YDirection().XYZ(),
-        S.Radius()*sinv,     S.Position().Direction().XYZ() ,
-        S.Position().Location().XYZ()  );
-     //-- static int t=0;
-     //-- cout<<"point p"<<++t<<" "<<M.X()<<" "<<M.Y()<<" "<<M.Z()<<endl;
-     B.Add(gp_Pnt(M));
-     v+=dv;
-   }
-   u+=du;
- }
- Standard_Real Maxduv = Max(du,dv)*0.5;
- Standard_Real Fleche = S.Radius() * (1 - cos(Maxduv));
- B.Enlarge(Fleche);
- B.Enlarge(10*Tol);
-#endif
+                 const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) 
+{
+  ComputeSphere(S, UMin, UMax, VMin, VMax, B);
+  B.Enlarge(Tol);
 }
 
-void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B) {
-
+void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B) 
+{
+  gp_Pnt P = S.Location();
   Standard_Real R = S.Radius();
-  gp_XYZ O = S.Location().XYZ();
-  gp_XYZ Xd = S.XAxis().Direction().XYZ();
-  gp_XYZ Yd = S.YAxis().Direction().XYZ();
-  gp_XYZ Zd = S.Position().Axis().Direction().XYZ();
-  B.Add(gp_Pnt(O -R*Xd -R*Yd+ R*Zd)); 
-  B.Add(gp_Pnt(O -R*Xd +R*Yd+ R*Zd)); 
-  B.Add(gp_Pnt(O +R*Xd -R*Yd+ R*Zd)); 
-  B.Add(gp_Pnt(O +R*Xd +R*Yd+ R*Zd)); 
-  B.Add(gp_Pnt(O +R*Xd -R*Yd- R*Zd)); 
-  B.Add(gp_Pnt(O -R*Xd -R*Yd- R*Zd)); 
-  B.Add(gp_Pnt(O +R*Xd +R*Yd- R*Zd)); 
-  B.Add(gp_Pnt(O -R*Xd +R*Yd- R*Zd)); 
+  Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
+  xmin = P.X() - R;
+  xmax = P.X() + R;
+  ymin = P.Y() - R;
+  ymax = P.Y() + R;
+  zmin = P.Z() - R;
+  zmax = P.Z() + R;
+  B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
   B.Enlarge(Tol);
 }
 
index eeb9025..58db970 100644 (file)
 #include <gp.hxx>
 #include <Precision.hxx>
 #include <Standard_Type.hxx>
+#include <math_MultipleVarFunction.hxx>
+#include <math_Function.hxx>
+#include <math_BrentMinimum.hxx>
+#include <math_PSO.hxx>
 
 //=======================================================================
 //function : BndLib_Box2dCurve
@@ -57,6 +61,8 @@ class BndLib_Box2dCurve  {
 
   void Perform();
 
+  void PerformOptimal(const Standard_Real Tol);
+
   void Clear();
 
   Standard_Integer ErrorStatus() const;
@@ -89,6 +95,17 @@ class BndLib_Box2dCurve  {
                                 const Standard_Real );
   //
   void PerformOnePoint();
+  //
+  void PerformGenCurv(const Standard_Real Tol = Precision::PConfusion());
+  //
+  Standard_Integer NbSamples();
+  //
+  Standard_Real AdjustExtr(const Standard_Real UMin,
+                           const Standard_Real UMax,
+                           const Standard_Real Extr0,
+                           const Standard_Integer CoordIndx,
+                           const Standard_Real Tol, 
+                           const Standard_Boolean IsMin);
   //-----------------------------
  protected:
   Handle(Geom2d_Curve) myCurve;
@@ -101,7 +118,109 @@ class BndLib_Box2dCurve  {
   Standard_Real myT2;
   GeomAbs_CurveType myTypeBase;
 };
+//
+class Curv2dMaxMinCoordMVar : public math_MultipleVarFunction
+{
+public:
+  Curv2dMaxMinCoordMVar(const Handle(Geom2d_Curve)& theCurve, 
+                        const Standard_Real UMin,
+                        const Standard_Real UMax,
+                        const Standard_Integer CoordIndx,
+                        const Standard_Real Sign)
+: myCurve(theCurve),
+  myUMin(UMin),
+  myUMax(UMax),
+  myCoordIndx(CoordIndx),
+  mySign(Sign)
+  {
+  }
+
+  Standard_Boolean Value (const math_Vector& X,
+                                Standard_Real& F)
+  {
+    if (!CheckInputData(X(1)))
+    {
+      return Standard_False;
+    }
+    gp_Pnt2d aP = myCurve->Value(X(1));
+
+    F = mySign * aP.Coord(myCoordIndx);
+
+    return Standard_True;
+  }
+
+  
+
+  Standard_Integer NbVariables() const
+  {
+    return 1;
+  }
+
+private:
+  Curv2dMaxMinCoordMVar & operator = (const Curv2dMaxMinCoordMVar & theOther);
+
+  Standard_Boolean CheckInputData(Standard_Real theParam)
+  {
+    if (theParam < myUMin || 
+        theParam > myUMax)
+      return Standard_False;
+    return Standard_True;
+  }
+
+  const Handle(Geom2d_Curve)& myCurve;
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Integer myCoordIndx;
+  Standard_Real mySign;
+};
+//
+class Curv2dMaxMinCoord : public math_Function
+{
+public:
+  Curv2dMaxMinCoord(const Handle(Geom2d_Curve)& theCurve, 
+                     const Standard_Real UMin,
+                     const Standard_Real UMax,
+                     const Standard_Integer CoordIndx,
+                     const Standard_Real Sign)
+: myCurve(theCurve),
+  myUMin(UMin),
+  myUMax(UMax),
+  myCoordIndx(CoordIndx),
+  mySign(Sign)
+  {
+  }
+
+  Standard_Boolean Value (const Standard_Real X,
+                                Standard_Real& F)
+  {
+    if (!CheckInputData(X))
+    {
+      return Standard_False;
+    }
+    gp_Pnt2d aP = myCurve->Value(X);
+
+    F = mySign * aP.Coord(myCoordIndx);
+
+    return Standard_True;
+  }
 
+private:
+  Curv2dMaxMinCoord & operator = (const Curv2dMaxMinCoord & theOther);
+
+  Standard_Boolean CheckInputData(Standard_Real theParam)
+  {
+    if (theParam < myUMin || 
+        theParam > myUMax)
+      return Standard_False;
+    return Standard_True;
+  }
+
+  const Handle(Geom2d_Curve)& myCurve;
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Integer myCoordIndx;
+  Standard_Real mySign;
+};
 
 //=======================================================================
 //function : 
@@ -244,6 +363,41 @@ void BndLib_Box2dCurve::Perform()
   }
 }
 //=======================================================================
+//function : PerformOptimal
+//purpose  : 
+//=======================================================================
+void BndLib_Box2dCurve::PerformOptimal(const Standard_Real Tol)
+{
+  Clear();
+  myErrorStatus=0;
+  CheckData();
+
+  if(myErrorStatus) {
+    return;
+  }
+  
+  if (myT1==myT2) {
+    PerformOnePoint();
+    return;
+  }
+  
+  GetInfoBase();
+  if(myErrorStatus) {
+    return;
+  }
+  
+  if (myTypeBase==GeomAbs_Line ||
+      myTypeBase==GeomAbs_Circle ||
+      myTypeBase==GeomAbs_Ellipse ||
+      myTypeBase==GeomAbs_Parabola ||
+      myTypeBase==GeomAbs_Hyperbola) { // LineConic
+    PerformLineConic();
+  }
+  else {
+    PerformGenCurv(Tol);
+  }
+}
+//=======================================================================
 //function : PerformOnePoint
 //purpose  : 
 //=======================================================================
@@ -379,6 +533,209 @@ void BndLib_Box2dCurve::PerformOther()
   myBox.Add(aP2D);
 }
 //=======================================================================
+//function : NbSamples
+//purpose  : 
+//=======================================================================
+Standard_Integer BndLib_Box2dCurve::NbSamples()
+{
+  Standard_Integer N;
+  switch (myTypeBase) {
+  case GeomAbs_BezierCurve: 
+    {
+      Handle(Geom2d_BezierCurve) aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
+      N = aCBz->NbPoles();
+      //By default parametric range of Bezier curv is [0, 1]
+      Standard_Real du = myT2 - myT1;
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  case GeomAbs_BSplineCurve: 
+    {
+      Handle(Geom2d_BSplineCurve) aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
+      N = (aCBS->Degree() + 1)*(aCBS->NbKnots() -1);
+      Standard_Real umin = aCBS->FirstParameter(), 
+                    umax = aCBS->LastParameter();
+      Standard_Real du = (myT2 - myT1) / (umax - umin);
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  default:
+    N = 17;
+  }
+  return Min (23,N);
+}
+//=======================================================================
+//function : AdjustExtr
+//purpose  : 
+//=======================================================================
+Standard_Real BndLib_Box2dCurve::AdjustExtr(const Standard_Real UMin,
+                                            const Standard_Real UMax,
+                                            const Standard_Real Extr0,
+                                            const Standard_Integer CoordIndx,                                 
+                                            const Standard_Real Tol, 
+                                            const Standard_Boolean IsMin)
+{
+  Standard_Real aSign = IsMin ? 1.:-1.;
+  Standard_Real extr = aSign * Extr0;
+  //
+  Standard_Real Du = (myCurve->LastParameter() - myCurve->FirstParameter());
+  //
+  Geom2dAdaptor_Curve aGAC(myCurve);
+  Standard_Real UTol = Max(aGAC.Resolution(Tol), Precision::PConfusion());
+  Standard_Real reltol = UTol / Max(Abs(UMin), Abs(UMax));
+  if(UMax - UMin < 0.01 * Du)
+  {
+    //It is suggested that function has one extremum on small interval
+    math_BrentMinimum anOptLoc(reltol, 100, UTol);
+    Curv2dMaxMinCoord aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
+    anOptLoc.Perform(aFunc, UMin, (UMin+UMax)/2., UMax);
+    if(anOptLoc.IsDone())
+    {
+      extr = anOptLoc.Minimum();
+      return aSign * extr;
+    }
+  }
+  //
+  Standard_Integer aNbParticles = Max(8, RealToInt(32 * (UMax - UMin) / Du));
+  Standard_Real maxstep = (UMax - UMin) / (aNbParticles + 1);
+  math_Vector aT(1,1);
+  math_Vector aLowBorder(1,1);
+  math_Vector aUppBorder(1,1);
+  math_Vector aSteps(1,1);
+  aLowBorder(1) = UMin;
+  aUppBorder(1) = UMax;
+  aSteps(1) = Min(0.1 * Du, maxstep);
+
+  Curv2dMaxMinCoordMVar aFunc(myCurve, UMin, UMax, CoordIndx, aSign);
+  math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles); 
+  aFinder.Perform(aSteps, extr, aT);
+  //
+  math_BrentMinimum anOptLoc(reltol, 100, UTol);
+  Curv2dMaxMinCoord aFunc1(myCurve, UMin, UMax, CoordIndx, aSign);
+  anOptLoc.Perform(aFunc1, Max(aT(1) - aSteps(1), UMin), aT(1), Min(aT(1) + aSteps(1), UMax));
+
+  if(anOptLoc.IsDone())
+  {
+    extr = anOptLoc.Minimum();
+    return aSign * extr;
+  }
+
+  return aSign * extr;
+}
+
+//=======================================================================
+//function : PerformGenCurv
+//purpose  : 
+//=======================================================================
+void BndLib_Box2dCurve::PerformGenCurv(const Standard_Real Tol)
+{
+  //
+  Standard_Integer Nu = NbSamples();
+  //
+  Standard_Real CoordMin[2] = {RealLast(), RealLast()}; 
+  Standard_Real CoordMax[2] = {-RealLast(), -RealLast()};
+  Standard_Real DeflMax[2] = {-RealLast(), -RealLast()};
+  //
+  gp_Pnt2d P;
+  Standard_Integer i, k;
+  Standard_Real du = (myT2 - myT1)/(Nu-1), du2 = du / 2.;
+  NCollection_Array1<gp_XY> aPnts(1, Nu);
+  Standard_Real u;
+  for (i = 1, u = myT1; i <= Nu; i++, u += du)
+  {
+    D0(u,P);
+    aPnts(i) = P.XY();
+    //
+    for(k = 0; k < 2; ++k)
+    {
+      if(CoordMin[k] > P.Coord(k+1))
+      {
+        CoordMin[k] = P.Coord(k+1);
+      }
+      if(CoordMax[k] < P.Coord(k+1))
+      {
+        CoordMax[k] = P.Coord(k+1);
+      }
+    }
+    //
+    if(i > 1)
+    {
+      gp_XY aPm = 0.5 * (aPnts(i-1) + aPnts(i));
+      D0(u - du2, P);
+      gp_XY aD = (P.XY() - aPm);
+      for(k = 0; k < 2; ++k)
+      {
+        if(CoordMin[k] > P.Coord(k+1))
+        {
+          CoordMin[k] = P.Coord(k+1);
+        }
+        if(CoordMax[k] < P.Coord(k+1))
+        {
+          CoordMax[k] = P.Coord(k+1);
+        }
+        Standard_Real d = Abs(aD.Coord(k+1));
+        if(DeflMax[k] < d)
+        {
+          DeflMax[k] = d;
+        }
+      }
+    }
+  }
+  //
+  //Adjusting minmax 
+  for(k = 0; k < 2; ++k)
+  {
+    Standard_Real d = DeflMax[k];
+    if(d <= Tol)
+    {
+      continue;
+    }
+    Standard_Real CMin = CoordMin[k];
+    Standard_Real CMax = CoordMax[k];
+    for(i = 1; i <= Nu; ++i)
+    {
+      if(aPnts(i).Coord(k+1) - CMin < d)
+      {
+        Standard_Real tmin, tmax;
+        tmin = myT1 + Max(0, i-2) * du;
+        tmax = myT1 + Min(Nu-1, i) * du;
+        Standard_Real cmin = AdjustExtr(tmin, tmax,
+                                        CMin, k + 1, Tol, Standard_True);
+        if(cmin < CMin)
+        {
+          CMin = cmin;
+        }
+      }
+      else if(CMax - aPnts(i).Coord(k+1) < d)
+      {
+        Standard_Real tmin, tmax;
+        tmin = myT1 + Max(0, i-2) * du;
+        tmax = myT1 + Min(Nu-1, i) * du;
+        Standard_Real cmax = AdjustExtr(tmin, tmax,
+                                        CMax, k + 1, Tol, Standard_False);
+        if(cmax > CMax)
+        {
+          CMax = cmax;
+        }
+      }
+    }
+    CoordMin[k] = CMin;
+    CoordMax[k] = CMax;
+  }
+
+  myBox.Add(gp_Pnt2d(CoordMin[0], CoordMin[1]));
+  myBox.Add(gp_Pnt2d(CoordMax[0], CoordMax[1]));
+  myBox.Enlarge(Tol);
+}
+//=======================================================================
 //function : D0
 //purpose  : 
 //=======================================================================
@@ -895,3 +1252,24 @@ void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
   aBox2D.Add(aBoxC);
   aBox2D.Enlarge(aTol);
 }
+//=======================================================================
+//function : AddOptimal
+//purpose  : 
+//=======================================================================
+void BndLib_Add2dCurve::AddOptimal(const Handle(Geom2d_Curve)& aC2D,
+                                   const Standard_Real aT1,
+                                   const Standard_Real aT2,
+                                   const Standard_Real aTol,
+                                   Bnd_Box2d& aBox2D)
+{
+  BndLib_Box2dCurve aBC;
+  //
+  aBC.SetCurve(aC2D);
+  aBC.SetRange(aT1, aT2);
+  //
+  aBC.PerformOptimal(aTol);
+  //
+  const Bnd_Box2d& aBoxC=aBC.Box();
+  aBox2D.Add(aBoxC);
+  aBox2D.Enlarge(aTol);
+}
\ No newline at end of file
index 3377ff9..13c3757 100644 (file)
@@ -115,7 +115,19 @@ public:
   //! -   if not, the points of an approximation of the curve C.
   Standard_EXPORT static void Add (const Handle(Geom2d_Curve)& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol, Bnd_Box2d& B);
 
-
+  //! Adds to the bounding box B the part of curve C
+  //! B is then enlarged by the tolerance value Tol.
+  //! U1, U2 - the parametric range to comute the bounding box;
+  //! Note: depending on the type of curve, one of the following
+  //! algorithms  is used to include it in the bounding box B:
+  //! -   an exact analytical if C is built from a line, a circle or a conic curve,
+  //! -   numerical calculation of bounding box sizes, based on minimization algorithm,  for other types of curve
+  //! If Tol = < Precision::PConfusion(), Precision::PConfusion is used as tolerance for calculation
+  Standard_EXPORT static void AddOptimal(const Handle(Geom2d_Curve)& C,
+                                                          const Standard_Real U1,
+                                                          const Standard_Real U2,
+                                                          const Standard_Real Tol,
+                                                          Bnd_Box2d& B);
 
 
 protected:
index 45e16be..3d9a697 100644 (file)
 #include <TColgp_Array1OfPnt.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColStd_Array1OfReal.hxx>
+#include <math_MultipleVarFunction.hxx>
+#include <math_Function.hxx>
+#include <math_PSO.hxx>
+#include <math_BrentMinimum.hxx>
+//
+static Standard_Integer NbSamples(const Adaptor3d_Curve& C, 
+                                   const Standard_Real Umin,
+                                   const Standard_Real Umax);
+
+static Standard_Real  AdjustExtr(const Adaptor3d_Curve& C, 
+                                 const Standard_Real UMin,
+                                                  const Standard_Real UMax,
+                                 const Standard_Real Extr0,
+                                 const Standard_Integer CoordIndx,                                 
+                                 const Standard_Real Tol, 
+                                 const Standard_Boolean IsMin);
+
 
 //=======================================================================
 //function : reduceSplineBox
@@ -247,3 +264,379 @@ void BndLib_Add3dCurve::Add( const Adaptor3d_Curve& C,
     }
   }
 }
+
+//=======================================================================
+//function : AddOptimal
+//purpose  : 
+//=======================================================================
+
+void BndLib_Add3dCurve::AddOptimal( const Adaptor3d_Curve& C,
+                                                     const Standard_Real Tol,
+                                                     Bnd_Box&      B )
+{
+  BndLib_Add3dCurve::AddOptimal(C,
+                                                 C.FirstParameter(),
+                                                 C.LastParameter (),
+                                                 Tol,B);
+}
+
+//=======================================================================
+//function : AddOptimal
+//purpose  : 
+//=======================================================================
+
+void BndLib_Add3dCurve::AddOptimal( const Adaptor3d_Curve& C,
+                                                     const Standard_Real U1,
+                                                     const Standard_Real U2,
+                                                     const Standard_Real Tol,
+                                                     Bnd_Box&            B)
+{
+  switch (C.GetType()) {
+
+    case GeomAbs_Line: 
+    {
+      BndLib::Add(C.Line(),U1,U2,Tol,B);
+      break;
+    }
+    case GeomAbs_Circle: 
+    {
+      BndLib::Add(C.Circle(),U1,U2,Tol,B);
+      break;
+    }
+    case GeomAbs_Ellipse: 
+    {
+      BndLib::Add(C.Ellipse(),U1,U2,Tol,B);
+      break;
+    }
+    case GeomAbs_Hyperbola: 
+    {
+      BndLib::Add(C.Hyperbola(),U1,U2,Tol,B);
+      break;
+    }
+    case GeomAbs_Parabola: 
+    {
+      BndLib::Add(C.Parabola(),U1,U2,Tol,B);
+      break;
+    }
+    default:
+    {
+      AddGenCurv(C, U1, U2, Tol, B);
+    }
+  }
+}
+
+//=======================================================================
+//function : AddGenCurv
+//purpose  : 
+//=======================================================================
+void BndLib_Add3dCurve::AddGenCurv(const Adaptor3d_Curve& C, 
+                                   const Standard_Real UMin,
+                                   const Standard_Real UMax,
+                                   const Standard_Real Tol,
+                                   Bnd_Box& B)
+{
+  Standard_Integer Nu = NbSamples(C, UMin, UMax);
+  //
+  Standard_Real CoordMin[3] = {RealLast(), RealLast(), RealLast()}; 
+  Standard_Real CoordMax[3] = {-RealLast(), -RealLast(), -RealLast()};
+  Standard_Real DeflMax[3] = {-RealLast(), -RealLast(), -RealLast()};
+  //
+  gp_Pnt P;
+  Standard_Integer i, k;
+  Standard_Real du = (UMax-UMin)/(Nu-1), du2 = du / 2.;
+  NCollection_Array1<gp_XYZ> aPnts(1, Nu);
+  Standard_Real u;
+  for (i = 1, u = UMin; i <= Nu; i++, u += du)
+  {
+    C.D0(u,P);
+    aPnts(i) = P.XYZ();
+    //
+    for(k = 0; k < 3; ++k)
+    {
+      if(CoordMin[k] > P.Coord(k+1))
+      {
+        CoordMin[k] = P.Coord(k+1);
+      }
+      if(CoordMax[k] < P.Coord(k+1))
+      {
+        CoordMax[k] = P.Coord(k+1);
+      }
+    }
+    //
+    if(i > 1)
+    {
+      gp_XYZ aPm = 0.5 * (aPnts(i-1) + aPnts(i));
+      C.D0(u - du2, P);
+      gp_XYZ aD = (P.XYZ() - aPm);
+      for(k = 0; k < 3; ++k)
+      {
+        if(CoordMin[k] > P.Coord(k+1))
+        {
+          CoordMin[k] = P.Coord(k+1);
+        }
+        if(CoordMax[k] < P.Coord(k+1))
+        {
+          CoordMax[k] = P.Coord(k+1);
+        }
+        Standard_Real d = Abs(aD.Coord(k+1));
+        if(DeflMax[k] < d)
+        {
+          DeflMax[k] = d;
+        }
+      }
+    }
+  }
+  //
+  //Adjusting minmax 
+  Standard_Real eps = Max(Tol, Precision::Confusion());
+  for(k = 0; k < 3; ++k)
+  {
+    Standard_Real d = DeflMax[k];
+    if(d <= eps)
+    {
+      continue;
+    }
+    Standard_Real CMin = CoordMin[k];
+    Standard_Real CMax = CoordMax[k];
+    for(i = 1; i <= Nu; ++i)
+    {
+      if(aPnts(i).Coord(k+1) - CMin < d)
+      {
+        Standard_Real umin, umax;
+        umin = UMin + Max(0, i-2) * du;
+        umax = UMin + Min(Nu-1, i) * du;
+        Standard_Real cmin = AdjustExtr(C, umin, umax,
+                                        CMin, k + 1, eps, Standard_True);
+        if(cmin < CMin)
+        {
+          CMin = cmin;
+        }
+      }
+      else if(CMax - aPnts(i).Coord(k+1) < d)
+      {
+        Standard_Real umin, umax;
+        umin = UMin + Max(0, i-2) * du;
+        umax = UMin + Min(Nu-1, i) * du;
+        Standard_Real cmax = AdjustExtr(C, umin, umax,
+                                        CMax, k + 1, eps, Standard_False);
+        if(cmax > CMax)
+        {
+          CMax = cmax;
+        }
+      }
+    }
+    CoordMin[k] = CMin;
+    CoordMax[k] = CMax;
+  }
+
+  B.Add(gp_Pnt(CoordMin[0], CoordMin[1], CoordMin[2]));
+  B.Add(gp_Pnt(CoordMax[0], CoordMax[1], CoordMax[2]));
+  B.Enlarge(eps);
+}
+//
+class CurvMaxMinCoordMVar : public math_MultipleVarFunction
+{
+public:
+  CurvMaxMinCoordMVar(const Adaptor3d_Curve& theCurve, 
+                      const Standard_Real UMin,
+                      const Standard_Real UMax,
+                      const Standard_Integer CoordIndx,                                 
+                      const Standard_Real Sign)
+: myCurve(theCurve),
+  myUMin(UMin),
+  myUMax(UMax),
+  myCoordIndx(CoordIndx),
+  mySign(Sign)
+  {
+  }
+
+  Standard_Boolean Value (const math_Vector& X,
+                                Standard_Real& F)
+  {
+    if (!CheckInputData(X(1)))
+    {
+      return Standard_False;
+    }
+    gp_Pnt aP = myCurve.Value(X(1));
+
+    F = mySign * aP.Coord(myCoordIndx);
+
+    return Standard_True;
+  }
+
+  
+
+  Standard_Integer NbVariables() const
+  {
+    return 1;
+  }
+
+private:
+  CurvMaxMinCoordMVar & operator = (const CurvMaxMinCoordMVar & theOther);
+
+  Standard_Boolean CheckInputData(Standard_Real theParam)
+  {
+    if (theParam < myUMin || 
+        theParam > myUMax)
+      return Standard_False;
+    return Standard_True;
+  }
+
+  const Adaptor3d_Curve& myCurve;
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Integer myCoordIndx;
+  Standard_Real mySign;
+};
+//
+class CurvMaxMinCoord : public math_Function
+{
+public:
+  CurvMaxMinCoord(const Adaptor3d_Curve& theCurve, 
+                  const Standard_Real UMin,
+                  const Standard_Real UMax,
+                  const Standard_Integer CoordIndx,                                 
+                  const Standard_Real Sign)
+: myCurve(theCurve),
+  myUMin(UMin),
+  myUMax(UMax),
+  myCoordIndx(CoordIndx),
+  mySign(Sign)
+  {
+  }
+
+  Standard_Boolean Value (const Standard_Real X,
+                                Standard_Real& F)
+  {
+    if (!CheckInputData(X))
+    {
+      return Standard_False;
+    }
+    gp_Pnt aP = myCurve.Value(X);
+
+    F = mySign * aP.Coord(myCoordIndx);
+
+    return Standard_True;
+  }
+
+private:
+  CurvMaxMinCoord & operator = (const CurvMaxMinCoord & theOther);
+
+  Standard_Boolean CheckInputData(Standard_Real theParam)
+  {
+    if (theParam < myUMin || 
+        theParam > myUMax)
+      return Standard_False;
+    return Standard_True;
+  }
+
+  const Adaptor3d_Curve& myCurve;
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Integer myCoordIndx;
+  Standard_Real mySign;
+};
+
+//=======================================================================
+//function : AdjustExtr
+//purpose  : 
+//=======================================================================
+
+Standard_Real AdjustExtr(const Adaptor3d_Curve& C, 
+                         const Standard_Real UMin,
+                         const Standard_Real UMax,
+                         const Standard_Real Extr0,
+                         const Standard_Integer CoordIndx,                                 
+                         const Standard_Real Tol, 
+                         const Standard_Boolean IsMin)
+{
+  Standard_Real aSign = IsMin ? 1.:-1.;
+  Standard_Real extr = aSign * Extr0;
+  //
+  Standard_Real uTol = Max(C.Resolution(Tol), Precision::PConfusion());
+  Standard_Real Du = (C.LastParameter() - C.FirstParameter());
+  //
+  Standard_Real reltol = uTol / Max(Abs(UMin), Abs(UMax));
+  if(UMax - UMin < 0.01 * Du)
+  {
+
+    math_BrentMinimum anOptLoc(reltol, 100, uTol);
+    CurvMaxMinCoord aFunc(C, UMin, UMax, CoordIndx, aSign);
+    anOptLoc.Perform(aFunc, UMin, (UMin+UMax)/2., UMax);
+    if(anOptLoc.IsDone())
+    {
+      extr = anOptLoc.Minimum();
+      return aSign * extr;
+    }
+  }
+  //
+  Standard_Integer aNbParticles = Max(8, RealToInt(32 * (UMax - UMin) / Du));
+  Standard_Real maxstep = (UMax - UMin) / (aNbParticles + 1);
+  math_Vector aT(1,1);
+  math_Vector aLowBorder(1,1);
+  math_Vector aUppBorder(1,1);
+  math_Vector aSteps(1,1);
+  aLowBorder(1) = UMin;
+  aUppBorder(1) = UMax;
+  aSteps(1) = Min(0.1 * Du, maxstep);
+
+  CurvMaxMinCoordMVar aFunc(C, UMin, UMax, CoordIndx, aSign);
+  math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles); 
+  aFinder.Perform(aSteps, extr, aT);
+  //
+  math_BrentMinimum anOptLoc(reltol, 100, uTol);
+  CurvMaxMinCoord aFunc1(C, UMin, UMax, CoordIndx, aSign);
+  anOptLoc.Perform(aFunc1, Max(aT(1) - aSteps(1), UMin), aT(1), Min(aT(1) + aSteps(1), UMax));
+
+  if(anOptLoc.IsDone())
+  {
+    extr = anOptLoc.Minimum();
+    return aSign * extr;
+  }
+
+  return aSign * extr;
+}
+
+//=======================================================================
+//function : NbSamples
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NbSamples(const Adaptor3d_Curve& C, 
+                           const Standard_Real Umin,
+                           const Standard_Real Umax) 
+{
+  Standard_Integer N;
+  GeomAbs_CurveType Type = C.GetType();
+  switch (Type) {
+  case GeomAbs_BezierCurve: 
+    {
+      N = 2 * C.NbPoles();
+      //By default parametric range of Bezier curv is [0, 1]
+      Standard_Real du = Umax - Umin;
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  case GeomAbs_BSplineCurve: 
+    {
+      const Handle(Geom_BSplineCurve)& BC = C.BSpline();
+      N = 2 * (BC->Degree() + 1)*(BC->NbKnots() -1);
+      Standard_Real umin = BC->FirstParameter(), 
+                    umax = BC->LastParameter();
+      Standard_Real du = (Umax - Umin) / (umax - umin);
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  default:
+    N = 33;
+  }
+  return Min(500, N);
+}
index 009abe2..4fdee15 100644 (file)
 #include <Standard_Handle.hxx>
 
 #include <Standard_Real.hxx>
+//
 class Adaptor3d_Curve;
 class Bnd_Box;
+class gp_Circ;
+class gp_Elips;
 
 
 //! Computes the bounding box for a curve in 3d.
@@ -92,8 +95,22 @@ public:
   //! numbers, or two positive infinite real numbers.
   Standard_EXPORT static void Add (const Adaptor3d_Curve& C, const Standard_Real U1, const Standard_Real U2, const Standard_Real Tol, Bnd_Box& B);
 
-
-
+  //! Adds to the bounding box B the curve C
+  //! These methods use more precise algorithms for building bnd box
+  //! then methods Add(...)
+  Standard_EXPORT static void AddOptimal (const Adaptor3d_Curve& C, const Standard_Real Tol, Bnd_Box& B);
+  Standard_EXPORT static void AddOptimal (const Adaptor3d_Curve& C, 
+                                          const Standard_Real U1, const Standard_Real U2, 
+                                          const Standard_Real Tol, Bnd_Box& B);
+  //! Adds to the bounding box B the curve C
+  //! using numerical minimization algorithms
+  //! This method is used in AddOptimal for not analytical curves.
+  //! if Tol < Precision::Confusion(), Precision:;Confusion is used as computation tolerance
+  Standard_EXPORT static void AddGenCurv(const Adaptor3d_Curve& C, 
+                                         const Standard_Real UMin,
+                                         const Standard_Real UMax,
+                                         const Standard_Real Tol,
+                                         Bnd_Box& B);
 
 protected:
 
index e2ad6e7..b2f23ce 100644 (file)
 #include <BndLib_AddSurface.hxx>
 #include <BSplCLib.hxx>
 #include <ElSLib.hxx>
+#include <ElCLib.hxx>
 #include <Geom_BezierSurface.hxx>
 #include <Geom_BSplineSurface.hxx>
 #include <GeomAbs_SurfaceType.hxx>
 #include <gp_Pln.hxx>
 #include <gp_Pnt.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Cone.hxx>
+#include <gp_Lin.hxx>
 #include <Precision.hxx>
 #include <TColgp_Array2OfPnt.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColStd_Array1OfReal.hxx>
+#include <BndLib_Add3dCurve.hxx>
+#include <math_MultipleVarFunction.hxx>
+#include <math_PSO.hxx>
+#include <math_Matrix.hxx>
+#include <math_Powell.hxx>
+//
+static Standard_Integer NbUSamples(const Adaptor3d_Surface& S, 
+                                   const Standard_Real Umin,
+                                   const Standard_Real Umax);
+//
+static Standard_Integer NbVSamples(const Adaptor3d_Surface& S, 
+                                   const Standard_Real Vmin,
+                                   const Standard_Real Vmax);
+//
+static Standard_Real  AdjustExtr(const Adaptor3d_Surface& S, 
+                                 const Standard_Real UMin,
+                                                  const Standard_Real UMax,
+                                                  const Standard_Real VMin,
+                                                  const Standard_Real VMax,
+                                 const Standard_Real Extr0,
+                                 const Standard_Integer CoordIndx,                                 
+                                 const Standard_Real Tol, 
+                                 const Standard_Boolean IsMin);
 
 //=======================================================================
 //function : Add
@@ -450,3 +477,502 @@ void BndLib_AddSurface::Add(const Adaptor3d_Surface& S,
     }
   }
 }
+//----- Methods for AddOptimal ---------------------------------------
+
+//=======================================================================
+//function : AddOptimal
+//purpose  : 
+//=======================================================================
+void BndLib_AddSurface::AddOptimal(const Adaptor3d_Surface& S,
+                                                    const Standard_Real Tol,
+                                                    Bnd_Box& B ) 
+{
+
+  BndLib_AddSurface::AddOptimal(S,
+                                                 S.FirstUParameter(),
+                                                 S.LastUParameter (),
+                                                 S.FirstVParameter(),
+                                                 S.LastVParameter (),Tol,B);
+}
+//=======================================================================
+//function : AddOptimal
+//purpose  : 
+//=======================================================================
+
+void BndLib_AddSurface::AddOptimal(const Adaptor3d_Surface& S,
+                           const Standard_Real UMin,
+                           const Standard_Real UMax,
+                           const Standard_Real VMin,
+                           const Standard_Real VMax,
+                           const Standard_Real Tol,
+                           Bnd_Box& B ) 
+{
+  GeomAbs_SurfaceType Type = S.GetType(); 
+
+  if (Precision::IsInfinite(VMin) ||
+      Precision::IsInfinite(VMax) ||
+      Precision::IsInfinite(UMin) ||
+      Precision::IsInfinite(UMax)   ) {
+    switch (Type) {
+      case GeomAbs_Plane: 
+      {
+        TreatInfinitePlane(S.Plane(), UMin, UMax, VMin, VMax, Tol, B);
+        return;
+      }
+      default: 
+      {
+             B.SetWhole();
+             return;
+      }
+    }
+  }
+
+  switch (Type) {
+    
+    case GeomAbs_Plane: 
+    {
+      gp_Pln Plan = S.Plane();
+      B.Add(ElSLib::Value(UMin,VMin,Plan)); 
+      B.Add(ElSLib::Value(UMin,VMax,Plan)); 
+      B.Add(ElSLib::Value(UMax,VMin,Plan)); 
+      B.Add(ElSLib::Value(UMax,VMax,Plan)); 
+      B.Enlarge(Tol);
+      break;
+    }
+    case GeomAbs_Cylinder: 
+    {
+      BndLib::Add(S.Cylinder(), UMin, UMax, VMin, VMax, Tol, B);
+      break;
+    }
+    case GeomAbs_Cone: 
+    {
+      BndLib::Add(S.Cone(), UMin, UMax, VMin, VMax, Tol, B);
+      break;
+    }
+    case GeomAbs_Sphere: 
+    {
+      BndLib::Add(S.Sphere(), UMin, UMax, VMin, VMax, Tol, B); 
+      break;
+    }
+    default: 
+    {
+      AddGenSurf(S, UMin, UMax, VMin, VMax, Tol, B);
+    }
+  }
+}
+//=======================================================================
+//function : AddGenSurf
+//purpose  : 
+//=======================================================================
+void BndLib_AddSurface::AddGenSurf(const Adaptor3d_Surface& S, 
+                                   const Standard_Real UMin,
+                                   const Standard_Real UMax,
+                                   const Standard_Real VMin,
+                                   const Standard_Real VMax,
+                                   const Standard_Real Tol,
+                                   Bnd_Box& B)
+{
+  Standard_Integer Nu = NbUSamples(S, UMin, UMax);
+  Standard_Integer Nv = NbVSamples(S, VMin, VMax);
+  //
+  Standard_Real CoordMin[3] = {RealLast(), RealLast(), RealLast()}; 
+  Standard_Real CoordMax[3] = {-RealLast(), -RealLast(), -RealLast()};
+  Standard_Real DeflMax[3] = {-RealLast(), -RealLast(), -RealLast()};
+  //
+  //
+  Standard_Real du = (UMax-UMin)/(Nu-1), du2 = du / 2.;
+  Standard_Real dv = (VMax-VMin)/(Nv-1), dv2 = dv / 2.;
+  NCollection_Array2<gp_XYZ> aPnts(1, Nu, 1, Nv);
+  Standard_Real u, v;
+  Standard_Integer i, j, k;
+  gp_Pnt P;
+  for (i = 1, u = UMin; i <= Nu; i++, u += du){
+    for (j = 1, v = VMin;j <= Nv; j++, v += dv){
+      S.D0(u,v,P);
+      aPnts(i, j) = P.XYZ();
+      //
+      for(k = 0; k < 3; ++k)
+      {
+        if(CoordMin[k] > P.Coord(k+1))
+        {
+          CoordMin[k] = P.Coord(k+1);
+        }
+        if(CoordMax[k] < P.Coord(k+1))
+        {
+          CoordMax[k] = P.Coord(k+1);
+        }
+      }
+      //
+      if(i > 1)
+      {
+        gp_XYZ aPm = 0.5 * (aPnts(i-1,j) + aPnts(i, j));
+        S.D0(u - du2, v, P);
+        gp_XYZ aD = (P.XYZ() - aPm);
+        for(k = 0; k < 3; ++k)
+        {
+          if(CoordMin[k] > P.Coord(k+1))
+          {
+            CoordMin[k] = P.Coord(k+1);
+          }
+          if(CoordMax[k] < P.Coord(k+1))
+          {
+            CoordMax[k] = P.Coord(k+1);
+          }
+          Standard_Real d = Abs(aD.Coord(k+1));
+          if(DeflMax[k] < d)
+          {
+            DeflMax[k] = d;
+          }
+        }
+      }
+      if(j > 1)
+      {
+        gp_XYZ aPm = 0.5 * (aPnts(i,j-1) + aPnts(i, j));
+        S.D0(u , v - dv2, P);
+        gp_XYZ aD = (P.XYZ() - aPm);
+        for(k = 0; k < 3; ++k)
+        {
+          if(CoordMin[k] > P.Coord(k+1))
+          {
+            CoordMin[k] = P.Coord(k+1);
+          }
+          if(CoordMax[k] < P.Coord(k+1))
+          {
+            CoordMax[k] = P.Coord(k+1);
+          }
+          Standard_Real d = Abs(aD.Coord(k+1));
+          if(DeflMax[k] < d)
+          {
+            DeflMax[k] = d;
+          }
+        }
+      }
+    }
+  }
+  //
+  //Adjusting minmax 
+  Standard_Real eps = Max(Tol, Precision::Confusion()); 
+  for(k = 0; k < 3; ++k)
+  {
+    Standard_Real d = DeflMax[k];
+    if(d <= eps)
+    {
+      continue;
+    }
+
+    Standard_Real CMin = CoordMin[k];
+    Standard_Real CMax = CoordMax[k];
+    for(i = 1; i <= Nu; ++i)
+    {
+      for(j = 1; j <= Nv; ++j)
+      {
+        if(aPnts(i,j).Coord(k+1) - CMin < d)
+        {
+          Standard_Real umin, umax, vmin, vmax;
+          umin = UMin + Max(0, i-2) * du;
+          umax = UMin + Min(Nu-1, i) * du;
+          vmin = VMin + Max(0, j-2) * dv;
+          vmax = VMin + Min(Nv-1, j) * dv;
+          Standard_Real cmin = AdjustExtr(S, umin, umax, vmin, vmax,
+                                          CMin, k + 1, eps, Standard_True);
+          if(cmin < CMin)
+          {
+            CMin = cmin;
+          }
+        }
+        else if(CMax - aPnts(i,j).Coord(k+1) < d)
+        {
+          Standard_Real umin, umax, vmin, vmax;
+          umin = UMin + Max(0, i-2) * du;
+          umax = UMin + Min(Nu-1, i) * du;
+          vmin = VMin + Max(0, j-2) * dv;
+          vmax = VMin + Min(Nv-1, j) * dv;
+          Standard_Real cmax = AdjustExtr(S, umin, umax, vmin, vmax,
+                                          CMax, k + 1, eps, Standard_False);
+          if(cmax > CMax)
+          {
+            CMax = cmax;
+          }
+        }
+      }
+    }
+    CoordMin[k] = CMin;
+    CoordMax[k] = CMax;
+
+  }
+
+  B.Add(gp_Pnt(CoordMin[0], CoordMin[1], CoordMin[2]));
+  B.Add(gp_Pnt(CoordMax[0], CoordMax[1], CoordMax[2]));
+  B.Enlarge(eps);
+}
+//
+
+//
+class SurfMaxMinCoord : public math_MultipleVarFunction
+{
+public:
+  SurfMaxMinCoord(const Adaptor3d_Surface& theSurf, 
+              const Standard_Real UMin,
+              const Standard_Real UMax,
+              const Standard_Real VMin,
+              const Standard_Real VMax,
+              const Standard_Integer CoordIndx,                                 
+              const Standard_Real Sign)
+: mySurf(theSurf),
+  myUMin(UMin),
+  myUMax(UMax),
+  myVMin(VMin),
+  myVMax(VMax),
+  myCoordIndx(CoordIndx),
+  mySign(Sign)
+  {
+    math_Vector X(1,2);
+    X(1) = UMin;
+    X(2) = (VMin + VMax) / 2.;
+    Standard_Real F1, F2;
+    Value(X, F1);
+    X(1) = UMax;
+    Value(X, F2);
+    Standard_Real DU = Abs((F2 - F1) / (UMax - UMin));
+    X(1) = (UMin + UMax) / 2.;
+    X(2) = VMin;
+    Value(X, F1);
+    X(2) = VMax;
+    Value(X, F2);
+    Standard_Real DV = Abs((F2 - F1) / (VMax - VMin));
+    myPenalty = 10. * Max(DU, DV);
+    myPenalty = Max(myPenalty, 1.);
+  }
+
+  Standard_Boolean Value (const math_Vector& X,
+                                  Standard_Real& F)
+  {
+    if (CheckInputData(X))
+    {
+      gp_Pnt aP = mySurf.Value(X(1), X(2));
+      F = mySign * aP.Coord(myCoordIndx);
+    }
+    else
+    {
+      Standard_Real UPen = 0., VPen = 0., u0, v0;
+      if(X(1) < myUMin)
+      {
+        UPen = myPenalty * (myUMin - X(1));
+        u0 = myUMin;
+      }
+      else if(X(1) > myUMax)
+      {
+        UPen = myPenalty * (X(1) - myUMax);
+        u0 = myUMax;
+      }
+      else
+      {
+        u0 = X(1);
+      }
+      //
+      if(X(2) < myVMin)
+      {
+        VPen = myPenalty * (myVMin - X(2));
+        v0 = myVMin;
+      }
+      else if(X(2) > myVMax)
+      {
+        VPen = myPenalty * (X(2) - myVMax);
+        v0 = myVMax;
+      }
+      else
+      {
+        v0 = X(2);
+      }
+      //
+      gp_Pnt aP = mySurf.Value(u0, v0);
+      F = mySign * aP.Coord(myCoordIndx) + UPen + VPen;
+    }
+
+    return Standard_True;
+  }
+
+  
+
+  Standard_Integer NbVariables() const
+  {
+    return 2;
+  }
+
+private:
+  SurfMaxMinCoord & operator = (const SurfMaxMinCoord & theOther);
+
+  Standard_Boolean CheckInputData(const math_Vector theParams)
+  {
+    if (theParams(1) < myUMin || 
+        theParams(1) > myUMax || 
+        theParams(2) < myVMin || 
+        theParams(2) > myVMax)
+      return Standard_False;
+    return Standard_True;
+  }
+
+  const Adaptor3d_Surface& mySurf;
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Real myVMin;
+  Standard_Real myVMax;
+  Standard_Integer myCoordIndx;
+  Standard_Real mySign;
+  Standard_Real myPenalty;
+};
+
+//=======================================================================
+//function : AdjustExtr
+//purpose  : 
+//=======================================================================
+
+Standard_Real AdjustExtr(const Adaptor3d_Surface& S, 
+                         const Standard_Real UMin,
+                         const Standard_Real UMax,
+                         const Standard_Real VMin,
+                         const Standard_Real VMax,
+                         const Standard_Real Extr0,
+                         const Standard_Integer CoordIndx,                                 
+                         const Standard_Real Tol, 
+                         const Standard_Boolean IsMin)
+{
+  Standard_Real aSign = IsMin ? 1.:-1.;
+  Standard_Real extr = aSign * Extr0;
+  Standard_Real relTol = 2.*Tol;
+  if(Abs(extr) > Tol)
+  {
+    relTol /= Abs(extr);
+  }
+  Standard_Real Du = (S.LastUParameter() - S.FirstUParameter());
+  Standard_Real Dv = (S.LastVParameter() - S.FirstVParameter());
+  //
+  math_Vector aT(1,2);
+  math_Vector aLowBorder(1,2);
+  math_Vector aUppBorder(1,2);
+  math_Vector aSteps(1,2);
+  aLowBorder(1) = UMin;
+  aUppBorder(1) = UMax;
+  aLowBorder(2) = VMin;
+  aUppBorder(2) = VMax;
+
+  Standard_Integer aNbU = Max(8, RealToInt(32 * (UMax - UMin) / Du));
+  Standard_Integer aNbV = Max(8, RealToInt(32 * (VMax - VMin) / Dv));
+  Standard_Integer aNbParticles = aNbU * aNbV;
+  Standard_Real aMaxUStep = (UMax - UMin) / (aNbU + 1);
+  aSteps(1) = Min(0.1 * Du, aMaxUStep);  
+  Standard_Real aMaxVStep = (VMax - VMin) / (aNbV + 1);
+  aSteps(2) = Min(0.1 * Dv, aMaxVStep);
+  SurfMaxMinCoord aFunc(S, UMin, UMax, VMin, VMax, CoordIndx, aSign);
+  math_PSO aFinder(&aFunc, aLowBorder, aUppBorder, aSteps, aNbParticles); 
+  aFinder.Perform(aSteps, extr, aT);
+  
+  //Refinement of extremal value
+  math_Matrix aDir(1, 2, 1, 2, 0.0);
+  aDir(1, 1) = 1.;
+  aDir(2, 1) = 0.;
+  aDir(1, 2) = 0.;
+  aDir(2, 2) = 1.;
+
+  Standard_Integer aNbIter = 200;
+  math_Powell powell(aFunc, relTol, aNbIter, Tol);
+  powell.Perform(aFunc, aT, aDir);
+
+  if (powell.IsDone())
+  {
+    powell.Location(aT);
+    extr = powell.Minimum();
+  }
+
+  return aSign * extr;
+}
+
+//=======================================================================
+//function : NbUSamples
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NbUSamples(const Adaptor3d_Surface& S, 
+                            const Standard_Real Umin,
+                            const Standard_Real Umax) 
+{
+  Standard_Integer N;
+  GeomAbs_SurfaceType Type = S.GetType();
+  switch (Type) {
+  case GeomAbs_BezierSurface: 
+    {
+      N = 2*S.NbUPoles();
+      //By default parametric range of Bezier surf is [0, 1] [0, 1]
+      Standard_Real du = Umax - Umin;
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  case GeomAbs_BSplineSurface: 
+    {
+      const Handle(Geom_BSplineSurface)& BS = S.BSpline();
+      N = 2*(BS->UDegree() + 1)*(BS->NbUKnots() -1);
+      Standard_Real umin, umax, vmin, vmax;
+      BS->Bounds(umin, umax, vmin, vmax);
+      Standard_Real du = (Umax - Umin) / (umax - umin);
+      if(du < .9)
+      {
+        N = RealToInt(du*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  default:
+    N = 33;
+  }
+  return Min (50,N);
+}
+
+//=======================================================================
+//function : NbVSamples
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NbVSamples(const Adaptor3d_Surface& S, 
+                            const Standard_Real Vmin,
+                            const Standard_Real Vmax) 
+{
+  Standard_Integer N;
+  GeomAbs_SurfaceType Type = S.GetType();
+  switch (Type) {
+  case GeomAbs_BezierSurface:
+    {
+      N = 2*S.NbVPoles();
+      //By default parametric range of Bezier surf is [0, 1] [0, 1]
+      Standard_Real dv = Vmax - Vmin;
+      if(dv < .9)
+      {
+        N = RealToInt(dv*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  case GeomAbs_BSplineSurface:
+    {
+      const Handle(Geom_BSplineSurface)& BS = S.BSpline();
+      N = 2*(BS->VDegree() + 1)*(BS->NbVKnots() - 1) ;
+     Standard_Real umin, umax, vmin, vmax;
+      BS->Bounds(umin, umax, vmin, vmax);
+      Standard_Real dv = (Vmax - Vmin) / (vmax - vmin);
+      if(dv < .9)
+      {
+        N = RealToInt(dv*N) + 1;
+        N = Max(N, 5);
+      }
+      break;
+    }
+  default:
+    N = 33;
+  }
+  return Min(50,N);
+}
+
index 53e02d5..d44ac71 100644 (file)
@@ -24,7 +24,9 @@
 #include <Standard_Real.hxx>
 class Adaptor3d_Surface;
 class Bnd_Box;
-
+class gp_Cylinder;
+class gp_Cone;
+class gp_Sphere;
 
 //! computes the box from a surface
 //! Functions to add a surface to a bounding box.
@@ -99,18 +101,36 @@ public:
   //! AddSurface::Add ( S, Tol, B );
   Standard_EXPORT static void Add (const Adaptor3d_Surface& S, const Standard_Real UMin, const Standard_Real UMax, const Standard_Real VMin, const Standard_Real VMax, const Standard_Real Tol, Bnd_Box& B);
 
+  //! Adds the surface S to the bounding box B.
+  //! This algorith builds precise bounding box
 
+  Standard_EXPORT static void AddOptimal (const Adaptor3d_Surface& S, const Standard_Real Tol, Bnd_Box& B);
 
+  Standard_EXPORT static void AddOptimal (const Adaptor3d_Surface& S, 
+                                          const Standard_Real UMin, const Standard_Real UMax, 
+                                          const Standard_Real VMin, const Standard_Real VMax, 
+                                          const Standard_Real Tol, Bnd_Box& B);
 
-protected:
 
+  //! Adds to the bounding box B the surface S
+  //! using numerical minimization algorithms
+  //! This method is used in AddOptimal for not analytical surfaces and torus.
+  //! if Tol < Precision::Confusion(), Precision::Confusion is used as computation tolerance
+    Standard_EXPORT static void AddGenSurf(const Adaptor3d_Surface& S, 
+                                           const Standard_Real UMin,
+                                           const Standard_Real UMax,
+                                           const Standard_Real VMin,
+                                           const Standard_Real VMax,
+                                           const Standard_Real Tol,
+                                           Bnd_Box& B);
 
+protected:
 
 
 
-private:
 
 
+private:
 
 
 
index 9cd6af9..1add28e 100644 (file)
@@ -1,7 +1,7 @@
 # test script on make volume operation
 # plane sphere
 
-puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC26020 Windows: Faulty shapes in variables faulty_1 to faulty_"
 puts "TODO OCC26020 ALL: Error: bopcheck failed"
 puts "TODO OCC26020 ALL: Error : The area of result shape is"
 
index 161164c..b553c3f 100644 (file)
@@ -43,4 +43,4 @@ mkface f7 con_f7 0 6.2831853071795862 0 1000000
 # make volume operation 
 mkvolume result f1 f2 f3 f4 f5 f6 f7
 
-checkprops result -s 3.7173e+06
+checkprops result -s 3.76654e+06
index 7ee5533..083d2f1 100644 (file)
@@ -1,10 +1,6 @@
 # test script on make volume operation
 # cone plane killed by cpulimit 300
 
-puts "TODO OCC26020 ALL: Error: bopcheck failed"
-puts "TODO OCC26020 ALL: Error : The area of result shape is"
-puts "TODO OCC26020 ALL: Faulty shapes in variables faulty_1 to"
-
 # planar face 
 plane pln_f1 -460.8377555733228 -1160 -121.8751945104883 0.17364817766693036 -5.955424826592936e-017 -0.98480775301220813
 erase pln_f1
@@ -43,4 +39,4 @@ mkface f7 con_f7 0 6.2831853071795862 0 1000000
 # make volume operation 
 mkvolume result f1 f2 f3 f4 f5 f6 f7
 
-checkprops result -s 0
+checkprops result -s 6.47464e+006
index 450c465..ea5501e 100644 (file)
@@ -1,6 +1,3 @@
-puts "TODO OCC26020 Linux: Error : The area of result shape is"
-puts "TODO OCC26020 Linux: Error: bopcheck failed"
-
 # test script on make volume operation
 # cylinder plane
 
index 8cb01cd..3bed768 100755 (executable)
@@ -15,6 +15,6 @@ vclear
 isos result 0
 triangles result
 
-checktrinfo result -tri 98 -nod 100
+checktrinfo result -tri 101 -nod 103
 checkprops result -s 150.283 
 checkview -display result -3d -path ${imagedir}/${test_image}.png
index 029a3b4..7ab908b 100755 (executable)
@@ -17,6 +17,6 @@ vfit
 isos result 0
 triangles result
 
-checktrinfo result -tri 1145 -nod 831
+checktrinfo result -tri 1111 -nod 814
 checkprops result -s 376.873 
 checkview -screenshot -3d -path ${imagedir}/${test_image}.png
index e2999b7..d6dfcd9 100644 (file)
@@ -18,7 +18,7 @@ if (![regexp {WIRE[ ]+: 1} $mlog]) {
 }
 
 set mlog [bounding a_1_3]
-if (![regexp {(-7.26623440743389) (-8.0984932752388978) (-150.09849327523889) (7.2662344074338865) (8.0984932752388978) (-141.90150672476111)} $mlog]) {
+if (![regexp {(-7.1677412321949925) (-8.0000000999999994) (-150.00000009999999) (7.1677412321949898) (8.0000000999999994) (-141.99999990000001)} $mlog]) {
   set status 0
 }                        
                                 
index d7a8d73..f3799b7 100755 (executable)
@@ -13,7 +13,7 @@ catch {pload XDE}
 set x1 210
 set y1 184
 
-set x2 205
+set x2 207
 set y2 180
 
 stepread [locate_data_file OCC23012-Sample_3.stp] a *