0025368: BREPExtrma DistShapeShape gives wrong result for Sphere and Line
authoraml <aml@opencascade.com>
Fri, 24 Oct 2014 03:44:40 +0000 (07:44 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 30 Oct 2014 10:43:04 +0000 (13:43 +0300)
Changed analytical Sphere/Line and Cylinder/Line extrema algorithms. Now they search perpendicular and intersection points.
Test cases added.

src/Extrema/Extrema_ExtElCS.cxx
tests/bugs/modalg_5/bug25368_1 [new file with mode: 0644]
tests/bugs/modalg_5/bug25368_2 [new file with mode: 0644]

index 48d8ed4..6eaac11 100644 (file)
@@ -72,7 +72,7 @@ Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
 
 
 void Extrema_ExtElCS::Perform(const gp_Lin& C,
-                             const gp_Cylinder& S)
+                              const gp_Cylinder& S)
 {
   myDone = Standard_False;
   myNbExt = 0;
@@ -85,6 +85,7 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C,
   Standard_Real radius = S.Radius();
   Extrema_ExtElC Extrem(gp_Lin(Pos.Axis()), C, Precision::Angular());
   if (Extrem.IsParallel()) {
+    // Line direction is similar to cylinder axis of rotation.
     mySqDist = new TColStd_HArray1OfReal(1, 1);
     myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1);
     myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1);
@@ -117,42 +118,28 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C,
     myIsPar = Standard_True;
   }
   else {
-    Standard_Integer i;
-    
+    Standard_Integer i, aStartIdx = 0;
+
     Extrema_POnCurv myPOnC1, myPOnC2;
     Extrem.Points(1, myPOnC1, myPOnC2);
     gp_Pnt PonAxis = myPOnC1.Value();
     gp_Pnt PC = myPOnC2.Value();
 
-    // line is tangent or outside of the cylunder -- single solution
-    if (radius - PonAxis.Distance(PC) < Precision::PConfusion())
-    {
-      Extrema_ExtPElS ExPS(PC, S, Precision::Confusion());
-      if (ExPS.IsDone()) {
-        myNbExt = ExPS.NbExt();
-        mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
-        myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
-        myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
-        for (i = 1; i <= myNbExt; i++) {
-          myPoint1->SetValue(i, myPOnC2);
-          myPoint2->SetValue(i, ExPS.Point(i));
-          mySqDist->SetValue(i,(myPOnC2.Value()).SquareDistance(ExPS.Point(i).Value()));
-        }
-      }
-    }
     // line intersects the cylinder
-    else
+    if (radius - PonAxis.Distance(PC) > Precision::PConfusion())
     {
       IntAna_Quadric theQuadric(S);
       IntAna_IntConicQuad Inters(C, theQuadric);
       if (Inters.IsDone())
       {
         myNbExt = Inters.NbPoints();
+        aStartIdx = myNbExt;
         if (myNbExt > 0)
         {
-          mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
-          myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
-          myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
+          // Not more than 2 additional points from perpendiculars.
+          mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2);
+          myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2);
+          myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2);
           Standard_Real u, v, w;
           for (i = 1; i <= myNbExt; i++)
           {
@@ -168,6 +155,27 @@ void Extrema_ExtElCS::Perform(const gp_Lin& C,
         }
       }
     }
+
+    // line is tangent or outside of the cylinder
+    Extrema_ExtPElS ExPS(PC, S, Precision::Confusion());
+      if (ExPS.IsDone())
+      {
+        if (aStartIdx == 0)
+        {
+          myNbExt = ExPS.NbExt();
+          mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
+          myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
+          myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
+        }
+        else
+          myNbExt += ExPS.NbExt();
+
+        for (i = aStartIdx + 1; i <= myNbExt; i++) {
+          myPoint1->SetValue(i, myPOnC2);
+          myPoint2->SetValue(i, ExPS.Point(i - aStartIdx));
+          mySqDist->SetValue(i,(myPOnC2.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value()));
+        }
+      }
     myDone = Standard_True;
   }
 
