mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-14 13:30:48 +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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user