1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0029084: Visualization, AIS_Manipulator - broken transformation is applied at Rotation angles near to Pi

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.
This commit is contained in:
kgv
2017-09-05 12:14:02 +03:00
committed by bugmaster
parent 3ba79772a0
commit 3ed88facdb
4 changed files with 123 additions and 89 deletions

View 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));
}
SetPosition (myStartPosition);
return;
}
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();
}
}

View 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: