0029084: Visualization, AIS_Manipulator - broken transformation is applied at Rotatio...
authorkgv <kgv@opencascade.com>
Tue, 5 Sep 2017 09:14:02 +0000 (12:14 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 22 Sep 2017 08:51:33 +0000 (11:51 +0300)
AIS_Manipulator::ObjectTransformation() - fixed using of manipulator axes
with temporarily applied transformation (when BehaviorOnTransform::FollowRotation is TRUE).
Start axes orientation (at the beginning of Rotation) is now used instead.

src/AIS/AIS_Manipulator.cxx
src/AIS/AIS_Manipulator.hxx
src/V3d/V3d_View.cxx
tests/v3d/manipulator/rotate2 [new file with mode: 0644]

index 32e7080..8dabf9d 100644 (file)
@@ -43,6 +43,22 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject)
 
 IMPLEMENT_HSEQUENCE(AIS_ManipulatorObjectSequence)
 
+namespace
+{
+  //! Return Ax1 for specified direction of Ax2.
+  static gp_Ax1 getAx1FromAx2Dir (const gp_Ax2& theAx2,
+                                  int theIndex)
+  {
+    switch (theIndex)
+    {
+      case 0: return gp_Ax1 (theAx2.Location(), theAx2.XDirection());
+      case 1: return gp_Ax1 (theAx2.Location(), theAx2.YDirection());
+      case 2: return theAx2.Axis();
+    }
+    throw Standard_ProgramError ("AIS_Manipulator - Invalid axis index");
+  }
+}
+
 //=======================================================================
 //function : init
 //purpose  : 
@@ -384,22 +400,19 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
   // Initialize start reference data
   if (!myHasStartedTransformation)
   {
-    Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
     myStartTrsfs.Clear();
-    for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
+    Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
+    for (AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects); anObjIter.More(); anObjIter.Next())
     {
-      myStartTrsfs.Append (anObjects->Value (anIt)->LocalTransformation());
+      myStartTrsfs.Append (anObjIter.Value()->LocalTransformation());
     }
     myStartPosition = myPosition;
   }
 
   // Get 3d point with projection vector
-  Graphic3d_Vec3d anInputPoint;
-  Graphic3d_Vec3d aProj;
+  Graphic3d_Vec3d anInputPoint, aProj;
   theView->ConvertWithProj (theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z());
-  gp_Lin anInputLine (gp_Pnt (anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir (aProj.x(), aProj.y(), aProj.z()));
-  gp_Pnt aNewPosition = gp::Origin();
-
+  const gp_Lin anInputLine (gp_Pnt (anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir (aProj.x(), aProj.y(), aProj.z()));
   switch (myCurrentMode)
   {
     case AIS_MM_Translation:
@@ -410,7 +423,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
       gp_Pnt aP1, aP2;
       anExtrema.NearestPoints (aP1, aP2);
-      aNewPosition = aP2;
+      const gp_Pnt aNewPosition = aP2;
 
       if (!myHasStartedTransformation)
       {
@@ -427,26 +440,28 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       gp_Trsf aNewTrsf;
       aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
       theTrsf *= aNewTrsf;
-      break;
+      return Standard_True;
     }
     case AIS_MM_Rotation:
     {
+      const gp_Pnt aPosLoc   = myStartPosition.Location();
+      const gp_Ax1 aCurrAxis = getAx1FromAx2Dir (myStartPosition, myCurrentIndex);
+
       Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
-      Handle(Geom_Surface) aSurface = new Geom_Plane (myPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
+      Handle(Geom_Surface) aSurface = new Geom_Plane (aPosLoc, aCurrAxis.Direction());
       GeomAPI_IntCS aIntersector (anInputCurve, aSurface);
       if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1)
       {
         return Standard_False;
       }
 
-      aNewPosition = aIntersector.Point (1);
-
+      const gp_Pnt aNewPosition = aIntersector.Point (1);
       if (!myHasStartedTransformation)
       {
         myStartPick = aNewPosition;
         myHasStartedTransformation = Standard_True;
-        gp_Dir aStartAxis = gce_MakeDir (myPosition.Location(), myStartPick);
-        myPrevState = aStartAxis.AngleWithRef (gce_MakeDir(myPosition.Location(), aNewPosition), myAxes[myCurrentIndex].Position().Direction());
+        gp_Dir aStartAxis = gce_MakeDir (aPosLoc, myStartPick);
+        myPrevState = aStartAxis.AngleWithRef (gce_MakeDir(aPosLoc, aNewPosition), aCurrAxis.Direction());
         return Standard_True;
       }
 
@@ -455,17 +470,17 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
         return Standard_False;
       }
 
-      gp_Dir aStartAxis = myPosition.Location().IsEqual (myStartPick, Precision::Confusion())
-        ? myAxes[(myCurrentIndex + 1) % 3].Position().Direction()
-        : gce_MakeDir (myPosition.Location(), myStartPick);
+      gp_Dir aStartAxis = aPosLoc.IsEqual (myStartPick, Precision::Confusion())
+        ? getAx1FromAx2Dir (myStartPosition, (myCurrentIndex + 1) % 3).Direction()
+        : gce_MakeDir (aPosLoc, myStartPick);
 
-      gp_Dir aCurrentAxis = gce_MakeDir (myPosition.Location(), aNewPosition);
-      Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, myAxes[myCurrentIndex].Position().Direction());
+      gp_Dir aCurrentAxis = gce_MakeDir (aPosLoc, aNewPosition);
+      Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, aCurrAxis.Direction());
 
       // Change value of an angle if it should have different sign.
       if (anAngle * myPrevState < 0 && Abs (anAngle) < M_PI_2)
       {
-        Standard_ShortReal aSign = myPrevState > 0 ? -1.0f : 1.0f;
+        Standard_Real aSign = myPrevState > 0 ? -1.0 : 1.0;
         anAngle = aSign * (M_PI * 2 - anAngle);
       }
 
@@ -475,10 +490,10 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       }
 
       gp_Trsf aNewTrsf;
