]> OCCT Git - occt-copy.git/commitdiff
0031016: Projection of an ellipse is a B-spline in some cases
authorazv <azv@opencascade.com>
Tue, 7 Jul 2020 14:40:50 +0000 (17:40 +0300)
committerazv <azv@opencascade.com>
Tue, 7 Jul 2020 20:10:12 +0000 (23:10 +0300)
Improve projection of ellipse and circle on a plane in case of the same parametrization of the original curve and the projected one is not necessary. Now the projection is a canonical curve instead on B-spline.

13 files changed:
src/ProjLib/ProjLib_ProjectOnPlane.cxx
tests/bugs/modalg_7/bug31016_01 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_02 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_03 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_04 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_05 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_06 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_07 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_08 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_09 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_10 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_11 [new file with mode: 0644]
tests/bugs/modalg_7/bug31016_12 [new file with mode: 0644]

index b059fcadfab95268dd2ce86d52d303b7b2720ee1..4837020025bdb4c7cd7bebd73f3a49ed3bec252e 100644 (file)
@@ -44,6 +44,9 @@
 #include <Geom_Parabola.hxx>
 #include <Geom_Hyperbola.hxx>
 #include <Geom_Ellipse.hxx>
+#include <GeomLib_Tool.hxx>
+#include <math_Jacobi.hxx>
+#include <math_Matrix.hxx>
 
 
 
@@ -516,10 +519,7 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
   gp_Ax2 Axis;
   Standard_Real R1 =0., R2 =0.;
 
