1
0
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:
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();
}
}