0027107: ShapeAnalysis_Surface should use GeomAdaptor_Surface for surface evaluation
authorabv <abv@opencascade.com>
Sun, 14 Feb 2016 08:16:24 +0000 (11:16 +0300)
committerabv <abv@opencascade.com>
Sat, 20 Feb 2016 07:10:07 +0000 (10:10 +0300)
ShapeAnalysis_Surface is improved to use adaptor for evaluation of points on a surface.
Useless field myExtSur is removed.
DE tests are amended according to induced changes (number of edges varied).

src/ShapeAnalysis/ShapeAnalysis_Surface.cxx
src/ShapeAnalysis/ShapeAnalysis_Surface.hxx
src/ShapeAnalysis/ShapeAnalysis_Surface.lxx
tests/de/iges_1/N9
tests/de/iges_1/P5
tests/de/iges_1/R8
tests/de/step_3/E6

index 405ec64..2611cd4 100644 (file)
@@ -74,7 +74,8 @@ ShapeAnalysis_Surface::ShapeAnalysis_Surface(const Handle(Geom_Surface)& S) :
        myIsoBoxes (Standard_False),
        myGap (0.), myUDelt (0.01), myVDelt (0.01), myUCloseVal (-1), myVCloseVal (-1)
 {
-  S->Bounds(myUF,myUL,myVF,myVL);
+  mySurf->Bounds(myUF,myUL,myVF,myVL);
+  myAdSur = new GeomAdaptor_HSurface (mySurf);
 }
 
 //=======================================================================
