]> OCCT Git - occt-copy.git/commitdiff
0027677: Incorrect CUT of a solid by semi-infinite solid
authorazv <azv@opencascade.com>
Mon, 18 Jul 2016 12:51:23 +0000 (15:51 +0300)
committerazv <azv@opencascade.com>
Mon, 18 Jul 2016 12:51:23 +0000 (15:51 +0300)
The problem of incorrect CUT is wrong Pcurve after projection onto cylinder of a small edge orthogonal to cylinder's axis. The result of projection is a line along V direction, but it should be along U.

ProjLib_Cylinder has no specific functionality to build projection in most common case, so it should return "not done" flag to start projection based on curve approximation.

Following changes are done:
1. ProjLib_Cylinder returns isDone=false in the following cases:
  * the projected line is not parallel to cylinder's axis
  * the plane of projected circle is not orthogonal to cylinder's axis
2. Test case added

src/ProjLib/ProjLib_Cylinder.cxx
src/ProjLib/ProjLib_ProjectedCurve.cxx

index e8f3cae7d71211df68be05943a13cb62c7458565..c67701e4380f0e5c60f5d0ad857ee181c44c255b 100644 (file)
@@ -129,6 +129,12 @@ static gp_Pnt2d EvalPnt2d( const gp_Pnt& P, const gp_Cylinder& Cy )
 
 void  ProjLib_Cylinder::Project(const gp_Lin& L)
 {
+  // Check the line is parallel to the axis of cylinder.
+  // In other cases, the projection is wrong.
+  if (L.Direction().XYZ().CrossSquareMagnitude(myCylinder.Position().Direction().XYZ()) >
+      Precision::Angular() * Precision::Angular())
+    return;
+
   myType = GeomAbs_Line;
 
   gp_Pnt2d P2d = EvalPnt2d(L.Location(),myCylinder);
@@ -152,23 +158,26 @@ void  ProjLib_Cylinder::Project(const gp_Lin& L)
 
 void  ProjLib_Cylinder::Project(const gp_Circ& C)
 {
+  // Check the circle's normal is parallel to the axis of cylinder.
+  // In other cases, the projection is wrong.
+  const gp_Ax3& aCylPos = myCylinder.Position();
+  const gp_Ax2& aCircPos = C.Position();
+  if (aCylPos.Direction().XYZ().CrossSquareMagnitude(aCircPos.Direction().XYZ()) >
+      Precision::Angular() * Precision::Angular())
+    return;
+
   myType = GeomAbs_Line;
 
-  gp_Dir ZCyl = myCylinder.Position().XDirection().Crossed
-    (myCylinder.Position().YDirection());
-  gp_Dir ZCir = C.Position().XDirection().Crossed
-    (C.Position().YDirection());
+  gp_Dir ZCyl = aCylPos.XDirection().Crossed(aCylPos.YDirection());
 
-  Standard_Real U = myCylinder.Position().XDirection()
-    .AngleWithRef(C.Position().XDirection(), ZCyl);
+  Standard_Real U = aCylPos.XDirection().AngleWithRef(aCircPos.XDirection(), ZCyl);
 
   gp_Vec OP( myCylinder.Location(),C.Location());
-  Standard_Real V = OP.Dot(gp_Vec(myCylinder.Position().Direction()));
-
+  Standard_Real V = OP.Dot(gp_Vec(aCylPos.Direction()));
 
   gp_Pnt2d P2d1 (U, V);
   gp_Dir2d D2d;
-  if ( ZCyl.Dot(ZCir) > 0.) 
+  if ( ZCyl.Dot(aCircPos.Direction()) > 0.) 
     D2d.SetCoord(1., 0.);
   else
     D2d.SetCoord(-1., 0.);
index 625766b69aacc40067cc7dc9a8b8a2944efb6839..f35ad02cbc8ac86e6300875a4234eacf7151fe1e 100644 (file)
@@ -606,6 +606,8 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
   {
     // Use advanced analytical projector if base analytical projection failed.
     ProjLib_ComputeApprox Comp( myCurve, mySurface, myTolerance);
+    if (Comp.Bezier().IsNull() && Comp.BSpline().IsNull())
+      return; // advanced projector has been failed too
     myResult.Done();
 
     // set the type