0030477: Visualization - crash in AIS_Manipulator::ObjectTransformation after using...
[occt.git] / src / AIS / AIS_Manipulator.cxx
index d0794af..e47a6c3 100644 (file)
@@ -55,6 +55,68 @@ namespace
     }
     throw Standard_ProgramError ("AIS_Manipulator - Invalid axis index");
   }
+
+  //! Auxiliary tool for filtering picking ray.
+  class ManipSensRotation
+  {
+  public:
+    //! Main constructor.
+    ManipSensRotation (const gp_Dir& thePlaneNormal) : myPlaneNormal (thePlaneNormal), myAngleTol (10.0 * M_PI / 180.0) {}
+
+    //! Checks if picking ray can be used for detection.
+    Standard_Boolean isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
+    {
+      if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+      {
+        return Standard_False;
+      }
+
+      const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt());
+      return !aRay.IsNormal (myPlaneNormal, myAngleTol);
+    }
+  private:
+    gp_Dir        myPlaneNormal;
+    Standard_Real myAngleTol;
+  };
+
+  //! Sensitive circle with filtering picking ray.
+  class ManipSensCircle : public Select3D_SensitiveCircle, public ManipSensRotation
+  {
+  public:
+    //! Main constructor.
+    ManipSensCircle (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+                     const Handle(Geom_Circle)& theCircle,
+                     const Standard_Integer theNbPnts)
+    : Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False, theNbPnts),
+      ManipSensRotation (theCircle->Position().Direction()) {}
+
+    //! Checks whether the circle overlaps current selecting volume
+    virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
+                                      SelectBasics_PickResult& thePickResult) Standard_OVERRIDE
+    {
+      return isValidRay (theMgr)
+          && Select3D_SensitiveCircle::Matches (theMgr, thePickResult);
+    }
+  };
+
+  //! Sensitive triangulation with filtering picking ray.
+  class ManipSensTriangulation : public Select3D_SensitiveTriangulation, public ManipSensRotation
+  {
+  public:
+    ManipSensTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+                            const Handle(Poly_Triangulation)& theTrg,
+                            const gp_Dir& thePlaneNormal)
+    : Select3D_SensitiveTriangulation (theOwnerId, theTrg, TopLoc_Location(), Standard_True),
+      ManipSensRotation (thePlaneNormal) {}
+
+    //! Checks whether the circle overlaps current selecting volume
+    virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
+                                      SelectBasics_PickResult& thePickResult) Standard_OVERRIDE
+    {
+      return isValidRay (theMgr)
+          && Select3D_SensitiveTriangulation::Matches (theMgr, thePickResult);
+    }
+  };
 }
 
 //=======================================================================
@@ -209,6 +271,18 @@ void AIS_Manipulator::SetPart (const Standard_Integer theAxisIndex, const AIS_Ma
   }
 }
 
+//=======================================================================
+//function : SetPart
+//purpose  : 
+//=======================================================================
+void AIS_Manipulator::SetPart (const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled)
+{
+  for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+  {
+    SetPart (anIt, theMode, theIsEnabled);
+  }
+}
+
 //=======================================================================
 //function : EnableMode
 //purpose  : 
@@ -419,6 +493,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       const gp_Lin aLine (myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
       Extrema_ExtElC anExtrema (anInputLine, aLine, Precision::Angular());
       if (!anExtrema.IsDone()
+        || anExtrema.IsParallel()
         || anExtrema.NbExt() != 1)
       {
         // translation cannot be done co-directed with camera
@@ -464,7 +539,9 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       const gp_Pnt aPosLoc   = myStartPosition.Location();
       const gp_Ax1 aCurrAxis = getAx1FromAx2Dir (myStartPosition, myCurrentIndex);
       IntAna_IntConicQuad aIntersector (anInputLine, gp_Pln (aPosLoc, aCurrAxis.Direction()), Precision::Angular(), Precision::Intersection());
-      if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1)
+      if (!aIntersector.IsDone()
+        || aIntersector.IsParallel()
+        || aIntersector.NbPoints() < 1)
       {
         return Standard_False;
       }
@@ -933,10 +1010,14 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
+      if (!myAxes[anIt].HasTranslation())
+      {
+        continue;
+      }
       const Axis& anAxis = myAxes[anIt];
       if (aMode != AIS_MM_None)
       {
-        anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
+        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
       }
       // define sensitivity by line
       Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
@@ -954,6 +1035,10 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
+      if (!myAxes[anIt].HasRotation())
+      {
+        continue;
+      }
       const Axis& anAxis = myAxes[anIt];
       if (aMode != AIS_MM_None)
       {
@@ -961,11 +1046,11 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       }
       // define sensitivity by circle
       Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
-      Handle(Select3D_SensitiveCircle) aCircle = new Select3D_SensitiveCircle (anOwner, aGeomCircle, Standard_False, anAxis.FacettesNumber());
+      Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
       aCircle->SetSensitivityFactor (15);
       theSelection->Add (aCircle);
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), TopLoc_Location(), Standard_True);
+      Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
       theSelection->Add (aTri);
     }
   }
@@ -974,6 +1059,10 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
+      if (!myAxes[anIt].HasScaling())
+      {
+        continue;
+      }
       if (aMode != AIS_MM_None)
       {
         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);