@@ -86,10 +87,11 @@ void ShapeAnalysis_Surface::Init(const Handle(Geom_Surface)& S)
 {
   if (mySurf == S) return;
   myExtOK = Standard_False; //:30
-  mySurf = S;  myAdSur.Nullify();
+  mySurf = S;
   myNbDeg = -1;
   myUCloseVal = myVCloseVal = -1;  myGap = 0.;
   mySurf->Bounds (myUF,myUL,myVF,myVL);
+  myAdSur = new GeomAdaptor_HSurface (mySurf);
   myIsos = Standard_False;
   myIsoBoxes = Standard_False;
   myIsoUF.Nullify(); myIsoUL.Nullify(); myIsoVF.Nullify(); myIsoVL.Nullify();
@@ -117,8 +119,6 @@ void ShapeAnalysis_Surface::Init(const Handle(ShapeAnalysis_Surface)& other)
 
 const Handle(GeomAdaptor_HSurface)& ShapeAnalysis_Surface::Adaptor3d()
 {
-  if (myAdSur.IsNull() && !mySurf.IsNull())
-    myAdSur = new GeomAdaptor_HSurface (mySurf);
   return myAdSur;
 }
 
@@ -191,19 +191,19 @@ void ShapeAnalysis_Surface::ComputeSingularities()
           (mySurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))) { //rln S4135
 
     //rln S4135 //:r3
-    myP3d     [0] = mySurf->Value (su1, 0.5 * (sv1 + sv2));
+    myP3d     [0] = myAdSur->Value (su1, 0.5 * (sv1 + sv2));
     myFirstP2d[0].SetCoord (su1, sv2); 
     myLastP2d [0].SetCoord (su1, sv1);
 
-    myP3d     [1] = mySurf->Value (su2, 0.5 * (sv1 + sv2));
+    myP3d     [1] = myAdSur->Value (su2, 0.5 * (sv1 + sv2));
     myFirstP2d[1].SetCoord (su2, sv1); 
     myLastP2d [1].SetCoord (su2, sv2);
 
-    myP3d     [2] = mySurf->Value (0.5 * (su1 + su2), sv1);
+    myP3d     [2] = myAdSur->Value (0.5 * (su1 + su2), sv1);
     myFirstP2d[2].SetCoord (su1, sv1); 
     myLastP2d [2].SetCoord (su2, sv1);
     
-    myP3d     [3] = mySurf->Value (0.5 * (su1 + su2), sv2);
+    myP3d     [3] = myAdSur->Value (0.5 * (su1 + su2), sv2);
     myFirstP2d[3].SetCoord (su2, sv2); 
     myLastP2d [3].SetCoord (su1, sv2);
 
@@ -215,10 +215,10 @@ void ShapeAnalysis_Surface::ComputeSingularities()
     myLastPar [2] = myLastPar [3] = su2;
     myUIsoDeg [2] = myUIsoDeg [3] = Standard_False;
 
-    gp_Pnt Corner1 = mySurf->Value(su1,sv1);
-    gp_Pnt Corner2 = mySurf->Value(su1,sv2);
-    gp_Pnt Corner3 = mySurf->Value(su2,sv1);
-    gp_Pnt Corner4 = mySurf->Value(su2,sv2);
+    gp_Pnt Corner1 = myAdSur->Value(su1,sv1);
+    gp_Pnt Corner2 = myAdSur->Value(su1,sv2);
+    gp_Pnt Corner3 = myAdSur->Value(su2,sv1);
+    gp_Pnt Corner4 = myAdSur->Value(su2,sv2);
 
     myPreci[0] = Max (Corner1.Distance(Corner2), Max (myP3d[0].Distance(Corner1), myP3d[0].Distance(Corner2)));
     myPreci[1] = Max (Corner3.Distance(Corner4), Max (myP3d[1].Distance(Corner3), myP3d[1].Distance(Corner4)));
@@ -587,8 +587,8 @@ Standard_Boolean ShapeAnalysis_Surface::IsUClosed(const Standard_Real preci)
        Standard_Integer nbvk = bs->NbVKnots();
        for (Standard_Integer i = 1; i <= nbvk; i ++) {
          Standard_Real v = bs->VKnot(i);
-         gp_Pnt p1 = bs->Value (uf, v);
-         gp_Pnt p2 = bs->Value (ul, v);
+         gp_Pnt p1 = SurfAdapt.Value (uf, v);
+         gp_Pnt p2 = SurfAdapt.Value (ul, v);
          myUCloseVal = Max (myUCloseVal, p1.SquareDistance (p2));
          distmin     = Min (distmin,     p1.SquareDistance (p2));
          if (i > 1) {
@@ -637,8 +637,8 @@ Standard_Boolean ShapeAnalysis_Surface::IsUClosed(const Standard_Real preci)
       Standard_Real distmin = RealLast();
       Standard_Integer nbpoints = 101; //can be revised
       for (Standard_Integer i = 0; i < nbpoints; i++) {
-       gp_Pnt p1 = mySurf->Value (uf, vf + (vl - vf ) * i / (nbpoints - 1));
-       gp_Pnt p2 = mySurf->Value (ul, vf + (vl - vf ) * i / (nbpoints - 1));
+       gp_Pnt p1 = SurfAdapt.Value (uf, vf + (vl - vf ) * i / (nbpoints - 1));
+       gp_Pnt p2 = SurfAdapt.Value (ul, vf + (vl - vf ) * i / (nbpoints - 1));
        myUCloseVal = Max (myUCloseVal, p1.SquareDistance (p2));
        distmin     = Min (distmin,     p1.SquareDistance (p2));
       }
@@ -713,14 +713,14 @@ Standard_Boolean ShapeAnalysis_Surface::IsVClosed(const Standard_Real preci)
        Standard_Integer nbuk = bs->NbUKnots();
        for (Standard_Integer i = 1; i <= nbuk; i ++) {
          Standard_Real u = bs->UKnot(i);
-         gp_Pnt p1 = bs->Value (u, vf);
-         gp_Pnt p2 = bs->Value (u, vl);
+         gp_Pnt p1 = SurfAdapt.Value (u, vf);
+         gp_Pnt p2 = SurfAdapt.Value (u, vl);
          myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2));
          distmin     = Min (distmin,     p1.SquareDistance (p2));
          if (i > 1) {
            u = 0.5 * (bs->UKnot(i-1) + bs->UKnot(i));
-           p1 = bs->Value (u, vf);
-           p2 = bs->Value (u, vl);
+           p1 = SurfAdapt.Value (u, vf);
+           p2 = SurfAdapt.Value (u, vl);
            myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2));
            distmin     = Min (distmin,     p1.SquareDistance (p2));
          }
@@ -763,8 +763,8 @@ Standard_Boolean ShapeAnalysis_Surface::IsVClosed(const Standard_Real preci)
       Standard_Real distmin = RealLast();
       Standard_Integer nbpoints = 101; //can be revised
       for (Standard_Integer i = 0; i < nbpoints; i++) {
-       gp_Pnt p1 = mySurf->Value (uf + (ul - uf ) * i / (nbpoints - 1), vf);
-       gp_Pnt p2 = mySurf->Value (uf + (ul - uf ) * i / (nbpoints - 1), vl);
+       gp_Pnt p1 = SurfAdapt.Value (uf + (ul - uf ) * i / (nbpoints - 1), vf);
+       gp_Pnt p2 = SurfAdapt.Value (uf + (ul - uf ) * i / (nbpoints - 1), vl);
        myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2));
        distmin     = Min (distmin,     p1.SquareDistance (p2));
       }