-      aNewTrsf.SetRotation (myAxes[myCurrentIndex].Position(), anAngle);
+      aNewTrsf.SetRotation (aCurrAxis, anAngle);
       theTrsf *= aNewTrsf;
       myPrevState = anAngle;
-      break;
+      return Standard_True;
     }
     case AIS_MM_Scaling:
     {
@@ -486,7 +501,7 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
       Handle(Geom_Curve) aCurve = new Geom_Line (aLine);
       GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
-      gp_Pnt aTmp;
+      gp_Pnt aNewPosition, aTmp;
       anExtrema.NearestPoints (aTmp, aNewPosition);
 
       if (!myHasStartedTransformation)
@@ -508,13 +523,14 @@ Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer t
       aNewTrsf.SetScale (myPosition.Location(), aCoeff);
 
       theTrsf = aNewTrsf;
-      break;
+      return Standard_True;
     }
     case AIS_MM_None:
+    {
       return Standard_False;
+    }
   }
-
-  return Standard_True;
+  return Standard_False;
 }
 
 //=======================================================================
@@ -544,18 +560,19 @@ void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
   }
 
   myHasStartedTransformation = Standard_False;
-
-  if (!theToApply)
+  if (theToApply)
   {
-    Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
-
-    for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
-    {
-      anObjects->Value (anIt)->SetLocalTransformation (myStartTrsfs(anIt));
-    }
+    return;
+  }
 
-    SetPosition (myStartPosition);
+  Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
+  AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
+  NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
+  for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
+  {
+    anObjIter.ChangeValue()->SetLocalTransformation (aTrsfIter.Value());
   }
+  SetPosition (myStartPosition);
 }
 
 //=======================================================================
@@ -569,11 +586,14 @@ void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
     return;
   }
 
-  Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
-
-  for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
   {
-    anObjects->Value (anIt)->SetLocalTransformation (theTrsf * myStartTrsfs(anIt));
+    Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
+    AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
+    NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
+    for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
+    {
+      anObjIter.ChangeValue()->SetLocalTransformation (theTrsf * aTrsfIter.Value());
+    }
   }
 
   if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation)
@@ -613,10 +633,9 @@ void AIS_Manipulator::SetPosition (const gp_Ax2& thePosition)
    || !myPosition.XDirection().IsEqual (thePosition.XDirection(), Precision::Angular()))
   {
     myPosition = thePosition;
-    myAxes[0].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.XDirection()));
-    myAxes[1].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.YDirection()));
-    myAxes[2].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.Direction()));
-
+    myAxes[0].SetPosition (getAx1FromAx2Dir (thePosition, 0));
+    myAxes[1].SetPosition (getAx1FromAx2Dir (thePosition, 1));
+    myAxes[2].SetPosition (getAx1FromAx2Dir (thePosition, 2));
     updateTransformation();
   }
 }
index 1562bb6..e8f321b 100644 (file)
@@ -215,18 +215,18 @@ public:
   //! @return true if manipulator is attached to some interactive object (has owning object).
   Standard_Boolean IsAttached() const { return HasOwner(); }
 
-  //! @return true if some part of manipulator is selected (tranformation mode is active, and owning object can be rtansformated).
+  //! @return true if some part of manipulator is selected (transformation mode is active, and owning object can be transformed).
   Standard_Boolean HasActiveMode() const { return IsAttached() && myCurrentMode != AIS_MM_None; }
 
   Standard_Boolean HasActiveTransformation() { return myHasStartedTransformation; }
 
