Mon, 03/04/2024 - 21:33
Forums: 
Hello all, i am running
m_manipulator->Transform(thePoint.x(), thePoint.y(), m_view)to move and rotate an AIS_InteractiveObject.
I would like that when I hold the ctrl key that rotation or movements go in steps like +-15 degrees for rotation or or 5mm steps for translation.
I was expecting to find some Signals for the manipulator but there are non (at least I can't find them). There are also no signals for AIS_InteractiveObject
How can I solve this problem?
Thank you!
        
Wed, 03/06/2024 - 10:23
It should be possible implementing such logic at application side, but I guess it might require some efforts.
Would be nice if
AIS_Manipulatorwill support something like this on its own...Wed, 03/06/2024 - 10:49
Hello, you mean integration ability to specify determined steps for interactive actions?
Best regards, Dmitrii.
Fri, 03/08/2024 - 22:57
>>Would be nice if AIS_Manipulator will support something like this on its own...
100% agreed
>> Hello, you mean integration ability to specify determined steps for interactive actions?
yes.
like
public:
setTranslationSteps(double steps)
setRotationSteps(double steps)
slots:
onTranslationStep(double step)
onRotationStep(double step)
Fri, 09/20/2024 - 16:05
I also need a method to perform this.
Anyone has found a solution to implement it ?
Tue, 10/01/2024 - 01:45
I bring this up and hope there will be progress on this?
Wed, 10/02/2024 - 12:52
I implemented this to achieve the goal, it's an extension of the base AIS_Manipulator.
Hope you'll enjoy it.
Custom_AIS_Manipulator.h :
#pragma once #include "AIS_Manipulator.hxx" #include "gp_Ax2.hxx" #include "V3d_View.hxx" #include "gp.hxx" class Custom_AIS_Manipulator : public AIS_Manipulator { DEFINE_STANDARD_RTTI_INLINE(APGM_AIS_Manipulator, AIS_Manipulator) public: Custom_AIS_Manipulator(); Custom_AIS_Manipulator(const gp_Ax2& thePosition); Standard_Real TranslationSteps(); void SetTranslationSteps(Standard_Real value); Standard_Real RotationSteps(); void SetRotationSteps(Standard_Real value); Standard_Real ScalingSteps(); void SetScalingSteps(Standard_Real value); Standard_Boolean CustomProcessDragging(const Handle(AIS_InteractiveContext)&, const Handle(V3d_View)& theView, const Handle(SelectMgr_EntityOwner)&, const Graphic3d_Vec2i& theDragFrom, const Graphic3d_Vec2i& theDragTo, const AIS_DragAction theAction); gp_Trsf CustomTransform(const Standard_Integer thePX, const Standard_Integer thePY, const Handle(V3d_View)& theView); Standard_Boolean CustomObjectTransformation(const Standard_Integer theMaxX, const Standard_Integer theMaxY, const Handle(V3d_View)& theView, gp_Trsf& theTrsf); private: Standard_Real myTranslationSteps = 0; Standard_Real myRotationSteps = 0; Standard_Real myScalingSteps = 0; };Custom_AIS_Manipulator.cpp
#include "Custom_AIS_Manipulator.h" #include <Extrema_ExtElC.hxx> #include <IntAna_IntConicQuad.hxx> #include <gce_MakeDir.hxx> //! 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"); } Custom_AIS_Manipulator::Custom_AIS_Manipulator() : AIS_Manipulator() { } Custom_AIS_Manipulator::Custom_AIS_Manipulator(const gp_Ax2& thePosition) : AIS_Manipulator(thePosition) { } Standard_Real Custom_AIS_Manipulator::TranslationSteps() { return this->myTranslationSteps; } void Custom_AIS_Manipulator::SetTranslationSteps(Standard_Real value) { if (value < 0) value = 0; this->myTranslationSteps = value; } Standard_Real Custom_AIS_Manipulator::RotationSteps() { return this->myRotationSteps; } void Custom_AIS_Manipulator::SetRotationSteps(Standard_Real value) { if (value < 0) value = 0; else if (value > M_PI) value = M_PI; this->myRotationSteps = value; } Standard_Real Custom_AIS_Manipulator::ScalingSteps() { return this->myScalingSteps; } void Custom_AIS_Manipulator::SetScalingSteps(Standard_Real value) { if (value < 0) value = 0; this->myScalingSteps = value; } Standard_Boolean Custom_AIS_Manipulator::CustomProcessDragging(const Handle(AIS_InteractiveContext)&, const Handle(V3d_View)& theView, const Handle(SelectMgr_EntityOwner)&, const Graphic3d_Vec2i& theDragFrom, const Graphic3d_Vec2i& theDragTo, const AIS_DragAction theAction) { switch (theAction) { case AIS_DragAction_Start: { if (HasActiveMode()) { StartTransform(theDragFrom.x(), theDragFrom.y(), theView); return Standard_True; } break; } case AIS_DragAction_Confirmed: { return Standard_True; } case AIS_DragAction_Update: { // ADDED TO ENSURE TRANSFORMATIONS STEPS CustomTransform(theDragTo.x(), theDragTo.y(), theView); // REMOVED TO ENSURE TRANSFORMATIONS STEPS //Transform(theDragTo.x(), theDragTo.y(), theView); return Standard_True; } case AIS_DragAction_Abort: { StopTransform(false); return Standard_True; } case AIS_DragAction_Stop: break; } return Standard_False; } gp_Trsf Custom_AIS_Manipulator::CustomTransform(const Standard_Integer thePX, const Standard_Integer thePY, const Handle(V3d_View)& theView) { gp_Trsf aTrsf; if (CustomObjectTransformation(thePX, thePY, theView, aTrsf)) { Transform(aTrsf); } return aTrsf; } Standard_Boolean Custom_AIS_Manipulator::CustomObjectTransformation(const Standard_Integer theMaxX, const Standard_Integer theMaxY, const Handle(V3d_View)& theView, gp_Trsf& theTrsf) { // Initialize start reference data if (!myHasStartedTransformation) { myStartTrsfs.Clear(); Handle(AIS_ManipulatorObjectSequence) anObjects = Objects(); for (AIS_ManipulatorObjectSequence::Iterator anObjIter(*anObjects); anObjIter.More(); anObjIter.Next()) { myStartTrsfs.Append(anObjIter.Value()->LocalTransformation()); } myStartPosition = myPosition; } // Get 3d point with projection vector Graphic3d_Vec3d anInputPoint, aProj; theView->ConvertWithProj(theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z()); 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: case AIS_MM_Scaling: { 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 return Standard_False; } Extrema_POnCurv anExPnts[2]; anExtrema.Points(1, anExPnts[0], anExPnts[1]); const gp_Pnt aNewPosition = anExPnts[1].Value(); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; return Standard_True; } else if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } gp_Trsf aNewTrsf; if (myCurrentMode == AIS_MM_Translation) { // CHANGED TO ENSURE TRANSLATION STEPS gp_Vec translationVector(myStartPick, aNewPosition); if (this->myTranslationSteps > 0) { Standard_Real distance = aNewPosition.Distance(myStartPick); Standard_Real modDiv = fmod(distance, this->myTranslationSteps); translationVector.Multiply((distance - modDiv) / distance); if (translationVector.Magnitude() < Precision::Confusion()) return Standard_False; } aNewTrsf.SetTranslation(translationVector); // END // REMOVED TO ENSURE TRANSLATION STEPS //aNewTrsf.SetTranslation(gp_Vec(myStartPick, aNewPosition)); // END theTrsf *= aNewTrsf; } else if (myCurrentMode == AIS_MM_Scaling) { if (aNewPosition.Distance(myStartPosition.Location()) < Precision::Confusion()) { return Standard_False; } Standard_Real aCoeff = myStartPosition.Location().Distance(aNewPosition) / myStartPosition.Location().Distance(myStartPick); // CHANGED TO ENSURE SCALING STEPS if (this->myScalingSteps > 0) { Standard_Real modDiv = fmod(aCoeff, this->myScalingSteps); aCoeff -= modDiv; } // END aNewTrsf.SetScale(myPosition.Location(), aCoeff); theTrsf = aNewTrsf; } return Standard_True; } case AIS_MM_Rotation: { 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.IsParallel() || aIntersector.NbPoints() < 1) { return Standard_False; } const gp_Pnt aNewPosition = aIntersector.Point(1); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; gp_Dir aStartAxis = gce_MakeDir(aPosLoc, myStartPick); myPrevState = aStartAxis.AngleWithRef(gce_MakeDir(aPosLoc, aNewPosition), aCurrAxis.Direction()); return Standard_True; } if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } gp_Dir aStartAxis = aPosLoc.IsEqual(myStartPick, Precision::Confusion()) ? getAx1FromAx2Dir(myStartPosition, (myCurrentIndex + 1) % 3).Direction() : gce_MakeDir(aPosLoc, myStartPick); 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_Real aSign = myPrevState > 0 ? -1.0 : 1.0; anAngle = aSign * (M_PI * 2 - anAngle); } if (Abs(anAngle) < Precision::Confusion()) { return Standard_False; } // ADDED TO ENSURE ROTATION STEPS if (this->myRotationSteps > 0) { Standard_Real modDiv = fmod(anAngle, this->myRotationSteps); anAngle -= modDiv; } // END gp_Trsf aNewTrsf; aNewTrsf.SetRotation(aCurrAxis, anAngle); theTrsf *= aNewTrsf; myPrevState = anAngle; return Standard_True; } case AIS_MM_TranslationPlane: { 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) { return Standard_False; } const gp_Pnt aNewPosition = aIntersector.Point(1); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; return Standard_True; } if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } // ADDED TO ENSURE TRANSLATION STEPS gp_Vec translationVector(myStartPick, aNewPosition); if (this->myTranslationSteps > 0) { Standard_Real distance = aNewPosition.Distance(myStartPick); Standard_Real modDiv = fmod(distance, this->myTranslationSteps); translationVector.Multiply((distance - modDiv) / distance); if (translationVector.Magnitude() < Precision::Confusion()) return Standard_False; } gp_Trsf aNewTrsf; aNewTrsf.SetTranslation(translationVector); // END // REMOVED TO ENSURE TRANSLATION STEPS //gp_Trsf aNewTrsf; //aNewTrsf.SetTranslation(gp_Vec(myStartPick, aNewPosition)); // END theTrsf *= aNewTrsf; return Standard_True; } case AIS_MM_None: { return Standard_False; } } return Standard_False; }Usage :