@@ -804,7 +804,7 @@ Standard_Boolean ShapeAnalysis_Surface::SurfaceNewton(const gp_Pnt2d &p2dPrev,
   for ( Standard_Integer i=0; i < 25; i++ ) {
     gp_Vec ru, rv, ruu, rvv, ruv;
     gp_Pnt pnt;
-    mySurf->D2 ( U, V, pnt, ru, rv, ruu, rvv, ruv );
+    SurfAdapt.D2 ( U, V, pnt, ru, rv, ruu, rvv, ruv );
 
     // normal
     Standard_Real ru2 = ru * ru, rv2 = rv * rv;
@@ -1036,10 +1036,9 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
       du = Min (myUDelt, SurfAdapt.UResolution (preci));
       dv = Min (myVDelt, SurfAdapt.VResolution (preci));
     }
-        myExtSrf = mySurf;
        Standard_Real Tol = Precision::PConfusion();
         myExtPS.SetFlag (Extrema_ExtFlag_MIN);
-       myExtPS.Initialize ( myExtSrf, uf-du, ul+du, vf-dv, vl+dv, Tol, Tol );
+       myExtPS.Initialize (SurfAdapt, uf-du, ul+du, vf-dv, vl+dv, Tol, Tol );
        myExtOK = Standard_True;
       }
       myExtPS.Perform ( P3D );
@@ -1060,7 +1059,7 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
         // file CEA_cuve-V5.igs Entityes 244, 259, 847, 925
         // if project point3D on SurfaceOfRevolution Extreme recompute 2d point, but
         // returns an old distance from 3d to solution :-(
-        gp_Pnt aCheckPnt = mySurf->Value( S, T );
+        gp_Pnt aCheckPnt = SurfAdapt.Value( S, T );
         dist2Min = P3D.SquareDistance(aCheckPnt);
         // end of WORKAROUND
        Standard_Real disSurf = sqrt (dist2Min);//, disCurv =1.e10;
@@ -1087,7 +1086,7 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
              Standard_Real Tol = Precision::Confusion();
              gp_Vec D1U, D1V;
              gp_Pnt pnt;
-             mySurf->D1(UU, VV, pnt, D1U, D1V);
+             SurfAdapt.D1(UU, VV, pnt, D1U, D1V);
              gp_Vec b = D1U.Crossed(D1V);
              gp_Vec a (pnt, P3D);
              Standard_Real ab = a.Dot(b);
@@ -1170,7 +1169,7 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
   } //:c9
   //szv#4:S4163:12Mar99 waste raise
   //if (!computed) Standard_NoSuchObject::Raise("PCurveLib_ProjectPointOnSurf::ValueOfUV untreated surface type");
-  if (computed) { if (myGap <= 0) myGap = P3D.Distance (mySurf->Value (S,T)); }
+  if (computed) { if (myGap <= 0) myGap = P3D.Distance (SurfAdapt.Value (S,T)); }
   else { myGap = -1.; S = 0.; T = 0.; }
   return gp_Pnt2d( S, T);
 }
