0030889: ACIS Import - Incorrect result reading SAT and SAB files
authoranv <anv@opencascade.com>
Tue, 5 Nov 2019 14:57:25 +0000 (17:57 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 6 Dec 2019 16:32:36 +0000 (19:32 +0300)
Adapting CR30932 fix for a GeomLib approximator.

src/Approx/Approx_CurveOnSurface.cxx
src/GeomLib/GeomLib.cxx
src/GeomLib/GeomLib.hxx
tests/bugs/iges/bug306
tests/de/iges_1/C8
tests/offset/simple/D03

index 9bc11d4..e0c42d2 100644 (file)
@@ -27,6 +27,7 @@
 #include <Geom2d_BSplineCurve.hxx>
 #include <Geom2dAdaptor_HCurve.hxx>
 #include <Geom_BSplineCurve.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <GeomAdaptor_HCurve.hxx>
 #include <GeomAdaptor_HSurface.hxx>
@@ -611,15 +612,69 @@ Standard_Boolean Approx_CurveOnSurface::buildC3dOnIsoLine(const Handle(Adaptor2d
   gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter());
   gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter());
 
+  Standard_Boolean isToTrim = Standard_True;
+  Standard_Real U1, U2, V1, V2;
+  aSurf->Bounds(U1, U2, V1, V2);
+
   if (theIsU)
   {
+    Standard_Real aV1Param = Min(aF2d.Y(), aL2d.Y());
+    Standard_Real aV2Param = Max(aF2d.Y(), aL2d.Y());
+    if (aV2Param < V1 - myTol || aV1Param > V2 + myTol)
+    {
+      return Standard_False;
+    }
+    else if (Precision::IsInfinite(V1) || Precision::IsInfinite(V2))
+    {
+      if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+      {
+        return Standard_False;
+      }
+      aSurf = new Geom_RectangularTrimmedSurface(aSurf, U1, U2, aV1Param, aV2Param);
+      isToTrim = Standard_False;
+    }
+    else
+    {
+      aV1Param = Max(aV1Param, V1);
+      aV2Param = Min(aV2Param, V2);
+      if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+      {
+        return Standard_False;
+      }
+    }
     aC3d = aSurf->UIso(theParam);
-    aC3d = new Geom_TrimmedCurve(aC3d, aF2d.Y(), aL2d.Y());
+    if (isToTrim)
+      aC3d = new Geom_TrimmedCurve(aC3d, aV1Param, aV2Param);
   }
   else
   {
+    Standard_Real aU1Param = Min(aF2d.X(), aL2d.X());
+    Standard_Real aU2Param = Max(aF2d.X(), aL2d.X());
+    if (aU2Param < U1 - myTol || aU1Param > U2 + myTol)
+    {
+      return Standard_False;
+    }
+    else if (Precision::IsInfinite(U1) || Precision::IsInfinite(U2))
+    {
+      if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+      {
+        return Standard_False;
+      }
+      aSurf = new Geom_RectangularTrimmedSurface(aSurf, aU1Param, aU2Param, V1, V2);
+      isToTrim = Standard_False;
+    }
+    else
+    {
+      aU1Param = Max(aU1Param, U1);
+      aU2Param = Min(aU2Param, U2);
+      if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+      {
+        return Standard_False;
+      }
+    }
     aC3d = aSurf->VIso(theParam);
-    aC3d = new Geom_TrimmedCurve(aC3d, aF2d.X(), aL2d.X());
+    if (isToTrim)
+      aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
   }
 
   // Convert arbitrary curve type to the b-spline.
index 97adc60..f357273 100644 (file)
@@ -48,6 +48,7 @@
 #include <Adaptor3d_HSurface.hxx>
 #include <AdvApprox_ApproxAFunction.hxx>
 #include <AdvApprox_PrefAndRec.hxx>
+#include <Approx_CurveOnSurface.hxx>
 #include <BSplCLib.hxx>
 #include <BSplSLib.hxx>
 #include <CSLib.hxx>
@@ -1095,7 +1096,6 @@ void GeomLib::BuildCurve3d(const Standard_Real           Tolerance,
 {
    
 
-  Standard_Integer curve_not_computed = 1 ;
   MaxDeviation     = 0.0e0 ;
   AverageDeviation = 0.0e0 ;
   Handle(GeomAdaptor_HSurface) geom_adaptor_surface_ptr (Handle(GeomAdaptor_HSurface)::DownCast(Curve.GetSurface()) );
@@ -1126,11 +1126,23 @@ void GeomLib::BuildCurve3d(const Standard_Real           Tolerance,
       NewCurvePtr = 
        GeomLib::To3d(axes,
                      geom2d_curve.Curve());
-     curve_not_computed = 0 ;
+      return;
       
     }
+
+    Handle(Adaptor2d_HCurve2d) TrimmedC2D = geom_adaptor_curve_ptr->Trim (FirstParameter, LastParameter, Precision::PConfusion());
+
+    Standard_Boolean isU, isForward;
+    Standard_Real aParam;
+    if (isIsoLine(TrimmedC2D, isU, aParam, isForward))
+    {
+      NewCurvePtr = buildC3dOnIsoLine (TrimmedC2D, geom_adaptor_surface_ptr, FirstParameter, LastParameter, Tolerance, isU, aParam, isForward);
+      if (!NewCurvePtr.IsNull())
+      {
+        return;
+      }
+    }
   }
-  if (curve_not_computed) {
 
       //
       // Entree
@@ -1182,7 +1194,6 @@ void GeomLib::BuildCurve3d(const Standard_Real           Tolerance,
       AverageDeviation = anApproximator.AverageError(3,1) ;
       NewCurvePtr = aCurvePtr ;
     }
-  }  
  }
 
 //=======================================================================
@@ -2783,3 +2794,218 @@ static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1,
   //
   return Standard_True;
 }
