0025861: Wrong result obtained by projection algorithm.
[occt.git] / src / Extrema / Extrema_ExtPS.cxx
old mode 100755 (executable)
new mode 100644 (file)
index ed4d304..37926ae
@@ -1,20 +1,16 @@
 // Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 //-----------------------------------------------------------------
 
@@ -24,8 +20,8 @@
 #include <Standard_NotImplemented.hxx>
 #include <Precision.hxx>
 #include <GeomAbs_CurveType.hxx>
-#include <Adaptor3d_SurfaceOfLinearExtrusion.hxx>
-#include <Adaptor3d_SurfaceOfRevolution.hxx>
+#include <Adaptor3d_HSurfaceOfRevolution.hxx>
+#include <Adaptor3d_HSurfaceOfLinearExtrusion.hxx>
 #include <ElCLib.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Pln.hxx>
@@ -60,41 +56,43 @@ static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
     Standard_Real Step,D1NormMax;
     if (IT == GeomAbs_IsoV) 
     {
-      Step = (U2 - U1)/10;
-      if(Step < Precision::PConfusion()) {
-        return Standard_False;
-      }
-      if(Step < Precision::PConfusion()) {
-        return Standard_False;
-      }
-      D1NormMax=0.;
-      for (T=U1;T<=U2;T=T+Step) 
+      if( !Precision::IsInfinite(U1) &&  !Precision::IsInfinite(U2) )
       {
-        S.D1(T,Param,P,D1U,D1V);
-        D1NormMax=Max(D1NormMax,D1U.Magnitude());
+        Step = (U2 - U1)/10;
+        if(Step < Precision::PConfusion()) {
+          return Standard_False;
+        }
+        D1NormMax=0.;
+
+        for (T=U1;T<=U2;T=T+Step) 
+        {
+          S.D1(T,Param,P,D1U,D1V);
+          D1NormMax=Max(D1NormMax,D1U.Magnitude());
+        }
+
+        if (D1NormMax >TolMax || D1NormMax < TolMin ) 
+          Along = Standard_False;
       }
-
-      if (D1NormMax >TolMax || D1NormMax < TolMin ) 
-           Along = Standard_False;
     }
     else 
     {
-      Step = (V2 - V1)/10;
-      if(Step < Precision::PConfusion()) {
-        return Standard_False;
-      }
-      if(Step < Precision::PConfusion()) {
-        return Standard_False;
-      }
-      D1NormMax=0.;
-      for (T=V1;T<=V2;T=T+Step) 
+      if( !Precision::IsInfinite(V1) &&  !Precision::IsInfinite(V2) )
       {
-       S.D1(Param,T,P,D1U,D1V);
-        D1NormMax=Max(D1NormMax,D1V.Magnitude());
+        Step = (V2 - V1)/10;
+        if(Step < Precision::PConfusion()) {
+          return Standard_False;
+        }
+        D1NormMax=0.;
+        for (T=V1;T<=V2;T=T+Step) 
+        {
+          S.D1(Param,T,P,D1U,D1V);
+          D1NormMax=Max(D1NormMax,D1V.Magnitude());
+        }
+
+        if (D1NormMax >TolMax || D1NormMax < TolMin ) 
+          Along = Standard_False;
       }
 
-      if (D1NormMax >TolMax || D1NormMax < TolMin ) 
-           Along = Standard_False;
 
 
     }
@@ -112,10 +110,22 @@ void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
   Standard_Real U, V;
   PS.Parameter(U, V);
   if (myS->IsUPeriodic()) {
-    U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
+    U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
+    
+    // Handle trimmed surfaces.
+    if (U > myusup + mytolu)
+      U -= myS->UPeriod();
+    if (U < myuinf - mytolu)
+      U += myS->UPeriod();
   }
   if (myS->IsVPeriodic()) {
-    V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
+    V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
+
+    // Handle trimmed surfaces.
+    if (V > myvsup + mytolv)
+      V -= myS->VPeriod();
+    if (V < myvinf - mytolv)
+      V += myS->VPeriod();
   }
   if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu &&
       (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) {
@@ -130,7 +140,7 @@ void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
 //purpose  : 
 //=======================================================================
 
-Extrema_ExtPS::Extrema_ExtPS() 
+Extrema_ExtPS::Extrema_ExtPS()
 {
   myDone = Standard_False;
 }
@@ -141,20 +151,25 @@ Extrema_ExtPS::Extrema_ExtPS()
 //purpose  : 
 //=======================================================================
 
-Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
-                            const Adaptor3d_Surface& S,
-                            const Standard_Real    TolU,
-                            const Standard_Real    TolV,
-           const Extrema_ExtFlag F,
-           const Extrema_ExtAlgo A)
-
+Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
+                              const Adaptor3d_Surface& theS,
+                              const Standard_Real      theTolU,
+                              const Standard_Real      theTolV,
+                              const Extrema_ExtFlag    theF,
+                              const Extrema_ExtAlgo    theA)
 {
-  myExtPS.SetFlag(F);
-  myExtPS.SetAlgo(A);
-  Initialize(S, S.FirstUParameter(), S.LastUParameter(), 
-               S.FirstVParameter(), S.LastVParameter(), 
-               TolU, TolV);
-  Perform(P);
+  myExtPS.SetFlag (theF);
+  myExtPS.SetAlgo (theA);
+
+  Initialize (theS,
+              theS.FirstUParameter(),
+              theS.LastUParameter(),
+              theS.FirstVParameter(),
+              theS.LastVParameter(),
+              theTolU,
+              theTolV);
+
+  Perform (theP);
 }
 
 //=======================================================================
@@ -162,22 +177,29 @@ Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
 //purpose  : 
 //=======================================================================
 
-Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
-                            const Adaptor3d_Surface& S,
-                            const Standard_Real    Uinf,       
-                            const Standard_Real    Usup,
-                            const Standard_Real    Vinf,       
-                            const Standard_Real    Vsup,
-                            const Standard_Real    TolU,
-                            const Standard_Real    TolV,
-           const Extrema_ExtFlag F,
-           const Extrema_ExtAlgo A)
-
+Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
+                              const Adaptor3d_Surface& theS,
+                              const Standard_Real      theUinf,
+                              const Standard_Real      theUsup,
+                              const Standard_Real      theVinf,
+                              const Standard_Real      theVsup,
+                              const Standard_Real      theTolU,
+                              const Standard_Real      theTolV,
+                              const Extrema_ExtFlag    theF,
+                              const Extrema_ExtAlgo    theA)
 {
-  myExtPS.SetFlag(F);
-  myExtPS.SetAlgo(A);
-  Initialize(S, Uinf, Usup, Vinf, Vsup, TolU, TolV);
-  Perform(P);
+  myExtPS.SetFlag (theF);
+  myExtPS.SetAlgo (theA);
+
+  Initialize (theS,
+              theUinf,
+              theUsup,
+              theVinf,
+              theVsup,
+              theTolU,
+              theTolV);
+
+  Perform (theP);
 }
 
 
@@ -186,31 +208,31 @@ Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
 //purpose  : 
 //=======================================================================
 
-void Extrema_ExtPS::Initialize(const Adaptor3d_Surface& S,
-                              const Standard_Real    Uinf,     
-                              const Standard_Real    Usup,
-                              const Standard_Real    Vinf,     
-                              const Standard_Real    Vsup,
-                              const Standard_Real    TolU,
-                              const Standard_Real    TolV)
+void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS,
+                                const Standard_Real      theUinf,
+                                const Standard_Real      theUsup,
+                                const Standard_Real      theVinf,
+                                const Standard_Real      theVsup,
+                                const Standard_Real      theTolU,
+                                const Standard_Real      theTolV)
 {
-  myS = (Adaptor3d_SurfacePtr)&S;
-  myuinf = Uinf;
-  myusup = Usup;
-  myvinf = Vinf;
-  myvsup = Vsup;
+  myS = (Adaptor3d_SurfacePtr)&theS;
+  myuinf = theUinf;
+  myusup = theUsup;
+  myvinf = theVinf;
+  myvsup = theVsup;
 
   if (Precision::IsNegativeInfinite(myuinf)) myuinf = -1e10;
   if (Precision::IsPositiveInfinite(myusup)) myusup = 1e10;
   if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10;
   if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10;
 
-  mytolu = TolU;
-  mytolv = TolV;
+  mytolu = theTolU;
+  mytolv = theTolV;
   mytype = myS->GetType();
 
   Standard_Boolean isB = ( myS->GetType() == GeomAbs_BSplineSurface ||
-                          myS->GetType() == GeomAbs_BezierSurface );
+                           myS->GetType() == GeomAbs_BezierSurface );
 
   Standard_Integer nbU = (isB) ? 44 : 32;
   Standard_Integer nbV = (isB) ? 44 : 32;