@@ -203,33 +211,75 @@ Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
 
 
 void Extrema_ExtElCS::Perform(const gp_Lin& C,
-                             const gp_Sphere& S)
+                              const gp_Sphere& S)
 {
+  // In case of intersection - return four points:
+  // 2 intersection points and 2 perpendicular.
+  // No intersection - only min and max.
+
   myDone = Standard_False;
   myNbExt = 0;
   myIsPar = Standard_False;
+  Standard_Integer aStartIdx = 0;
 
-  gp_Pnt O = S.Location();
+  gp_Pnt aCenter = S.Location();
 
-  Extrema_ExtPElC Extrem(O, C, Precision::Angular(), RealFirst(), RealLast());
+  Extrema_ExtPElC Extrem(aCenter, C, Precision::Angular(), RealFirst(), RealLast());
 
   Standard_Integer i;
-  if (Extrem.IsDone()) {
+  if (Extrem.IsDone() &&
+      Extrem.NbExt() > 0)
+  {
     Extrema_POnCurv myPOnC1 =  Extrem.Point(1);
+    if (myPOnC1.Value().Distance(aCenter) <= S.Radius())
+    {
+      IntAna_IntConicQuad aLinSphere(C, S);
+      if (aLinSphere.IsDone())
+      {
+        myNbExt = aLinSphere.NbPoints();
+        aStartIdx = myNbExt;
+        // Not more than 2 additional points from perpendiculars.
+        mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2);
+        myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2);
+        myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2);
+
+        for (i = 1; i <= myNbExt; i++)
+        {
+          Extrema_POnCurv aCPnt(aLinSphere.ParamOnConic(i), aLinSphere.Point(i));
+
+          Standard_Real u,v;
+          ElSLib::Parameters(S, aLinSphere.Point(i), u, v);
+          Extrema_POnSurf aSPnt(u, v, aLinSphere.Point(i));
+
+          myPoint1->SetValue(i, aCPnt);
+          myPoint2->SetValue(i, aSPnt);
+          mySqDist->SetValue(i,(aCPnt.Value()).SquareDistance(aSPnt.Value()));
+        }
+      }
+    }
+
     Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion());
-    if (ExPS.IsDone()) {
-      myNbExt = ExPS.NbExt();
-      mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
-      myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
-      myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
-      for (i = 1; i <= myNbExt; i++) {
-       myPoint1->SetValue(i, myPOnC1);
-       myPoint2->SetValue(i, ExPS.Point(i));
-       mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i).Value()));
-       myDone = Standard_True;
+    if (ExPS.IsDone())
+    {
+      if (aStartIdx == 0)
+      {
+        myNbExt = ExPS.NbExt();
+        mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
+        myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
+        myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
+      }
+      else
+        myNbExt += ExPS.NbExt();
+
+      for (i = aStartIdx + 1; i <= myNbExt; i++)
+      {
+        myPoint1->SetValue(i, myPOnC1);
+        myPoint2->SetValue(i, ExPS.Point(i - aStartIdx));
+        mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value()));
       }
     }
   }
+  myDone = Standard_True;
 }
 
 
diff --git a/tests/bugs/modalg_5/bug25368_1 b/tests/bugs/modalg_5/bug25368_1
new file mode 100644 (file)
index 0000000..af3e75a
--- /dev/null
@@ -0,0 +1,29 @@
+puts "=========="
+puts "OCC25368"
+puts "=========="
+puts ""
+################################################
+# BREPExtrma DistShapeShape gives wrong result for Sphere and Line
+################################################
+
+sphere s 0 0 0 5
+line l 0 0 0.2 1 1 0
+trim l l 0 10
+
+set extrema_res [extrema l s]
+set extrema_length [llength ${extrema_res} ]
+
+#Amount Check
+if {${extrema_length} != 10 } {
+   puts "Error: Invalid extrema number in extrema output"
+}
+regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x y z
+
+# Point check
+set good_x 3.5327043465311383
+set good_y 3.5327043465311383
+set good_z 0.20
+checkreal "Intersection point x:" ${x} ${good_x} 0.01 0.01
+checkreal "Intersection point y:" ${y} ${good_y} 0.01 0.01
+checkreal "Intersection point z:" ${z} ${good_z} 0.01 0.01
+
diff --git a/tests/bugs/modalg_5/bug25368_2 b/tests/bugs/modalg_5/bug25368_2
new file mode 100644 (file)
index 0000000..5daf8f9
--- /dev/null
@@ -0,0 +1,41 @@
+puts "=========="
+puts "OCC25368"
+puts "=========="
+puts ""
+################################################
+# BREPExtrma DistShapeShape gives wrong result for Sphere and Line
+################################################
+
+sphere s 0 0 0 4.5
+rotate s 0 0.5 1 1 1 0.5 34.9
+line l -0.79 0.88 1.22 0.579 1.765 0.576
+
+set extrema_res [extrema l s]
+set extrema_length [llength ${extrema_res} ]
+
+# Amount check
+if {${extrema_length} != 18 } {
+  puts "Error: expected only two lines as result of extrema!"
+}
+
+# Distance check on ext_1
+set info [dump ext_1]
+regexp {Extrema 1 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x1 y1 z1
+# Point check
+set good_x1 -2.2838350838816694
+set good_y1 -3.6737459810900646
+set good_z1 -0.2660950057268425
+checkreal "Intersection point x:" ${x1} ${good_x1} 0.01 0.01
+checkreal "Intersection point y:" ${y1} ${good_y1} 0.01 0.01
+checkreal "Intersection point z:" ${z1} ${good_z1} 0.01 0.01
+
+
+# Distance check on ext_2
+regexp {Extrema 2 is point : +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $extrema_res full x2 y2 z2
+# Point check
+set good_x2 0.29086178559218934
+set good_y2 4.1748550113475211
+set good_z2 2.2952614654595873
+checkreal "Intersection point x:" ${x2} ${good_x2} 0.01 0.01
+checkreal "Intersection point y:" ${y2} ${good_y2} 0.01 0.01
+checkreal "Intersection point z:" ${z2} ${good_z2} 0.01 0.01