-  gp_Trsf StartTransformation() const { return myStartTrsfs.Size() < 1 ? gp_Trsf() : myStartTrsfs(1); }
+  gp_Trsf StartTransformation() const { return !myStartTrsfs.IsEmpty() ? myStartTrsfs.First() : gp_Trsf(); }
 
-  gp_Trsf StartTransformation (const Standard_Integer theIndex) const
+  gp_Trsf StartTransformation (Standard_Integer theIndex) const
   {
     Standard_ProgramError_Raise_if (theIndex < 1 || theIndex > Objects()->Upper(),
       "AIS_Manipulator::StartTransformation(): theIndex is out of bounds");
-    return myStartTrsfs.Size() < 1 ? gp_Trsf() : myStartTrsfs (theIndex);
+    return !myStartTrsfs.IsEmpty() ? myStartTrsfs (theIndex) : gp_Trsf();
   }
 
 public: //! @name Configuration of graphical transformations
@@ -245,7 +245,7 @@ public: //! @name Configuration of graphical transformations
   //! Redefines transform persistence management to setup transformation for sub-presentation of axes.
   //! @warning this interactive object does not support custom transformation persistence when
   //! using \sa ZoomPersistence mode. In this mode the transformation persistence flags for
-  //! presentations are overriden by this class.
+  //! presentations are overridden by this class.
   //! @warning Invokes debug assertion to catch incompatible usage of the method with \sa ZoomPersistence mode,
   //! silently does nothing in release mode.
   //! @warning revise use of AdjustSize argument of of \sa AttachToObjects method
@@ -298,17 +298,17 @@ public:
 public: //! @name Presentation computation
 
   //! Fills presentation.
-  //! @note Manipulator presentation does not use display mode and for all modes has the same presenatation.
+  //! @note Manipulator presentation does not use display mode and for all modes has the same presentation.
   Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
                                         const Handle(Prs3d_Presentation)& thePrs,
                                         const Standard_Integer theMode = 0) Standard_OVERRIDE;
 
   //! Computes selection sensitive zones (triangulation) for manipulator.
-  //! @param theNode [in] Seldction mode that is treated as transformation mode.
+  //! @param theNode [in] Selection mode that is treated as transformation mode.
   Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
                                                  const Standard_Integer theMode) Standard_OVERRIDE;
 