-  if ( Type != GeomAbs_Line)  // on garde le parametrage
-    myKeepParam = Standard_True;
-  else                        // on prend le choix utilisateur.
-    myKeepParam = KeepParametrization;
+  myKeepParam = KeepParametrization;
 
   switch ( Type) {
   case GeomAbs_Line: 
@@ -648,12 +648,13 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
 
       Standard_Real Tol2 = myTolerance*myTolerance;
       if (VDx.SquareMagnitude() < Tol2 ||
-         VDy.SquareMagnitude() < Tol2    ) {
-       myIsApprox = Standard_True;
+          VDy.SquareMagnitude() < Tol2 ||
+          VDx.CrossSquareMagnitude(VDy) < Tol2) {
+        myIsApprox = Standard_True;
       }
 
-      if (!myIsApprox && 
-         gp_Dir(VDx).IsNormal(gp_Dir(VDy),Precision::Angular())) {
+      if (!myIsApprox)
+      {
        Dx = gp_Dir(VDx);
        Dy = gp_Dir(VDy);
        gp_Pnt O    = Axis.Location();
@@ -662,39 +663,89 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
        gp_Pnt Py   = ProjectPnt(myPlane,myDirection,O.Translated(R2*gp_Vec(Y)));
        Standard_Real Major = P.Distance(Px);
        Standard_Real Minor = P.Distance(Py);
-       gp_Ax2 Axe( P, Dx^Dy,Dx);
 
-       if ( Abs( Major - Minor) < Precision::Confusion()) {
-         myType = GeomAbs_Circle;
-         gp_Circ Circ(Axe, Major);
-         GeomCirclePtr  = new Geom_Circle(Circ);
-//  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
-         GeomAdaptor_Curve aGACurve(GeomCirclePtr);
-         myResult = new GeomAdaptor_HCurve(aGACurve);
-//  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
-       }
-       else if ( Major > Minor) {
-         myType = GeomAbs_Ellipse;
-         Elips  = gp_Elips( Axe, Major, Minor);
-         
-          GeomEllipsePtr = new Geom_Ellipse(Elips) ;
+        if (myKeepParam)
+          myIsApprox = !gp_Dir(VDx).IsNormal(gp_Dir(VDy), Precision::Angular());
+        else
+        {
+          // Since it is not necessary to keep the same parameter for the point on the original and on the projected curves,
+          // we will use the following approach to find axes of the projected ellipse and provide the canonical curve:
+          // https://www.geometrictools.com/Documentation/ParallelProjectionEllipse.pdf
+          math_Matrix aMatrA(1, 2, 1, 2);
+          // A = Jp^T * Pr(Je), where
+          //   Pr(Je) - projection of axes of original ellipse to the target plane
+          //   Jp - X and Y axes of the target plane
+          aMatrA(1, 1) = myPlane.XDirection().XYZ().Dot(VDx.XYZ());
+          aMatrA(1, 2) = myPlane.XDirection().XYZ().Dot(VDy.XYZ());
+          aMatrA(2, 1) = myPlane.YDirection().XYZ().Dot(VDx.XYZ());
+          aMatrA(2, 2) = myPlane.YDirection().XYZ().Dot(VDy.XYZ());
+
+          math_Matrix aMatrDelta2(1, 2, 1, 2, 0.0);
+          //           | 1/MajorRad^2       0       |
+          // Delta^2 = |                            |
+          //           |      0        1/MajorRad^2 |
+          aMatrDelta2(1, 1) = 1.0 / (R1 * R1);
+          aMatrDelta2(2, 2) = 1.0 / (R2 * R2);
+
+          math_Matrix aMatrAInv = aMatrA.Inverse();
+          math_Matrix aMatrM = aMatrAInv.Transposed() * aMatrDelta2 * aMatrAInv;
+
+          // perform eigenvalues calculation
+          math_Jacobi anEigenCalc(aMatrM);
+          if (anEigenCalc.IsDone())
+          {
+            // radii of the projected ellipse
+            Minor = 1.0 / Sqrt(anEigenCalc.Value(1));
+            Major = 1.0 / Sqrt(anEigenCalc.Value(2));
+
+            // calculate the rotation angle for the plane axes to meet the correct axes of the projected ellipse
+            // (swap eigenvectors in respect to major and minor axes)
+            const math_Matrix& anEigenVec = anEigenCalc.Vectors();
+            gp_Trsf2d aTrsfInPlane;
+            aTrsfInPlane.SetValues(anEigenVec(1, 2), anEigenVec(1, 1), 0.0,
+                                   anEigenVec(2, 2), anEigenVec(2, 1), 0.0);
+            gp_Trsf aRot;
+            aRot.SetRotation(gp_Ax1(P, myPlane.Direction()), aTrsfInPlane.RotationPart());
+
+            Dx = myPlane.XDirection().Transformed(aRot);
+            Dy = myPlane.YDirection().Transformed(aRot);
+          }
+          else
+            myIsApprox = Standard_True;
+        }
+
+        if (!myIsApprox)
+        {
+          gp_Ax2 Axe(P, Dx^Dy, Dx);
+
+          if (Abs(Major - Minor) < Precision::Confusion()) {
+            myType = GeomAbs_Circle;
+            gp_Circ Circ(Axe, Major);
+            GeomCirclePtr  = new Geom_Circle(Circ);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
-         GeomAdaptor_Curve aGACurve(GeomEllipsePtr);
-         myResult = new GeomAdaptor_HCurve(aGACurve);
+            GeomAdaptor_Curve aGACurve(GeomCirclePtr);
+            myResult = new GeomAdaptor_HCurve(aGACurve);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
-       }
-       else {
-         myIsApprox = Standard_True;
-         myType = GeomAbs_BSplineCurve;
-          PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
+          }
+          else if ( Major > Minor) {
+            myType = GeomAbs_Ellipse;
+            Elips  = gp_Elips( Axe, Major, Minor);
+
+            GeomEllipsePtr = new Geom_Ellipse(Elips);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
-         GeomAdaptor_Curve aGACurve(ApproxCurve);
-         myResult = new GeomAdaptor_HCurve(aGACurve);
+            GeomAdaptor_Curve aGACurve(GeomEllipsePtr);
+            myResult = new GeomAdaptor_HCurve(aGACurve);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
-       }
+          }
+          else {
+            myIsApprox = Standard_True;
+          }
+        }
       }
-      else {
-       myIsApprox = Standard_True;
+
+      // No way to build the canonical curve, approximate as B-spline
+      if (myIsApprox)
+      {
        myType     = GeomAbs_BSplineCurve;
         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
@@ -702,10 +753,26 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
        myResult = new GeomAdaptor_HCurve(aGACurve);
 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
       }
+      else if (GeomCirclePtr || GeomEllipsePtr)
+      {
+        Handle(Geom_Curve) aResultCurve = GeomCirclePtr;
+        if (aResultCurve.IsNull())
+          aResultCurve = GeomEllipsePtr;
+        // start and end parameters of the projected curve
+        Standard_Real aParFirst = myCurve->FirstParameter();
+        Standard_Real aParLast = myCurve->LastParameter();
+        gp_Pnt aPntFirst = ProjectPnt(myPlane, myDirection, myCurve->Value(aParFirst));
+        gp_Pnt aPntLast = ProjectPnt(myPlane, myDirection, myCurve->Value(aParLast));
+        GeomLib_Tool::Parameter(aResultCurve, aPntFirst, Precision::Confusion(), myFirstPar);
+        GeomLib_Tool::Parameter(aResultCurve, aPntLast, Precision::Confusion(), myLastPar);
+        while (myLastPar <= myFirstPar)
+          myLastPar += myResult->Period();
+      }
     }
     break;
   case GeomAbs_Parabola:
     {
+      myKeepParam = Standard_True;
       //     P(u) = O + (u*u)/(4*f) * Xc + u * Yc
       // ==> Q(u) = f(P(u)) 
       //          = f(O) + (u*u)/(4*f) * f(Xc) + u * f(Yc)
@@ -757,6 +824,7 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
     break;
   case GeomAbs_Hyperbola:
     {
+      myKeepParam = Standard_True;
       //     P(u) = O + R1 * Cosh(u) * Xc + R2 * Sinh(u) * Yc
       // ==> Q(u) = f(P(u)) 
       //          = f(O) + R1 * Cosh(u) * f(Xc) + R2 * Sinh(u) * f(Yc)
@@ -824,6 +892,7 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
       Handle(Geom_BezierCurve) ProjCu = 
        Handle(Geom_BezierCurve)::DownCast(BezierCurvePtr->Copy());
 
+      myKeepParam = Standard_True;
       myIsApprox = Standard_False;
       myType = Type;
       for ( Standard_Integer i = 1; i <= NbPoles; i++) {
@@ -847,6 +916,7 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
       Handle(Geom_BSplineCurve) ProjectedBSplinePtr =
        Handle(Geom_BSplineCurve)::DownCast(BSplineCurvePtr->Copy()) ;
       
+      myKeepParam = Standard_True;
       myIsApprox = Standard_False;
       myType = Type;
       for ( Standard_Integer i = 1; i <= BSplineCurvePtr->NbPoles(); i++) {
@@ -862,6 +932,7 @@ void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
     break;
   default:
     {
+      myKeepParam = Standard_True;
       myIsApprox = Standard_True;
       myType     = GeomAbs_BSplineCurve;
       PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
diff --git a/tests/bugs/modalg_7/bug31016_01 b/tests/bugs/modalg_7/bug31016_01
new file mode 100644 (file)
index 0000000..e060fd2
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 1 10
+projonplane r c p 0
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_02 b/tests/bugs/modalg_7/bug31016_02
new file mode 100644 (file)
index 0000000..cef8994
--- /dev/null
@@ -0,0 +1,55 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 1 10
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 0
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_03 b/tests/bugs/modalg_7/bug31016_03
new file mode 100644 (file)
index 0000000..1b650b1
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+circle c 0 0 0  10
+plane p 0 0 0  1 0 1
+projonplane r c p 0
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_04 b/tests/bugs/modalg_7/bug31016_04
new file mode 100644 (file)
index 0000000..53d8c8a
--- /dev/null
@@ -0,0 +1,55 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+circle c 0 0 0  10
+plane p 0 0 0  1 0 1
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 0
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_05 b/tests/bugs/modalg_7/bug31016_05
new file mode 100644 (file)
index 0000000..3a23107
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+ellipse c 0 0 0  0.866025403784439 0 0.5  0.5 0 -0.866025403784439  20 10
+plane p 0 0 0  0 0 1
+projonplane r c p 0
+
+if {![regexp {Circle} [dump r]]} {
+  puts "ERROR: Projected curve is not a circle"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_06 b/tests/bugs/modalg_7/bug31016_06
new file mode 100644 (file)
index 0000000..bd31296
--- /dev/null
@@ -0,0 +1,55 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 0 1
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 0
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+parameters r [lindex $pnt 0] [lindex $pnt 1] [lindex $pnt 2] 0.1 shift
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+  set par1 [expr $par0 + [dval shift]]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par1 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_07 b/tests/bugs/modalg_7/bug31016_07
new file mode 100644 (file)
index 0000000..408f958
--- /dev/null
@@ -0,0 +1,51 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 1 10
+projonplane r c p 1
+
+if {![regexp {BSplineCurve} [dump r]]} {
+  puts "ERROR: Projected curve is not a B-spline curve"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-12} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_08 b/tests/bugs/modalg_7/bug31016_08
new file mode 100644 (file)
index 0000000..c10456e
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 1 10
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 1
+
+if {![regexp {BSplineCurve} [dump r]]} {
+  puts "ERROR: Projected curve is not a B-spline curve"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-12} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_09 b/tests/bugs/modalg_7/bug31016_09
new file mode 100644 (file)
index 0000000..5b2e0d5
--- /dev/null
@@ -0,0 +1,51 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+circle c 0 0 0  10
+plane p 0 0 0  1 0 1
+projonplane r c p 1
+
+if {![regexp {BSplineCurve} [dump r]]} {
+  puts "ERROR: Projected curve is not a B-spline curve"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-12} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_10 b/tests/bugs/modalg_7/bug31016_10
new file mode 100644 (file)
index 0000000..fd55195
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+circle c 0 0 0  10
+plane p 0 0 0  1 0 1
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 1
+
+if {![regexp {BSplineCurve} [dump r]]} {
+  puts "ERROR: Projected curve is not a B-spline curve"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-12} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_11 b/tests/bugs/modalg_7/bug31016_11
new file mode 100644 (file)
index 0000000..fe1c0d1
--- /dev/null
@@ -0,0 +1,51 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+ellipse c 0 0 0  0.866025403784439 0 0.5  0.5 0 -0.866025403784439  20 10
+plane p 0 0 0  0 0 1
+projonplane r c p 1
+
+if {![regexp {Circle} [dump r]]} {
+  puts "ERROR: Projected curve is not a circle"
+}
+
+proc toPlane {pln curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  set pr [proj p x y z]
+  regexp {Parameters: ([-0-9.+eE]+) ([-0-9.+eE]+)} $pr full u v
+  svalue p $u $v x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane [dval x]
+  lappend pntOnPlane [dval y]
+  lappend pntOnPlane [dval z]
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-12} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}
diff --git a/tests/bugs/modalg_7/bug31016_12 b/tests/bugs/modalg_7/bug31016_12
new file mode 100644 (file)
index 0000000..1bd5cc9
--- /dev/null
@@ -0,0 +1,53 @@
+puts "========"
+puts "OCC31016"
+puts "========"
+puts ""
+###################################################################
+# Projection of an ellipse or a circle is a B-spline in some cases
+###################################################################
+
+set projDir { 1 1 1 }
+
+ellipse c 0 0 0  0 0 1  2 1 0  20 10
+plane p 0 0 0  0 0 1
+projonplane r c p [lindex $projDir 0] [lindex $projDir 1] [lindex $projDir 2] 1
+
+if {![regexp {Ellipse} [dump r]]} {
+  puts "ERROR: Projected curve is not an ellipse"
+}
+
+proc toPlane {pln dir curve param} {
+  upvar $pln p
+  upvar $curve crv
+  cvalue crv $param x y z
+  line ln x y z [lindex $dir 0] [lindex $dir 1] [lindex $dir 2]
+  intersect pt ln p
+  regexp {Point : ([-0-9.+eE]+), ([-0-9.+eE]+), ([-0-9.+eE]+)} [dump pt] full x y z
+
+  set pntOnPlane {}
+  lappend pntOnPlane $x
+  lappend pntOnPlane $y
+  lappend pntOnPlane $z
+  return $pntOnPlane
+}
+
+# calculate a parametric shift on the projected curve
+set pnt [toPlane p $projDir c 0]
+
+set nbPoints 100
+for {set i 0} {$i <= $nbPoints} {incr i} {
+  set par0 [expr 8*atan(1)*$i/$nbPoints]
+
+  set pnt [toPlane p $projDir c $par0]
+  cvalue r $par0 X Y Z
+
+  set dx [expr [lindex $pnt 0]-[dval X]]
+  set dy [expr [lindex $pnt 1]-[dval Y]]
+  set dz [expr [lindex $pnt 2]-[dval Z]]
+
+  if {[expr $dx*$dx + $dy*$dy + $dz*$dz] < 1.e-14} {
+    puts "OK: Projection correct"
+  } else {
+    puts "ERROR: Projection incorrect"
+  }
+}