+
+//=============================================================================
+//function : isIsoLine
+//purpose  :
+//=============================================================================
+Standard_Boolean GeomLib::isIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+                                     Standard_Boolean&                theIsU,
+                                     Standard_Real&                   theParam,
+                                     Standard_Boolean&                theIsForward)
+{
+  // These variables are used to check line state (vertical or horizontal).
+  Standard_Boolean isAppropriateType = Standard_False;
+  gp_Pnt2d aLoc2d;
+  gp_Dir2d aDir2d;
+
+  // Test type.
+  const GeomAbs_CurveType aType = theC2D->GetType();
+  if (aType == GeomAbs_Line)
+  {
+    gp_Lin2d aLin2d = theC2D->Line();
+    aLoc2d = aLin2d.Location();
+    aDir2d = aLin2d.Direction();
+    isAppropriateType = Standard_True;
+  }
+  else if (aType == GeomAbs_BSplineCurve)
+  {
+    Handle(Geom2d_BSplineCurve) aBSpline2d = theC2D->BSpline();
+    if (aBSpline2d->Degree() != 1 || aBSpline2d->NbPoles() != 2)
+      return Standard_False; // Not a line or uneven parameterization.
+
+    aLoc2d = aBSpline2d->Pole(1);
+
+    // Vector should be non-degenerated.
+    gp_Vec2d aVec2d(aBSpline2d->Pole(1), aBSpline2d->Pole(2));
+    if (aVec2d.SquareMagnitude() < Precision::Confusion())
+      return Standard_False; // Degenerated spline.
+    aDir2d = aVec2d;
+
+    isAppropriateType = Standard_True;
+  }
+  else if (aType == GeomAbs_BezierCurve)
+  {
+    Handle(Geom2d_BezierCurve) aBezier2d = theC2D->Bezier();
+    if (aBezier2d->Degree() != 1 || aBezier2d->NbPoles() != 2)
+      return Standard_False; // Not a line or uneven parameterization.
+
+    aLoc2d = aBezier2d->Pole(1);
+
+    // Vector should be non-degenerated.
+    gp_Vec2d aVec2d(aBezier2d->Pole(1), aBezier2d->Pole(2));
+    if (aVec2d.SquareMagnitude() < Precision::Confusion())
+      return Standard_False; // Degenerated spline.
+    aDir2d = aVec2d;
+
+    isAppropriateType = Standard_True;
+  }
+
+  if (!isAppropriateType)
+    return Standard_False;
+
+  // Check line to be vertical or horizontal.
+  if (aDir2d.IsParallel(gp::DX2d(), Precision::Angular()))
+  {
+    // Horizontal line. V = const.
+    theIsU = Standard_False;
+    theParam = aLoc2d.Y();
+    theIsForward = aDir2d.Dot(gp::DX2d()) > 0.0;
+    return Standard_True;
+  }
+  else if (aDir2d.IsParallel(gp::DY2d(), Precision::Angular()))
+  {
+    // Vertical line. U = const.
+    theIsU = Standard_True;
+    theParam = aLoc2d.X();
+    theIsForward = aDir2d.Dot(gp::DY2d()) > 0.0;
+    return Standard_True;
+  }
+
+  return Standard_False;
+}
+
+//=============================================================================
+//function : buildC3dOnIsoLine
+//purpose  :
+//=============================================================================
+Handle(Geom_Curve) GeomLib::buildC3dOnIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+                                               const Handle(Adaptor3d_HSurface) theSurf,
+                                               const Standard_Real              theFirst,
+                                               const Standard_Real              theLast,
+                                               const Standard_Real              theTolerance,
+                                               const Standard_Boolean           theIsU,
+                                               const Standard_Real              theParam,
+                                               const Standard_Boolean           theIsForward)
+{
+  // Convert adapter to the appropriate type.
+  Handle(GeomAdaptor_HSurface) aGeomAdapter = Handle(GeomAdaptor_HSurface)::DownCast(theSurf);
+  if (aGeomAdapter.IsNull())
+    return Handle(Geom_Curve)();
+
+  if (theSurf->GetType() == GeomAbs_Sphere)
+    return Handle(Geom_Curve)();
+
+  // Extract isoline
+  Handle(Geom_Surface) aSurf = aGeomAdapter->ChangeSurface().Surface();
+  Handle(Geom_Curve) aC3d;
+
+  gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter());
+  gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter());
+
+  Standard_Boolean isToTrim = Standard_True;
+  Standard_Real U1, U2, V1, V2;
+  aSurf->Bounds(U1, U2, V1, V2);
+
+  if (theIsU)
+  {
+    Standard_Real aV1Param = Min(aF2d.Y(), aL2d.Y());
+    Standard_Real aV2Param = Max(aF2d.Y(), aL2d.Y());
+    if (aV2Param < V1 - theTolerance || aV1Param > V2 + theTolerance)
+    {
+      return Handle(Geom_Curve)();
+    }
+    else if (Precision::IsInfinite(V1) || Precision::IsInfinite(V2))
+    {
+      if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+      {
+        return Handle(Geom_Curve)();
+      }
+      aSurf = new Geom_RectangularTrimmedSurface(aSurf, U1, U2, aV1Param, aV2Param);
+      isToTrim = Standard_False;
+    }
+    else
+    {
+      aV1Param = Max(aV1Param, V1);
+      aV2Param = Min(aV2Param, V2);
+      if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+      {
+        return Handle(Geom_Curve)();
+      }
+    }
+    aC3d = aSurf->UIso(theParam);
+    if (isToTrim)
+      aC3d = new Geom_TrimmedCurve(aC3d, aV1Param, aV2Param);
+  }
+  else
+  {
+    Standard_Real aU1Param = Min(aF2d.X(), aL2d.X());
+    Standard_Real aU2Param = Max(aF2d.X(), aL2d.X());
+    if (aU2Param < U1 - theTolerance || aU1Param > U2 + theTolerance)
+    {
+      return Handle(Geom_Curve)();
+    }
+    else if (Precision::IsInfinite(U1) || Precision::IsInfinite(U2))
+    {
+      if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+      {
+        return Handle(Geom_Curve)();
+      }
+      aSurf = new Geom_RectangularTrimmedSurface(aSurf, aU1Param, aU2Param, V1, V2);
+      isToTrim = Standard_False;
+    }
+    else
+    {
+      aU1Param = Max(aU1Param, U1);
+      aU2Param = Min(aU2Param, U2);
+      if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+      {
+        return Handle(Geom_Curve)();
+      }
+    }
+    aC3d = aSurf->VIso(theParam);
+    if (isToTrim)
+      aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
+  }
+
+  // Convert arbitrary curve type to the b-spline.
+  Handle(Geom_BSplineCurve) aCurve3d = GeomConvert::CurveToBSplineCurve(aC3d, Convert_QuasiAngular);
+  if (!theIsForward)
+    aCurve3d->Reverse();
+
+  // Rebuild parameterization for the 3d curve to have the same parameterization with
+  // a two-dimensional curve. 
+  TColStd_Array1OfReal aKnots = aCurve3d->Knots();
+  BSplCLib::Reparametrize(theC2D->FirstParameter(), theC2D->LastParameter(), aKnots);
+  aCurve3d->SetKnots(aKnots);
+
+  // Evaluate error.
+  Standard_Real anError3d = 0.0;
+
+  const Standard_Real aParF = theFirst;
+  const Standard_Real aParL = theLast;
+  const Standard_Integer aNbPnt = 23;
+  for (Standard_Integer anIdx = 0; anIdx <= aNbPnt; ++anIdx)
+  {
+    const Standard_Real aPar = aParF + ((aParL - aParF) * anIdx) / aNbPnt;
+
+    const gp_Pnt2d aPnt2d = theC2D->Value(aPar);
+
+    const gp_Pnt aPntC3D = aCurve3d->Value(aPar);
+    const gp_Pnt aPntC2D = theSurf->Value(aPnt2d.X(), aPnt2d.Y());
+
+    const Standard_Real aSqDeviation = aPntC3D.SquareDistance(aPntC2D);
+    anError3d = Max (aSqDeviation, anError3d);
+  }
+
+  anError3d = Sqrt(anError3d);
+
+  // Target tolerance is not obtained. This situation happens for isolines on the sphere.
+  // OCCT is unable to convert it keeping original parameterization, while the geometric
+  // form of the result is entirely identical. In that case, it is better to utilize
+  // a general-purpose approach. 
+  if (anError3d > theTolerance)
+    return Handle(Geom_Curve)();
+
+  return aCurve3d;
+}
index b51028d..f77b997 100644 (file)
@@ -34,6 +34,8 @@ class gp_Ax2;
 class Geom2d_Curve;
 class gp_GTrsf2d;
 class Adaptor3d_CurveOnSurface;
+class Adaptor2d_HCurve2d;
+class Adaptor3d_HSurface;
 class Geom_BoundedCurve;
 class gp_Pnt;
 class gp_Vec;
@@ -223,10 +225,35 @@ public:
                                                         const Standard_Real V2,
                                                         const Standard_Real Tol);
 
-protected:
-
+  //! Checks whether the 2d curve is a isoline. It can be represented by b-spline, bezier,
+  //! or geometric line. This line should have natural parameterization.
+  //! @param theC2D       Trimmed curve to be checked.
+  //! @param theIsU       Flag indicating that line is u const.
+  //! @param theParam     Line parameter.
+  //! @param theIsForward Flag indicating forward parameterization on a isoline.
+  //! @return Standard_True when 2d curve is a line and Standard_False otherwise.
+  Standard_EXPORT static Standard_Boolean isIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+                                                     Standard_Boolean&                theIsU,
+                                                     Standard_Real&                   theParam,
+                                                     Standard_Boolean&                theIsForward);
 
+  //! Builds 3D curve for a isoline. This method takes corresponding isoline from
+  //! the input surface.
+  //! @param theC2D   Trimmed curve to be approximated.
+  //! @param theIsU   Flag indicating that line is u const.
+  //! @param theParam Line parameter.
+  //! @param theIsForward Flag indicating forward parameterization on a isoline.
+  //! @return Standard_True when 3d curve is built and Standard_False otherwise.
+  Standard_EXPORT static Handle(Geom_Curve) buildC3dOnIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+                                                               const Handle(Adaptor3d_HSurface) theSurf,
+                                                               const Standard_Real              theFirst,
+                                                               const Standard_Real              theLast,
+                                                               const Standard_Real              theTolerance,
+                                                               const Standard_Boolean           theIsU,
+                                                               const Standard_Real              theParam,
+                                                               const Standard_Boolean           theIsForward);
 
+protected:
 
 
 private:
index 8b543c2..0e84434 100755 (executable)
@@ -20,9 +20,9 @@ vsetdispmode result 1
 vdisplay result
 vfit
 
-checktrinfo result -tri 5810 -nod 5806
+checktrinfo result -tri 5812 -nod 5809
 
 checkmaxtol result -ref 0.92213088179312575
 checknbshapes result -shell 1
-checkfreebounds result 265
+checkfreebounds result 239
 checkview -display result -3d -path ${imagedir}/${test_image}.png
index 62ed50d..e693b94 100644 (file)
@@ -1,9 +1,11 @@
 # !!!! This file is generated automatically, do not edit manually! See end script
+puts "TODO CR30889 ALL: TPSTAT : Faulty" 
+
 set filename CTS21866.igs
 
 set ref_data {
 DATA        : Faulties = 0  ( 0 )  Warnings = 0  ( 11531 )  Summary  = 0  ( 11531 )
-TPSTAT      : Faulties = 0  ( 0 )  Warnings = 89  ( 91 )  Summary  = 89  ( 91 )
+TPSTAT      : Faulties = 0  ( 0 )  Warnings = 92  ( 91 )  Summary  = 92  ( 91 )
 CHECKSHAPE  : Wires    = 0  ( 0 )  Faces    = 0  ( 0 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
 NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 1459  ( 1459 ) 
 STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 1459  ( 1459 )   FreeWire = 0  ( 0 ) 
index be241e1..a22a491 100644 (file)
@@ -6,4 +6,4 @@ set OffsetValue 10.0
 
 # Reference data.
 set ExpectedMass 178976
-set ExpectedMaxTol 0.479111
+set ExpectedMaxTol 0.470985