-  //! Disables auto highlighting to use HilightSelected() and HilightOwnerWithColor() overriden methods.
+  //! Disables auto highlighting to use HilightSelected() and HilightOwnerWithColor() overridden methods.
   Standard_EXPORT virtual Standard_Boolean IsAutoHilight() const Standard_OVERRIDE
   {
     return Standard_False;
@@ -352,7 +352,7 @@ protected:
   Standard_EXPORT virtual void setLocalTransformation (const Handle(Geom_Transformation)& theTrsf) Standard_OVERRIDE;
   using AIS_InteractiveObject::SetLocalTransformation; // hide visibility
 
-protected: //! @name Auxilliary classes to fill presentation with proper primitives
+protected: //! @name Auxiliary classes to fill presentation with proper primitives
 
   class Quadric
   {
@@ -616,16 +616,16 @@ protected:
 
   Axis myAxes[3]; //!< Tree axes of the manipulator.
   Sphere myCenter; //!< Visual part displaying the center sphere of the manipulator.
-  gp_Ax2 myPosition; //!< Position of the manipualtor object. it displayes its location and position of its axes.
+  gp_Ax2 myPosition; //!< Position of the manipulator object. it displays its location and position of its axes.
 
   Standard_Integer myCurrentIndex; //!< Index of active axis.
-  AIS_ManipulatorMode myCurrentMode; //!< Name of active manipualtion mode.
+  AIS_ManipulatorMode myCurrentMode; //!< Name of active manipulation mode.
 
   Standard_Boolean myIsActivationOnDetection; //!< Manual activation of modes (not on parts selection).
   Standard_Boolean myIsZoomPersistentMode; //!< Zoom persistence mode activation.
   BehaviorOnTransform myBehaviorOnTransform; //!< Behavior settings applied on manipulator when transforming an object.
 
-protected: //! @name Fields for interactive trnasformation. Fields only for internal needs. They do not have public interface.
+protected: //! @name Fields for interactive transformation. Fields only for internal needs. They do not have public interface.
 
   NCollection_Sequence<gp_Trsf> myStartTrsfs; //!< Owning object transformation for start. It is used internally.
   Standard_Boolean myHasStartedTransformation; //!< Shows if transformation is processed (sequential calls of Transform()).
@@ -633,7 +633,7 @@ protected: //! @name Fields for interactive trnasformation. Fields only for inte
   gp_Pnt myStartPick; //! 3d point corresponding to start mouse pick.
   Standard_Real myPrevState; //! Previous value of angle during rotation.
 
-  //! Aspect used to colour current detected part and current selected part.
+  //! Aspect used to color current detected part and current selected part.
   Handle(Prs3d_ShadingAspect) myHighlightAspect;
 public:
 
index 9b1c914..cd15176 100644 (file)
@@ -1795,45 +1795,38 @@ void V3d_View::Convert(const Standard_Integer Xp,
 //function : ConvertWithProj
 //purpose  :
 //=======================================================================
-void V3d_View::ConvertWithProj(const Standard_Integer Xp,
-                               const Standard_Integer Yp,
-                               Standard_Real& X,
-                               Standard_Real& Y,
-                               Standard_Real& Z,
-                               Standard_Real& Dx,
-                               Standard_Real& Dy,
-                               Standard_Real& Dz) const
+void V3d_View::ConvertWithProj(const Standard_Integer theXp,
+                               const Standard_Integer theYp,
+                               Standard_Real& theX,
+                               Standard_Real& theY,
+                               Standard_Real& theZ,
+                               Standard_Real& theDx,
+                               Standard_Real& theDy,
+                               Standard_Real& theDz) const
 {
   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
-  Standard_Integer aHeight, aWidth;
+  Standard_Integer aHeight = 0, aWidth = 0;
   MyWindow->Size (aWidth, aHeight);
 
-  Standard_Real anX = 2.0 * Xp / aWidth - 1.0;
-  Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0;
-  Standard_Real  aZ = 2.0 * 0.0 - 1.0;
-
-  Handle(Graphic3d_Camera) aCamera = Camera();
-
-  gp_Pnt aResult = aCamera->UnProject (gp_Pnt (anX, anY, aZ));
-
-  X = aResult.X();
-  Y = aResult.Y();
-  Z = aResult.Z();
-
-  Graphic3d_Vertex aVrp;
-  aVrp.SetCoord (X, Y, Z);
+  const Standard_Real anX = 2.0 * theXp / aWidth - 1.0;
+  const Standard_Real anY = 2.0 * (aHeight - 1 - theYp) / aHeight - 1.0;
+  const Standard_Real  aZ = 2.0 * 0.0 - 1.0;
 
-  aResult = aCamera->UnProject (gp_Pnt (anX, anY, aZ - 10.0));
+  const Handle(Graphic3d_Camera)& aCamera = Camera();
+  const gp_Pnt aResult1 = aCamera->UnProject (gp_Pnt (anX, anY, aZ));
+  const gp_Pnt aResult2 = aCamera->UnProject (gp_Pnt (anX, anY, aZ - 10.0));
 
-  Graphic3d_Vec3d aNormDir;
-  aNormDir.x() = X - aResult.X();
-  aNormDir.y() = Y - aResult.Y();
-  aNormDir.z() = Z - aResult.Z();
+  theX = aResult1.X();
+  theY = aResult1.Y();
+  theZ = aResult1.Z();
+  Graphic3d_Vec3d aNormDir (theX - aResult2.X(),
+                            theY - aResult2.Y(),
+                            theZ - aResult2.Z());
   aNormDir.Normalize();
 
-  Dx = aNormDir.x();
-  Dy = aNormDir.y();
-  Dz = aNormDir.z();
+  theDx = aNormDir.x();
+  theDy = aNormDir.y();
+  theDz = aNormDir.z();
 }
 
 //=======================================================================
diff --git a/tests/v3d/manipulator/rotate2 b/tests/v3d/manipulator/rotate2
new file mode 100644 (file)
index 0000000..2645db6
--- /dev/null
@@ -0,0 +1,22 @@
+puts "=================================="
+puts "0029084: Visualization, AIS_Manipulator - broken transformation is applied at Rotation angles near to Pi"
+puts "=================================="
+
+pload MODELING VISUALIZATION
+box b 1 2 3
+vclear
+vinit View1
+vdisplay -dispMode 0 b
+vpoint p0 0 0 0
+vtop
+vfit
+vmanipulator m -attach b
+vmoveto 135 275
+vselect 135 275
+vmanipulator m -startTransform 135 275
+vdump $imagedir/${casename}_0.png
+for {set x 250} {$x < 400} {set x [expr $x+5]} { vmanipulator m -transform $x 400 }
+vdump $imagedir/${casename}_1.png
+for {set y 400} {$y > 300} {set y [expr $y-1]} { vmanipulator m -transform 400 $y }
+vdump $imagedir/${casename}_2.png
+vmanipulator m -stopTransform