@@ -1192,7 +1191,7 @@ Standard_Real ShapeAnalysis_Surface::UVFromIso(const gp_Pnt& P3d,const Standard_
 
   //  Initialisation des recherches : point deja trouve (?)
   UU = U; VV = V;
-  gp_Pnt depart = mySurf->Value (U,V);
+  gp_Pnt depart = myAdSur->Value (U,V);
   theMin = depart.Distance(P3d);
     
   if (theMin < preci/10) return theMin;  // c etait deja OK
index 3e821f3..0176b05 100644 (file)
@@ -295,7 +295,6 @@ protected:
   Handle(Geom_Surface) mySurf;
   Handle(GeomAdaptor_HSurface) myAdSur;
   Extrema_ExtPS myExtPS;
-  GeomAdaptor_Surface myExtSrf;
   Standard_Boolean myExtOK;
   Standard_Integer myNbDeg;
   Standard_Real myPreci[4];
index 71c1652..70eedda 100644 (file)
@@ -12,6 +12,7 @@
 // commercial license or contractual agreement.
 
 #include <Geom_Surface.hxx>
+#include <GeomAdaptor_HSurface.hxx>
 
 //=======================================================================
 //function : Surface
@@ -54,7 +55,7 @@ inline Standard_Real ShapeAnalysis_Surface::Gap() const
 inline gp_Pnt ShapeAnalysis_Surface::Value (const Standard_Real u,
                                            const Standard_Real v) 
 {
-  return mySurf->Value ( u, v );
+  return myAdSur->Value ( u, v );
 }
 
  
@@ -65,7 +66,7 @@ inline gp_Pnt ShapeAnalysis_Surface::Value (const Standard_Real u,
 
 inline gp_Pnt ShapeAnalysis_Surface::Value(const gp_Pnt2d& p2d) 
 {
-  return mySurf->Value ( p2d.X(), p2d.Y() );
+  return myAdSur->Value ( p2d.X(), p2d.Y() );
 }
 
  
index f5a6ad9..4a0f54b 100644 (file)
@@ -8,10 +8,10 @@ set ref_data {
 DATA        : Faulties = 0  ( 1 )  Warnings = 0  ( 0 )  Summary  = 0  ( 1 )
 TPSTAT      : Faulties = 0  ( 0 )  Warnings = 3  ( 183 )  Summary  = 3  ( 183 )
 CHECKSHAPE  : Wires    = 0  ( 0 )  Faces    = 0  ( 0 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
-NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 97  ( 97 )   Summary  = 2685  ( 2684 )
-STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 97  ( 97 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 1243  ( 1243 )
+NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 98  ( 98 )   Summary  = 2690  ( 2687 )
+STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 98  ( 98 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 1244  ( 1243 )
 TOLERANCE   : MaxTol   = 0.009955692634  ( 0.009955692464 )  AvgTol   =  0.0008509893784  (  0.0008531522552 )
-LABELS      : N0Labels = 97  ( 97 )  N1Labels = 0  ( 91 )  N2Labels = 0  ( 0 )   TotalLabels = 97  ( 188 )   NameLabels = 97  ( 97 )   ColorLabels = 97  ( 188 )   LayerLabels = 0  ( 0 )
+LABELS      : N0Labels = 97  ( 97 )  N1Labels = 2  ( 102 )  N2Labels = 0  ( 0 )   TotalLabels = 99  ( 199 )   NameLabels = 97  ( 97 )   ColorLabels = 98  ( 199 )   LayerLabels = 0  ( 0 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )
 NCOLORS     : NColors  = 1  ( 1 )
 COLORS      : Colors   = BLACK  ( BLACK )
index 54df8aa..885ad8a 100755 (executable)
@@ -1,6 +1,5 @@
 # !!!! This file is generated automatically, do not edit manually! See end script
 puts "TODO CR23096 ALL: LABELS : Faulty" 
-puts "TODO CR23096 ALL: Error : 3 differences with reference data found" 
 
 set LinuxDiff 2
 set filename brazo1.igs
@@ -9,10 +8,10 @@ set ref_data {
 DATA        : Faulties = 0  ( 2 )  Warnings = 0  ( 0 )  Summary  = 0  ( 2 )
 TPSTAT      : Faulties = 0  ( 0 )  Warnings = 139  ( 454 )  Summary  = 139  ( 454 )
 CHECKSHAPE  : Wires    = 6  ( 8 )  Faces    = 6  ( 8 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
-NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 223  ( 223 )   Summary  = 4710  ( 4574 )
-STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 223  ( 223 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 2166  ( 2092 )
-TOLERANCE   : MaxTol   =    0.991254355  (    0.991254355 )  AvgTol   =   0.01133191355  (   0.01225911215 )
-LABELS      : N0Labels = 223  ( 223 )  N1Labels = 0  ( 256 )  N2Labels = 0  ( 0 )   TotalLabels = 223  ( 479 )   NameLabels = 223  ( 388 )   ColorLabels = 223  ( 479 )   LayerLabels = 223  ( 479 )
+NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 223  ( 223 )   Summary  = 4584  ( 4544 )
+STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 223  ( 223 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 2084  ( 2076 )
+TOLERANCE   : MaxTol   =    0.991254355  (    0.991254355 )  AvgTol   =   0.01156050183  (   0.01226830477 )
+LABELS      : N0Labels = 223  ( 223 )  N1Labels = 0  ( 242 )  N2Labels = 0  ( 0 )   TotalLabels = 223  ( 465 )   NameLabels = 223  ( 388 )   ColorLabels = 223  ( 465 )   LayerLabels = 223  ( 465 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )
 NCOLORS     : NColors  = 3  ( 3 )
 COLORS      : Colors   = BLUE1 MAGENTA1 YELLOW  ( BLUE1 MAGENTA1 YELLOW )
index a5e3c29..b69c32f 100755 (executable)
@@ -1,7 +1,6 @@
 # !!!! This file is generated automatically, do not edit manually! See end script
 puts "TODO CR23096 ALL: LABELS : Faulty" 
 puts "TODO CR23096 ALL: STATSHAPE : Faulty" 
-puts "TODO CR23096 ALL: Error : 3 differences with reference data found" 
 
 set LinuxDiff 5
 set filename BUC60743.igs
@@ -9,11 +8,11 @@ set filename BUC60743.igs
 set ref_data {
 DATA        : Faulties = 0  ( 2 )  Warnings = 0  ( 0 )  Summary  = 0  ( 2 )
 TPSTAT      : Faulties = 3  ( 59 )  Warnings = 2203  ( 4655 )  Summary  = 2206  ( 4714 )
-CHECKSHAPE  : Wires    = 7  ( 17 )  Faces    = 7  ( 12 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
-NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 3349  ( 2837 )   Summary  = 45927  ( 39202 )
-STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 3349  ( 3349 )   FreeWire = 6  ( 6 )   FreeEdge  = 67 ( 67 )   SharedEdge = 19607  ( 16774 )
+CHECKSHAPE  : Wires    = 7  ( 18 )  Faces    = 7  ( 13 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
+NBSHAPES    : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 3350  ( 2837 )   Summary  = 45925  ( 39210 )
+STATSHAPE   : Solid    = 0  ( 0 )  Shell    = 0  ( 0 )  Face     = 3350  ( 3349 )   FreeWire = 6  ( 6 )   FreeEdge  = 67 ( 67 )   SharedEdge = 19603  ( 16778 )
 TOLERANCE   : MaxTol   =    4.854604894  (    5.769095076 )  AvgTol   =   0.01628658326  (   0.01747356296 )
-LABELS      : N0Labels = 11  ( 11 )  N1Labels = 2891  ( 6327 )  N2Labels = 0  ( 0 )   TotalLabels = 2902  ( 6338 )   NameLabels = 2900  ( 5879 )   ColorLabels = 2891  ( 6327 )   LayerLabels = 2411  ( 5258 )
+LABELS      : N0Labels = 11  ( 11 )  N1Labels = 2891  ( 6329 )  N2Labels = 0  ( 0 )   TotalLabels = 2902  ( 6340 )   NameLabels = 2900  ( 5879 )   ColorLabels = 2891  ( 6329 )   LayerLabels = 2411  ( 5259 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )
 NCOLORS     : NColors  = 4  ( 4 )
 COLORS      : Colors   = BLACK BLUE1 RED YELLOW  ( BLACK BLUE1 RED YELLOW )
index 7e5deb1..87208ff 100755 (executable)
@@ -9,8 +9,8 @@ set ref_data {
 DATA        : Faulties = 0  ( 0 )  Warnings = 0  ( 0 )  Summary  = 0  ( 0 )
 TPSTAT      : Faulties = 3  ( 0 )  Warnings = 944  ( 3168 )  Summary  = 947  ( 3168 )
 CHECKSHAPE  : Wires    = 52  ( 41 )  Faces    = 52  ( 48 )  Shells   = 0  ( 2 )   Solids   = 0 ( 0 )
-NBSHAPES    : Solid    = 28  ( 28 )  Shell    = 768  ( 30 )  Face     = 3240  ( 3239 )   Summary  = 29369  ( 28626 )
-STATSHAPE   : Solid    = 28  ( 28 )  Shell    = 768  ( 30 )  Face     = 3240  ( 3239 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 12583  ( 12576 )
+NBSHAPES    : Solid    = 28  ( 28 )  Shell    = 768  ( 30 )  Face     = 3240  ( 3239 )   Summary  = 29370  ( 28626 )
+STATSHAPE   : Solid    = 28  ( 28 )  Shell    = 768  ( 30 )  Face     = 3240  ( 3239 )   FreeWire = 0  ( 0 )   FreeEdge  = 0 ( 0 )   SharedEdge = 12584  ( 12576 )
 TOLERANCE   : MaxTol   =    15.00300076  (    20.46526799 )  AvgTol   =   0.02248945623  (   0.03724082116 )
 LABELS      : N0Labels = 3  ( 3 )  N1Labels = 2  ( 2 )  N2Labels = 0  ( 0 )   TotalLabels = 5  ( 5 )   NameLabels = 5  ( 5 )   ColorLabels = 0  ( 0 )   LayerLabels = 0  ( 0 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )