CR23683: Geom_BSplineSurface incorrectly determines continuity for periodic cases
[occt.git] / src / Geom / Geom_OffsetCurve.cxx
index 01217fc..cec8bb1 100755 (executable)
@@ -1,15 +1,27 @@
-// File:       Geom_OffsetCurve.cxx
-// Created:    Wed Mar 10 09:49:18 1993
-// Author:     JCV
-//             <fid@phylox>
-// Copyright:  Matra Datavision 1993
-
-// Created:    Tue Jun 25 15:36:30 1991
-// Author:     JCV
+// Created on: 1991-06-25
+// Created by: JCV
+// Copyright (c) 1991-1999 Matra Datavision
+// Copyright (c) 1999-2012 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.
+//
+// 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.
+//
+// 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.
+
+
 // 24-Aug-95 : xab removed C1 and C2 test : appeller  D1 et D2 
 //             avec discernement !
 // 19-09-97  : JPI correction derivee seconde
-//
 
 
 #include <Geom_OffsetCurve.ixx>
@@ -77,14 +89,12 @@ Handle(Geom_Geometry) Geom_OffsetCurve::Copy () const {
 Geom_OffsetCurve::Geom_OffsetCurve (const Handle(Curve)& C,
                                    const Standard_Real           Offset, 
                                    const Dir&           V      )
- : direction(V), offsetValue(Offset) {
-  
+ : direction(V), offsetValue(Offset)
+{
   if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve)) {
-    Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C->Copy());
-    if ((OC->BasisCurve())->Continuity() == GeomAbs_C0)  
-      Standard_ConstructionError::Raise();
+    Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C);
+    SetBasisCurve (OC->BasisCurve());
 
-    basisCurve = Handle(Curve)::DownCast((OC->BasisCurve())->Copy());
     Standard_Real PrevOff = OC->Offset();
     gp_Vec V1(OC->Direction());
     gp_Vec V2(direction);
@@ -97,9 +107,9 @@ Geom_OffsetCurve::Geom_OffsetCurve (const Handle(Curve)& C,
       offsetValue = -Vdir.Magnitude();
       direction.SetXYZ((-Vdir).XYZ());
     }
-  } else {
-    if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
-    basisCurve = Handle(Curve)::DownCast(C->Copy()); // DownCast: 10-03-93
+  }
+  else {
+    SetBasisCurve(C);
   }
 }
 
@@ -176,10 +186,36 @@ Standard_Real Geom_OffsetCurve::Period () const
 //purpose  : 
 //=======================================================================
 
-void Geom_OffsetCurve::SetBasisCurve (const Handle(Curve)& C) {
+void Geom_OffsetCurve::SetBasisCurve (const Handle(Curve)& C)
+{
+  Handle(Curve) aBasisCurve = Handle(Curve)::DownCast(C->Copy());
+
+  // Basis curve must be at least C1
+  if (aBasisCurve->Continuity() == GeomAbs_C0)
+  {
+    // For B-splines it is sometimes possible to increase continuity by removing 
+    // unnecessarily duplicated knots
+    if (aBasisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
+    {
+      Handle(Geom_BSplineCurve) aBCurve = Handle(Geom_BSplineCurve)::DownCast(aBasisCurve);
+      Standard_Integer degree = aBCurve->Degree();
+      Standard_Real Toler = Precision::Confusion();
+      Standard_Integer start = aBCurve->IsPeriodic() ? 1 :  aBCurve->FirstUKnotIndex(),
+                       finish = aBCurve->IsPeriodic() ? aBCurve->NbKnots() :  aBCurve->LastUKnotIndex();
+      for (Standard_Integer i = start; i <= finish; i++)
+      {
+        Standard_Integer mult = aBCurve->Multiplicity(i);
+        if ( mult == degree )
+          aBCurve->RemoveKnot(i,degree - 1, Toler);
+      }
+    }
 
-  if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
-  basisCurve = Handle(Curve)::DownCast(C->Copy()); // DownCast: 10-03-93
+    // Raise exception if still C0
+    if (aBasisCurve->Continuity() == GeomAbs_C0)
+      Standard_ConstructionError::Raise("Offset on C0 curve");
+  }
+
+  basisCurve = aBasisCurve;
 }
 
 
@@ -529,12 +565,6 @@ void Geom_OffsetCurve::D1 ( const Standard_Real U,
 
    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
 
-
-#ifdef DEB
-  GeomAbs_Shape Continuity = basisCurve->Continuity();
-#else
-  basisCurve->Continuity();
-#endif
   basisCurve->D2 (U, PBasis, V1basis, V2basis);
   V1 = V1basis;
   Vec V2 = V2basis;
@@ -590,12 +620,6 @@ void Geom_OffsetCurve::D2 (const Standard_Real U,
    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
 
-#ifdef DEB
-  GeomAbs_Shape Continuity = basisCurve->Continuity();
-#else
-  basisCurve->Continuity();
-#endif
-
   basisCurve->D3 (U, PBasis, V1basis, V2basis, V3basis);
   Standard_Integer Index = 2;
   V1     = V1basis;