@@ -218,16 +240,19 @@ void Extrema_ExtPS::Initialize(const Adaptor3d_Surface& S,
   Standard_Boolean bUIsoIsDeg = Standard_False, bVIsoIsDeg = Standard_False;
 
   if(myS->GetType() != GeomAbs_Plane) {
-    bUIsoIsDeg = IsoIsDeg(S, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
-                 IsoIsDeg(S, myusup, GeomAbs_IsoU, 0., 1.e-9);
-    bVIsoIsDeg = IsoIsDeg(S, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
-                 IsoIsDeg(S, myvsup, GeomAbs_IsoV, 0., 1.e-9);
+    bUIsoIsDeg = IsoIsDeg(theS, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
+                 IsoIsDeg(theS, myusup, GeomAbs_IsoU, 0., 1.e-9);
+    bVIsoIsDeg = IsoIsDeg(theS, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
+                 IsoIsDeg(theS, myvsup, GeomAbs_IsoV, 0., 1.e-9);
   }
 
   if(bUIsoIsDeg) nbU = 300;
   if(bVIsoIsDeg) nbV = 300;
 
   myExtPS.Initialize(*myS, nbU, nbV, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
+
+  myExtPExtS.Nullify();
+  myExtPRevS.Nullify();
 }
 
 //=======================================================================
@@ -235,86 +260,107 @@ void Extrema_ExtPS::Initialize(const Adaptor3d_Surface& S,
 //purpose  : 
 //=======================================================================
 
-void Extrema_ExtPS::Perform(const gp_Pnt& P)
+void Extrema_ExtPS::Perform(const gp_Pnt& thePoint)
 {
   myPoints.Clear();
   mySqDist.Clear();
-  Standard_Integer i;
-  P11 = myS->Value(myuinf, myvinf);
-  P12 = myS->Value(myuinf, myvsup);
-  P21 = myS->Value(myusup, myvinf);
-  P22 = myS->Value(myusup, myvsup);
-  d11 = P.SquareDistance(P11);
-  d12 = P.SquareDistance(P12);
-  d21 = P.SquareDistance(P21);
-  d22 = P.SquareDistance(P22);
-  
-  switch(mytype) {
-    
-  case GeomAbs_Cylinder:
-    myExtPElS.Perform(P, myS->Cylinder(), Precision::Confusion());
-    break;
-  case GeomAbs_Plane:
-    myExtPElS.Perform(P, myS->Plane(), Precision::Confusion());
-    break;
-  case GeomAbs_Cone:
-    myExtPElS.Perform(P, myS->Cone(), Precision::Confusion());
-    break;
-  case GeomAbs_Sphere:
-    myExtPElS.Perform(P, myS->Sphere(), Precision::Confusion());
-    break;
-  case GeomAbs_Torus:
-    myExtPElS.Perform(P, myS->Torus(), Precision::Confusion());
-    break;
 
-    
-  case GeomAbs_SurfaceOfExtrusion: {
-    Extrema_ExtPExtS anExtPExtS(P,
-                               Adaptor3d_SurfaceOfLinearExtrusion(myS->BasisCurve(),
-                                                                  myS->Direction()),
-                               myuinf,myusup, myvinf,myvsup, mytolu,mytolv);
-    myDone = anExtPExtS.IsDone();
-    if (myDone) 
-      for (i = 1; i <= anExtPExtS.NbExt(); i++) {
-       TreatSolution (anExtPExtS.Point(i), anExtPExtS.SquareDistance(i));
+  switch (mytype)
+  {
+    case GeomAbs_Cylinder:
+      myExtPElS.Perform (thePoint, myS->Cylinder(), Precision::Confusion());
+      break;
+    case GeomAbs_Plane:
+      myExtPElS.Perform (thePoint, myS->Plane(), Precision::Confusion());
+      break;
+    case GeomAbs_Cone:
+      myExtPElS.Perform (thePoint, myS->Cone(), Precision::Confusion());
+      break;
+    case GeomAbs_Sphere:
+      myExtPElS.Perform (thePoint, myS->Sphere(), Precision::Confusion());
+      break;
+    case GeomAbs_Torus:
+      myExtPElS.Perform (thePoint, myS->Torus(), Precision::Confusion());
+      break;
+
+    case GeomAbs_SurfaceOfExtrusion:
+    {
+      if (myExtPExtS.IsNull())
+      {
+        Handle(Adaptor3d_HSurfaceOfLinearExtrusion) aS (new Adaptor3d_HSurfaceOfLinearExtrusion (
+          Adaptor3d_SurfaceOfLinearExtrusion (myS->BasisCurve(), myS->Direction())));
+
+        myExtPExtS = new Extrema_ExtPExtS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
+      }
+      else
+      {
+        myExtPExtS->Perform (thePoint);
       }
-    return;
-  }
 
-    
-  case GeomAbs_SurfaceOfRevolution: {
-    Extrema_ExtPRevS anExtPRevS(P,
-                               Adaptor3d_SurfaceOfRevolution(myS->BasisCurve(),
-                                                             myS->AxeOfRevolution()),
-                               myuinf, myusup,myvinf, myvsup,mytolu, mytolv);
-    myDone = anExtPRevS.IsDone();
-    if (myDone) 
-      for (i = 1; i <= anExtPRevS.NbExt(); i++) {
-       TreatSolution (anExtPRevS.Point(i), anExtPRevS.SquareDistance(i));
+      myDone = myExtPExtS->IsDone();
+      if (myDone)
+      {
+        for (Standard_Integer anIdx = 1; anIdx <= myExtPExtS->NbExt(); ++anIdx)
+        {
+          TreatSolution (myExtPExtS->Point (anIdx), myExtPExtS->SquareDistance (anIdx));
+        }
       }
-    return;
-  }
 
-    
-  default: 
-    myExtPS.Perform(P);
-    myDone = myExtPS.IsDone();
-    if (myDone) 
-      for (i = 1; i <= myExtPS.NbExt(); i++) 
-       TreatSolution (myExtPS.Point(i), myExtPS.SquareDistance(i));
-    return;
+      return;
+    }
+
+    case GeomAbs_SurfaceOfRevolution:
+    {
+      if (myExtPRevS.IsNull())
+      {
+        Handle(Adaptor3d_HSurfaceOfRevolution) aS (new Adaptor3d_HSurfaceOfRevolution (
+          Adaptor3d_SurfaceOfRevolution (myS->BasisCurve(), myS->AxeOfRevolution())));
+
+        myExtPRevS = new Extrema_ExtPRevS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
+      }
+      else
+      {
+        myExtPRevS->Perform (thePoint);
+      }
+
+      myDone = myExtPRevS->IsDone();
+      if (myDone)
+      {
+        for (Standard_Integer anIdx = 1; anIdx <= myExtPRevS->NbExt(); ++anIdx)
+        {
+          TreatSolution (myExtPRevS->Point (anIdx), myExtPRevS->SquareDistance (anIdx));
+        }
+      }
+
+      return;
+    }
+
+    default:
+    {
+      myExtPS.Perform (thePoint);
+      myDone = myExtPS.IsDone();
+      if (myDone)
+      {
+        for (Standard_Integer anIdx = 1; anIdx <= myExtPS.NbExt(); ++anIdx)
+        {
+          TreatSolution (myExtPS.Point (anIdx), myExtPS.SquareDistance (anIdx));
+        }
+      }
+      return;
+    }
   }
 
-  
   myDone = myExtPElS.IsDone();
-  if (myDone) 
-    for (i = 1; i <= myExtPElS.NbExt(); i++) 
-      TreatSolution (myExtPElS.Point(i), myExtPElS.SquareDistance(i));
-  return;
+  if (myDone)
+  {
+    for (Standard_Integer anIdx = 1; anIdx <= myExtPElS.NbExt(); ++anIdx)
+    {
+      TreatSolution (myExtPElS.Point (anIdx), myExtPElS.SquareDistance (anIdx));
+    }
+  }
 }
 
 
-
 Standard_Boolean Extrema_ExtPS::IsDone() const
 {
   return myDone;
@@ -336,8 +382,7 @@ Standard_Integer Extrema_ExtPS::NbExt() const
 }
 
 
-
-Extrema_POnSurf Extrema_ExtPS::Point(const Standard_Integer N) const
+const Extrema_POnSurf& Extrema_ExtPS::Point(const Standard_Integer N) const
 {
   if(!myDone) StdFail_NotDone::Raise();
   return myPoints.Value(N);