AIS_Manipulator class has been created to provide interactive services for manipulating with mouse local transformations of other interactive objects.
The class features three kinds of transformation modes for attached objects:
- translation of through axis
- scaling within axis
- rotation around axis
For more details please have a look at description of the class in reference manual or in header file.
The patch includes DRAW test workbench for evaluating the AIS_Manipulator features.
Clang warning (override)
--- /dev/null
+// Created on: 2015-12-23
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_Manipulator.hxx>
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_ManipulatorOwner.hxx>
+#include <gce_MakeDir.hxx>
+#include <GeomAPI_ExtremaCurveCurve.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Transformation.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <Select3D_SensitiveCircle.hxx>
+#include <Select3D_SensitivePoint.hxx>
+#include <Select3D_SensitiveSegment.hxx>
+#include <Select3D_SensitiveTriangulation.hxx>
+#include <SelectMgr_SequenceOfOwner.hxx>
+#include <StdPrs_ToolDisk.hxx>
+#include <StdPrs_ToolCylinder.hxx>
+#include <StdPrs_ToolSphere.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <V3d_View.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (AIS_Manipulator, AIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject)
+
+IMPLEMENT_HSEQUENCE(AIS_ManipulatorObjectSequence)
+
+//=======================================================================
+//function : init
+//purpose :
+//=======================================================================
+void AIS_Manipulator::init()
+{
+ // Create axis in the default coordinate system. The custom position is applied in local transformation.
+ myAxes[0] = Axis (gp::OX(), Quantity_NOC_RED);
+ myAxes[1] = Axis (gp::OY(), Quantity_NOC_GREEN);
+ myAxes[2] = Axis (gp::OZ(), Quantity_NOC_BLUE1);
+
+ Graphic3d_MaterialAspect aShadingMaterial;
+ aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
+
+ myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+ myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
+ myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE);
+ myDrawer->ShadingAspect()->SetMaterial (aShadingMaterial);
+
+ Graphic3d_MaterialAspect aHilightMaterial;
+ aHilightMaterial.SetColor (Quantity_NOC_AZURE);
+ aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
+ aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
+ aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
+ aHilightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
+
+ myHighlightAspect = new Prs3d_ShadingAspect();
+ myHighlightAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
+ myHighlightAspect->SetMaterial (aHilightMaterial);
+
+ SetSize (100);
+ SetZLayer (Graphic3d_ZLayerId_Topmost);
+}
+
+//=======================================================================
+//function : getHighlightPresentation
+//purpose :
+//=======================================================================
+Handle(Prs3d_Presentation) AIS_Manipulator::getHighlightPresentation (const Handle(SelectMgr_EntityOwner)& theOwner) const
+{
+ Handle(Prs3d_Presentation) aDummyPrs;
+ Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
+ if (anOwner.IsNull())
+ {
+ return aDummyPrs;
+ }
+
+ switch (anOwner->Mode())
+ {
+ case AIS_MM_Translation: return myAxes[anOwner->Index()].TranslatorHighlightPrs();
+ case AIS_MM_Rotation : return myAxes[anOwner->Index()].RotatorHighlightPrs();
+ case AIS_MM_Scaling : return myAxes[anOwner->Index()].ScalerHighlightPrs();
+ case AIS_MM_None : break;
+ }
+
+ return aDummyPrs;
+}
+
+//=======================================================================
+//function : getGroup
+//purpose :
+//=======================================================================
+Handle(Graphic3d_Group) AIS_Manipulator::getGroup (const Standard_Integer theIndex, const AIS_ManipulatorMode theMode) const
+{
+ Handle(Graphic3d_Group) aDummyGroup;
+
+ if (theIndex < 0 || theIndex > 2)
+ {
+ return aDummyGroup;
+ }
+
+ switch (theMode)
+ {
+ case AIS_MM_Translation: return myAxes[theIndex].TranslatorGroup();
+ case AIS_MM_Rotation : return myAxes[theIndex].RotatorGroup();
+ case AIS_MM_Scaling : return myAxes[theIndex].ScalerGroup();
+ case AIS_MM_None : break;
+ }
+
+ return aDummyGroup;
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_Manipulator::AIS_Manipulator()
+: myPosition (gp::XOY()),
+ myCurrentIndex (-1),
+ myCurrentMode (AIS_MM_None),
+ myIsActivationOnDetection (Standard_False),
+ myIsZoomPersistentMode (Standard_True),
+ myHasStartedTransformation (Standard_False),
+ myStartPosition (gp::XOY()),
+ myStartPick (0.0, 0.0, 0.0),
+ myPrevState (0.0)
+{
+ SetInfiniteState();
+ SetMutable (Standard_True);
+ SetDisplayMode (AIS_Shaded);
+ init();
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_Manipulator::AIS_Manipulator (const gp_Ax2& thePosition)
+: myPosition (thePosition),
+ myCurrentIndex (-1),
+ myCurrentMode (AIS_MM_None),
+ myIsActivationOnDetection (Standard_False),
+ myIsZoomPersistentMode (Standard_True),
+ myHasStartedTransformation (Standard_False),
+ myStartPosition (gp::XOY()),
+ myStartPick (0.0, 0.0, 0.0),
+ myPrevState (0.0)
+{
+ SetInfiniteState();
+ SetMutable (Standard_True);
+ SetDisplayMode (AIS_Shaded);
+ init();
+}
+
+//=======================================================================
+//function : SetPart
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetPart (const Standard_Integer theAxisIndex, const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled)
+{
+ Standard_ProgramError_Raise_if (theAxisIndex < 0 || theAxisIndex > 2, "AIS_Manipulator::SetMode(): axis index should be between 0 and 2");
+ switch (theMode)
+ {
+ case AIS_MM_Translation:
+ myAxes[theAxisIndex].SetTranslation (theIsEnabled);
+ break;
+
+ case AIS_MM_Rotation:
+ myAxes[theAxisIndex].SetRotation (theIsEnabled);
+ break;
+
+ case AIS_MM_Scaling:
+ myAxes[theAxisIndex].SetScaling (theIsEnabled);
+ break;
+
+ case AIS_MM_None:
+ break;
+ }
+}
+
+//=======================================================================
+//function : EnableMode
+//purpose :
+//=======================================================================
+void AIS_Manipulator::EnableMode (const AIS_ManipulatorMode theMode)
+{
+ if (!IsAttached())
+ {
+ return;
+ }
+
+ const Handle(AIS_InteractiveContext)& aContext = GetContext();
+ if (aContext.IsNull())
+ {
+ return;
+ }
+
+ aContext->Activate (this, theMode);
+}
+
+//=======================================================================
+//function : attachToBox
+//purpose :
+//=======================================================================
+void AIS_Manipulator::attachToBox (const Bnd_Box& theBox)
+{
+ if (theBox.IsVoid())
+ {
+ return;
+ }
+
+ Standard_Real anXmin = 0.0, anYmin = 0.0, aZmin = 0.0, anXmax = 0.0, anYmax = 0.0, aZmax = 0.0;
+ theBox.Get (anXmin, anYmin, aZmin, anXmax, anYmax, aZmax);
+
+ gp_Ax2 aPosition = gp::XOY();
+ aPosition.SetLocation (gp_Pnt ((anXmin + anXmax) * 0.5, (anYmin + anYmax) * 0.5, (aZmin + aZmax) * 0.5));
+ SetPosition (aPosition);
+}
+
+//=======================================================================
+//function : adjustSize
+//purpose :
+//=======================================================================
+void AIS_Manipulator::adjustSize (const Bnd_Box& theBox)
+{
+ Standard_Real aXmin = 0., aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.0;
+ theBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ Standard_Real aXSize = aXmax - aXmin;
+ Standard_Real aYSize = aYmax - aYmin;
+ Standard_Real aZSize = aZmax - aZmin;
+
+ SetSize ((Standard_ShortReal) (Max (aXSize, Max (aYSize, aZSize)) * 0.5));
+}
+
+//=======================================================================
+//function : Attach
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Attach (const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions)
+{
+ if (theObject->IsKind (STANDARD_TYPE(AIS_Manipulator)))
+ {
+ return;
+ }
+
+ Handle(AIS_ManipulatorObjectSequence) aSeq = new AIS_ManipulatorObjectSequence();
+ aSeq->Append (theObject);
+ Attach (aSeq, theOptions);
+}
+
+//=======================================================================
+//function : Attach
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Attach (const Handle(AIS_ManipulatorObjectSequence)& theObjects, const OptionsForAttach& theOptions)
+{
+ if (theObjects->Size() < 1)
+ {
+ return;
+ }
+
+ SetOwner (theObjects);
+ Bnd_Box aBox;
+ const Handle(AIS_InteractiveObject)& aCurObject = theObjects->Value (theObjects->Lower());
+ aCurObject->BoundingBox (aBox);
+
+ if (theOptions.AdjustPosition)
+ {
+ attachToBox (aBox);
+ }
+
+ if (theOptions.AdjustSize)
+ {
+ adjustSize (aBox);
+ }
+
+ const Handle(AIS_InteractiveContext)& aContext = Object()->GetContext();
+ if (!aContext.IsNull())
+ {
+ if (!aContext->IsDisplayed (this))
+ {
+ aContext->Display (this, Standard_False);
+ }
+ else
+ {
+ aContext->Update (this, Standard_False);
+ aContext->RecomputeSelectionOnly (this);
+ }
+
+ aContext->Load (this);
+ aContext->CurrentViewer()->RedrawImmediate();
+ }
+
+ if (theOptions.EnableModes)
+ {
+ EnableMode (AIS_MM_Rotation);
+ EnableMode (AIS_MM_Translation);
+ EnableMode (AIS_MM_Scaling);
+ }
+}
+
+//=======================================================================
+//function : Detach
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Detach()
+{
+ DeactivateCurrentMode();
+
+ if (!IsAttached())
+ {
+ return;
+ }
+
+ Handle(AIS_InteractiveObject) anObject = Object();
+ const Handle(AIS_InteractiveContext)& aContext = anObject->GetContext();
+ if (!aContext.IsNull())
+ {
+ aContext->Remove (this, Standard_False);
+ }
+
+ SetOwner (NULL);
+}
+
+//=======================================================================
+//function : Objects
+//purpose :
+//=======================================================================
+Handle(AIS_ManipulatorObjectSequence) AIS_Manipulator::Objects() const
+{
+ return Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
+}
+
+//=======================================================================
+//function : Object
+//purpose :
+//=======================================================================
+Handle(AIS_InteractiveObject) AIS_Manipulator::Object (const Standard_Integer theIndex) const
+{
+ Handle(AIS_ManipulatorObjectSequence) anOwner = Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
+
+ Standard_ProgramError_Raise_if (theIndex < anOwner->Lower() || theIndex > anOwner->Upper(), "AIS_Manipulator::Object(): wrong index value");
+
+ if (anOwner.IsNull() || anOwner->IsEmpty())
+ {
+ return NULL;
+ }
+
+ return anOwner->Value (theIndex);
+}
+
+//=======================================================================
+//function : Object
+//purpose :
+//=======================================================================
+Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const
+{
+ return Object (1);
+}
+
+//=======================================================================
+//function : ObjectTransformation
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer theMaxX, const Standard_Integer theMaxY,
+ const Handle(V3d_View)& theView, gp_Trsf& theTrsf)
+{
+ // Initialize start reference data
+ if (!myHasStartedTransformation)
+ {
+ Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
+ myStartTrsfs.Clear();
+ for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
+ {
+ myStartTrsfs.Append (anObjects->Value (anIt)->LocalTransformation());
+ }
+ myStartPosition = myPosition;
+ }
+
+ // Get 3d point with projection vector
+ Graphic3d_Vec3d anInputPoint;
+ Graphic3d_Vec3d 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();
+
+ switch (myCurrentMode)
+ {
+ case AIS_MM_Translation:
+ {
+ gp_Lin aLine (myStartPick, myAxes[myCurrentIndex].Position().Direction());
+ Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
+ Handle(Geom_Curve) aCurve = new Geom_Line (aLine);
+ GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
+ gp_Pnt aP1, aP2;
+ anExtrema.NearestPoints (aP1, aP2);
+ aNewPosition = aP2;
+
+ if (!myHasStartedTransformation)
+ {
+ myStartPick = aNewPosition;
+ myHasStartedTransformation = Standard_True;
+ return Standard_True;
+ }
+
+ if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
+ {
+ return Standard_False;
+ }
+
+ gp_Trsf aNewTrsf;
+ aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
+ theTrsf *= aNewTrsf;
+ break;
+ }
+ case AIS_MM_Rotation:
+ {
+ Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
+ Handle(Geom_Surface) aSurface = new Geom_Plane (myPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
+ GeomAPI_IntCS aIntersector (anInputCurve, aSurface);
+ if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1)
+ {
+ return Standard_False;
+ }
+
+ 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());
+ return Standard_True;
+ }
+
+ if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
+ {
+ 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 aCurrentAxis = gce_MakeDir (myPosition.Location(), aNewPosition);
+ Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, myAxes[myCurrentIndex].Position().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;
+ anAngle = aSign * (M_PI * 2 - anAngle);
+ }
+
+ if (Abs (anAngle) < Precision::Confusion())
+ {
+ return Standard_False;
+ }
+
+ gp_Trsf aNewTrsf;
+ aNewTrsf.SetRotation (myAxes[myCurrentIndex].Position(), anAngle);
+ theTrsf *= aNewTrsf;
+ myPrevState = anAngle;
+ break;
+ }
+ case AIS_MM_Scaling:
+ {
+ gp_Lin aLine (myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
+ Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
+ Handle(Geom_Curve) aCurve = new Geom_Line (aLine);
+ GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
+ gp_Pnt aTmp;
+ anExtrema.NearestPoints (aTmp, aNewPosition);
+
+ if (!myHasStartedTransformation)
+ {
+ myStartPick = aNewPosition;
+ myHasStartedTransformation = Standard_True;
+ return Standard_True;
+ }
+
+ if (aNewPosition.Distance (myStartPick) < Precision::Confusion()
+ || aNewPosition.Distance (myStartPosition.Location()) < Precision::Confusion())
+ {
+ return Standard_False;
+ }
+
+ Standard_Real aCoeff = myStartPosition.Location().Distance (aNewPosition)
+ / myStartPosition.Location().Distance (myStartPick);
+ gp_Trsf aNewTrsf;
+ aNewTrsf.SetScale (myPosition.Location(), aCoeff);
+
+ theTrsf = aNewTrsf;
+ break;
+ }
+ case AIS_MM_None:
+ return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : StartTransform
+//purpose :
+//=======================================================================
+void AIS_Manipulator::StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView)
+{
+ if (myHasStartedTransformation)
+ {
+ return;
+ }
+
+ gp_Trsf aTrsf;
+ ObjectTransformation (theX, theY, theView, aTrsf);
+}
+
+//=======================================================================
+//function : StopTransform
+//purpose :
+//=======================================================================
+void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
+{
+ if (!IsAttached() || !myHasStartedTransformation)
+ {
+ return;
+ }
+
+ myHasStartedTransformation = Standard_False;
+
+ 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);
+ }
+}
+
+//=======================================================================
+//function : Transform
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
+{
+ if (!IsAttached() || !myHasStartedTransformation)
+ {
+ return;
+ }
+
+ Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
+
+ for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
+ {
+ anObjects->Value (anIt)->SetLocalTransformation (theTrsf * myStartTrsfs(anIt));
+ }
+
+ if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation)
+ || (myCurrentMode == AIS_MM_Rotation && myBehaviorOnTransform.FollowRotation))
+ {
+ gp_Pnt aPos = myStartPosition.Location().Transformed (theTrsf);
+ gp_Dir aVDir = myStartPosition.Direction().Transformed (theTrsf);
+ gp_Dir aXDir = myStartPosition.XDirection().Transformed (theTrsf);
+ SetPosition (gp_Ax2 (aPos, aVDir, aXDir));
+ }
+}
+
+//=======================================================================
+//function : Transform
+//purpose :
+//=======================================================================
+gp_Trsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
+ const Handle(V3d_View)& theView)
+{
+ gp_Trsf aTrsf;
+ if (ObjectTransformation (thePX, thePY, theView, aTrsf))
+ {
+ Transform (aTrsf);
+ }
+
+ return aTrsf;
+}
+
+//=======================================================================
+//function : SetPosition
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetPosition (const gp_Ax2& thePosition)
+{
+ if (!myPosition.Location().IsEqual (thePosition.Location(), Precision::Confusion())
+ || !myPosition.Direction().IsEqual (thePosition.Direction(), Precision::Angular())
+ || !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()));
+
+ updateTransformation();
+ }
+}
+
+//=======================================================================
+//function : updateTransformation
+//purpose : set local transformation to avoid graphics recomputation
+//=======================================================================
+void AIS_Manipulator::updateTransformation()
+{
+ gp_Trsf aTrsf;
+
+ if (!myIsZoomPersistentMode)
+ {
+ aTrsf.SetTransformation (myPosition, gp::XOY());
+ }
+ else
+ {
+ const gp_Dir& aVDir = myPosition.Direction();
+ const gp_Dir& aXDir = myPosition.XDirection();
+ aTrsf.SetTransformation (gp_Ax2 (gp::Origin(), aVDir, aXDir), gp::XOY());
+ }
+
+ AIS_InteractiveObject::SetLocalTransformation (aTrsf);
+
+ Handle(Geom_Transformation) aGeomTrsf = new Geom_Transformation (this->Transformation());
+
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ myAxes[anIt].Transform (aGeomTrsf);
+ }
+
+ if (myIsZoomPersistentMode)
+ {
+ if (!(GetTransformPersistenceMode () == Graphic3d_TMF_ZoomPers
+ && GetTransformPersistencePoint().IsEqual (myPosition.Location(), 0.)))
+ {
+ setTransformPersistence (Graphic3d_TMF_ZoomPers, myPosition.Location());
+ }
+ }
+}
+
+//=======================================================================
+//function : SetSize
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetSize (const Standard_ShortReal theSideLength)
+{
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ myAxes[anIt].SetSize (theSideLength);
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : SetGap
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetGap (const Standard_ShortReal theValue)
+{
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ myAxes[anIt].SetIndent (theValue);
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : DeactivateCurrentMode
+//purpose :
+//=======================================================================
+void AIS_Manipulator::DeactivateCurrentMode()
+{
+ if (!myIsActivationOnDetection)
+ {
+ Handle(Graphic3d_Group) aGroup = getGroup (myCurrentIndex, myCurrentMode);
+ if (aGroup.IsNull())
+ {
+ return;
+ }
+
+ Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
+ anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
+ anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
+ anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
+ anAspect->SetColor (myAxes[myCurrentIndex].Color());
+
+ aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
+ }
+
+ myCurrentIndex = -1;
+ myCurrentMode = AIS_MM_None;
+
+ if (myHasStartedTransformation)
+ {
+ myHasStartedTransformation = Standard_False;
+ }
+}
+
+//=======================================================================
+//function : SetZoomPersistence
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
+{
+ if (myIsZoomPersistentMode != theToEnable)
+ {
+ SetToUpdate();
+ }
+
+ myIsZoomPersistentMode = theToEnable;
+
+ if (!theToEnable)
+ {
+ setTransformPersistence (Graphic3d_TMF_None, gp::Origin());
+ }
+
+ updateTransformation();
+}
+
+//=======================================================================
+//function : SetTransformPersistence
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint)
+{
+ Standard_ASSERT_RETURN (!myIsZoomPersistentMode,
+ "AIS_Manipulator::SetTransformPersistence: "
+ "Custom settings are not supported by this class in ZoomPersistence mode",);
+
+ setTransformPersistence (theFlag, thePoint);
+}
+
+//=======================================================================
+//function : setTransformPersistence
+//purpose :
+//=======================================================================
+void AIS_Manipulator::setTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint)
+{
+ AIS_InteractiveObject::SetTransformPersistence (theFlag, thePoint);
+
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ myAxes[anIt].SetTransformPersistence (theFlag, thePoint);
+ }
+}
+
+//=======================================================================
+//function : SetLocalTransformation
+//purpose :
+//=======================================================================
+void AIS_Manipulator::SetLocalTransformation (const gp_Trsf& /*theTransformation*/)
+{
+ Standard_ASSERT_INVOKE (
+ "AIS_Manipulator::SetLocalTransformation: "
+ "Custom transformation is not supported by this class");
+}
+
+//=======================================================================
+//function : Compute
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ if (theMode != AIS_Shaded)
+ {
+ return;
+ }
+
+ thePrs->SetInfiniteState (Standard_True);
+ thePrs->SetMutable (Standard_True);
+ Handle(Graphic3d_Group) aGroup;
+ Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
+ anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
+ anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
+ anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
+
+ // Display center
+ myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
+ aGroup = Prs3d_Root::NewGroup (thePrs);
+ aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+ aGroup->AddPrimitiveArray (myCenter.Array());
+
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ // Display axes
+ aGroup = Prs3d_Root::NewGroup (thePrs);
+ anAspect->SetColor (myAxes[anIt].Color());
+ aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
+ myAxes[anIt].Compute (thePrsMgr, thePrs, anAspect);
+ myAxes[anIt].SetTransformPersistence (GetTransformPersistenceMode(),
+ GetTransformPersistencePoint());
+ }
+
+ updateTransformation();
+}
+
+//=======================================================================
+//function : HilightSelected
+//purpose :
+//=======================================================================
+void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
+ const SelectMgr_SequenceOfOwner& theSeq)
+{
+ if (theSeq.IsEmpty())
+ {
+ return;
+ }
+
+ if (myIsActivationOnDetection)
+ {
+ return;
+ }
+
+ if (!theSeq (1)->IsKind (STANDARD_TYPE (AIS_ManipulatorOwner)))
+ {
+ thePM->Color (this, GetContext()->HilightColor(), 0);
+ return;
+ }
+
+ Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theSeq (1));
+ myHighlightAspect->Aspect()->SetInteriorColor (GetContext()->HilightColor());
+ Handle(Graphic3d_Group) aGroup = getGroup (anOwner->Index(), anOwner->Mode());
+ if (aGroup.IsNull())
+ {
+ return;
+ }
+
+ aGroup->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
+
+ myCurrentIndex = anOwner->Index();
+ myCurrentMode = anOwner->Mode();
+}
+
+//=======================================================================
+//function : ClearSelected
+//purpose :
+//=======================================================================
+void AIS_Manipulator::ClearSelected()
+{
+ DeactivateCurrentMode();
+}
+
+//=======================================================================
+//function : HilightOwnerWithColor
+//purpose :
+//=======================================================================
+void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, const Quantity_NameOfColor theColor, const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+ Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
+ Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation (anOwner);
+ if (aPresentation.IsNull())
+ {
+ return;
+ }
+ aPresentation->Highlight (Aspect_TOHM_COLOR, theColor);
+ aPresentation->SetShadingAspect (myHighlightAspect);
+ aPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
+ thePM->AddToImmediateList (aPresentation);
+
+ if (myIsActivationOnDetection)
+ {
+ if (HasActiveMode())
+ {
+ DeactivateCurrentMode();
+ }
+
+ myCurrentIndex = anOwner->Index();
+ myCurrentMode = anOwner->Mode();
+ }
+}
+
+//=======================================================================
+//function : ComputeSelection
+//purpose :
+//=======================================================================
+void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Standard_Integer theMode)
+{
+ //Check mode
+ AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
+ if (aMode == AIS_MM_None)
+ {
+ return;
+ }
+ Handle(SelectMgr_EntityOwner) anOwner;
+ if (aMode == AIS_MM_None)
+ {
+ anOwner = new SelectMgr_EntityOwner (this, 5);
+ }
+ Handle(Select3D_SensitiveTriangulation) aTri;
+ if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
+ {
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ const Axis& anAxis = myAxes[anIt];
+ if (aMode != AIS_MM_None)
+ {
+ anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
+ }
+ // define sensitivity by line
+ Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
+ aLine->SetSensitivityFactor (15);
+ theSelection->Add (aLine);
+ // enlarge sensitivity by triangulation
+ aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorCylinder().Triangulation(), TopLoc_Location(), Standard_True);
+ theSelection->Add (aTri);
+ aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrow().Triangulation(), TopLoc_Location(), Standard_True);
+ theSelection->Add (aTri);
+ aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrowBottom().Triangulation(), TopLoc_Location(), Standard_True);
+ theSelection->Add (aTri);
+ }
+ }
+
+ if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
+ {
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ const Axis& anAxis = myAxes[anIt];
+ if (aMode != AIS_MM_None)
+ {
+ anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
+ }
+ // define sensitivity by circle
+ Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
+ Handle(Select3D_SensitiveCircle) aCircle = new Select3D_SensitiveCircle (anOwner, aGeomCircle, Standard_False, anAxis.FacettesNumber());
+ aCircle->SetSensitivityFactor (15);
+ theSelection->Add (aCircle);
+ // enlarge sensitivity by triangulation
+ aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), TopLoc_Location(), Standard_True);
+ theSelection->Add (aTri);
+ }
+ }
+
+ if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
+ {
+ for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+ {
+ if (aMode != AIS_MM_None)
+ {
+ anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
+ }
+ // define sensitivity by point
+ Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
+ aPnt->SetSensitivityFactor (15);
+ theSelection->Add (aPnt);
+ // enlarge sensitivity by triangulation
+ aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
+ theSelection->Add (aTri);
+ }
+ }
+}
+
+//=======================================================================
+//class : Cylinder
+//function : Init
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Cylinder::Init (const Standard_ShortReal theBotRad, const Standard_ShortReal theTopRad,
+ const Standard_ShortReal theHeight,
+ const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb,
+ const gp_Ax1& thePosition)
+{
+ myPosition = thePosition;
+ myBottomRad = theBotRad;
+ myTopRad = theTopRad;
+ myHeight = theHeight;
+
+ StdPrs_ToolCylinder aTool (myBottomRad, myTopRad, myHeight, theSlicesNb, theStacksNb);
+ gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
+ gp_Trsf aTrsf;
+ aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+ aTool.FillArray (myArray, myTriangulation, aTrsf);
+}
+
+//=======================================================================
+//class : Disk
+//function : Init
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
+ const Standard_ShortReal theOuterRadius,
+ const gp_Ax1& thePosition,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb)
+{
+ myPosition = thePosition;
+ myInnerRad = theInnerRadius;
+ myOuterRad = theOuterRadius;
+
+ StdPrs_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
+ gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
+ gp_Trsf aTrsf;
+ aTrsf.SetTransformation (aSystem, gp_Ax3());
+ aTool.FillArray (myArray, myTriangulation, aTrsf);
+}
+
+//=======================================================================
+//class : Sphere
+//function : Init
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
+ const gp_Pnt& thePosition,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb)
+{
+ myPosition = thePosition;
+ myRadius = theRadius;
+
+ StdPrs_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
+ aTool.FillArray (myArray, myTriangulation, aTrsf);
+}
+
+//=======================================================================
+//class : Cube
+//function : Init
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
+{
+ myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
+
+ Poly_Array1OfTriangle aPolyTriangles (1, 12);
+ TColgp_Array1OfPnt aPoints (1, 36);
+ NCollection_Array1<gp_Dir> aNormals (1, 12);
+ myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
+
+ gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
+ gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
+ gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
+ gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
+ gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
+ gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
+ + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
+ gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
+ gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
+ gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
+
+ gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
+ gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
+
+ // Bottom
+ addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
+ addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
+
+ // Front
+ addTriangle (2, aV3, aV4, aV5, aFront);
+ addTriangle (3, aV3, aV5, aTopRight, aFront);
+
+ // Back
+ addTriangle (4, aBottomLeft, aV2, aV7, -aFront);
+ addTriangle (5, aBottomLeft, aV7, aV6, -aFront);
+
+ // aTop
+ addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
+ addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
+
+ //Left
+ addTriangle (8, aV6, aV5, aV4, -aRight);
+ addTriangle (9, aBottomLeft, aV6, aV4, -aRight);
+
+ // Right
+ addTriangle (10, aV3, aTopRight, aV7, aRight);
+ addTriangle (11, aV3, aV7, aV2, aRight);
+}
+
+//=======================================================================
+//class : Cube
+//function : addTriangle
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
+ const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
+ const gp_Dir& theNormal)
+{
+ myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 1, theP1);
+ myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 2, theP2);
+ myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 3, theP3);
+
+ myTriangulation->ChangeTriangles().SetValue (theIndex + 1, Poly_Triangle (theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3));
+ myArray->AddVertex (theP1, theNormal);
+ myArray->AddVertex (theP2, theNormal);
+ myArray->AddVertex (theP3, theNormal);
+}
+
+//=======================================================================
+//class : Axis
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
+ const Quantity_Color& theColor,
+ const Standard_ShortReal theLength)
+: myReferenceAxis (theAxis),
+ myPosition (theAxis),
+ myColor (theColor),
+ myHasTranslation (Standard_True),
+ myLength (theLength),
+ myAxisRadius (0.5f),
+ myHasScaling (Standard_True),
+ myBoxSize (2.0f),
+ myHasRotation (Standard_True),
+ myInnerRadius (myLength + myBoxSize),
+ myDiskThickness (myBoxSize * 0.5f),
+ myIndent (0.2f),
+ myFacettesNumber (20),
+ myCircleRadius (myLength + myBoxSize + myBoxSize * 0.5f * 0.5f)
+{
+ //
+}
+
+//=======================================================================
+//class : Axis
+//function : Compute
+//purpose :
+//=======================================================================
+void AIS_Manipulator::Axis::Compute (const Handle_PrsMgr_PresentationManager3d& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Handle(Prs3d_ShadingAspect)& theAspect)
+{
+ Handle(Graphic3d_Group) aGroup;
+
+ if (myHasTranslation)
+ {
+ const Standard_ShortReal anArrowLength = 0.25f * myLength;
+ const Standard_ShortReal aCylinderLength = myLength - anArrowLength;
+
+ myCylinder.Init (myAxisRadius, myAxisRadius, aCylinderLength, myFacettesNumber, 2, gp_Ax1 (gp::Origin(), myReferenceAxis.Direction()));
+
+ gp_Pnt anArrowBottom (0.0, 0.0, 0.0);
+ anArrowBottom.Translate (myReferenceAxis.Direction().XYZ() * aCylinderLength);
+
+ myArrow.Init (myAxisRadius * 1.5f, 0.0f, anArrowLength, myFacettesNumber, 2, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()));
+ myArrowBottom.Init (myAxisRadius, myAxisRadius * 1.5f, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()), myFacettesNumber);
+ myArrowTipPos = anArrowBottom;
+
+ myTranslatorGroup = Prs3d_Root::NewGroup (thePrs);
+ myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
+ myTranslatorGroup->AddPrimitiveArray (myCylinder.Array());
+ myTranslatorGroup->AddPrimitiveArray (myArrow.Array());
+ myTranslatorGroup->AddPrimitiveArray (myArrowBottom.Array());
+
+ if (myHighlightTranslator.IsNull())
+ {
+ myHighlightTranslator = new Prs3d_Presentation (thePrsMgr->StructureManager());
+ }
+
+ myHighlightTranslator->Clear();
+ aGroup = Prs3d_Root::CurrentGroup (myHighlightTranslator);
+ aGroup->AddPrimitiveArray (myCylinder.Array());
+ aGroup->AddPrimitiveArray (myArrow.Array());
+ aGroup->AddPrimitiveArray (myArrowBottom.Array());
+ }
+
+ if (myHasScaling)
+ {
+ myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
+ myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
+
+ myScalerGroup = Prs3d_Root::NewGroup (thePrs);
+ myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
+ myScalerGroup->AddPrimitiveArray (myCube.Array());
+
+ if (myHighlightScaler.IsNull())
+ {
+ myHighlightScaler = new Prs3d_Presentation (thePrsMgr->StructureManager());
+ }
+
+ myHighlightScaler->Clear();
+ aGroup = Prs3d_Root::CurrentGroup (myHighlightScaler);
+ aGroup->AddPrimitiveArray (myCube.Array());
+ }
+
+ if (myHasRotation)
+ {
+ myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
+ myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
+ myRotatorGroup = Prs3d_Root::NewGroup (thePrs);
+ myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
+ myRotatorGroup->AddPrimitiveArray (myCircle.Array());
+
+ if (myHighlightRotator.IsNull())
+ {
+ myHighlightRotator = new Prs3d_Presentation (thePrsMgr->StructureManager());
+ }
+
+ myHighlightRotator->Clear();
+ aGroup = Prs3d_Root::CurrentGroup (myHighlightRotator);
+ Prs3d_Root::CurrentGroup (myHighlightRotator)->AddPrimitiveArray (myCircle.Array());
+ }
+}
--- /dev/null
+// Created on: 2015-12-23
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_Manipulator_HeaderFile
+#define _AIS_Manipulator_HeaderFile
+
+#include <AIS_InteractiveObject.hxx>
+#include <AIS_ManipulatorMode.hxx>
+#include <gp.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Pnt.hxx>
+#include <Graphic3d_ArrayOfQuadrangles.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_Group.hxx>
+#include <NCollection_HSequence.hxx>
+#include <Poly_Triangulation.hxx>
+#include <V3d_View.hxx>
+#include <Standard_Version.hxx>
+#include <Standard_DefineHandle.hxx>
+NCOLLECTION_HSEQUENCE(AIS_ManipulatorObjectSequence, Handle(AIS_InteractiveObject));
+
+DEFINE_STANDARD_HANDLE (AIS_Manipulator, AIS_InteractiveObject)
+
+//! Interactive object class to manipulate local transformation of another interactive
+//! object or a group of objects via mouse.
+//! It manages three types of manipulations in 3D space:
+//! - translation through axis
+//! - scaling within axis
+//! - rotation around axis
+//! To enable one of this modes, selection mode (from 1 to 3) is to be activated.
+//! There are three orthogonal transformation axes defined by position property of
+//! the manipulator. Particular transformation mode can be disabled for each
+//! of the axes or all of them. Furthermore each of the axes can be hidden or
+//! made visible.
+//! The following steps demonstrate how to attach, configure and use manipulator
+//! for an interactive object:
+//! Step 1. Create manipulator object and adjust it appearance:
+//! @code
+//! Handle(AIS_Manipulator) aManipulator = new AIS_Manipulator();
+//! aManipulator->SetPart (0, AIS_Manipulator::Scaling, Standard_False);
+//! aManipulator->SetPart (1, AIS_Manipulator::Rotation, Standard_False);
+//! // Attach manipulator to already displayed object and manage manipulation modes
+//! aManipulator->AttachToObject (anAISObject);
+//! aManipulator->EnableMode (AIS_Manipulator::Translation);
+//! aManipulator->EnableMode (AIS_Manipulator::Rotation);
+//! aManipulator->EnableMode (AIS_Manipulator::Scaling);
+//! @endcode
+//! Note that you can enable only one manipulation mode but have all visual parts displayed.
+//! This code allows you to view manipulator and select its manipulation parts.
+//! Note that manipulator activates mode on part selection.
+//! If this mode is activated, no selection will be performed for manipulator.
+//! It can be activated with highlighting. To enable this:
+//! @code
+//! aManipulator->SetModeActivationOnDetection (Standard_True);
+//! @endcode
+//! Step 2. To perform transformation of object use next code in your event processing chain:
+//! @code
+//! // catch mouse button down event
+//! if (aManipulator->HasActiveMode())
+//! {
+//! aManipulator->StartTransform (anXPix, anYPix, aV3dView);
+//! }
+//! ...
+//! // or track mouse move event
+//! if (aManipulator->HasActiveMode())
+//! {
+//! aManipulator->Transform (anXPix, anYPix, aV3dView);
+//! aV3dView->Redraw();
+//! }
+//! ...
+//! // or catch mouse button up event (apply) or escape event (cancel)
+//! aManipulator->StopTransform(/*Standard_Boolean toApply*/);
+//! @endcode
+//! Step 3. To deactivate current manipulation mode use:
+//! @code aManipulator->DeactivateCurrentMode();
+//! @endcode
+//! Step 4. To detach manipulator from object use:
+//! @code
+//! aManipulator->Detach();
+//! @endcode
+//! The last method erases manipulator object.
+//! @warning
+//! On construction an instance of AIS_Manipulator object is bound to Graphic3d_ZLayerId_Topmost layer,
+//! so make sure to call for your AIS_InteractiveContext the method MainSelector()->SetPickClosest (Standard_False)
+//! otherwise you may notice issues with activation of modes.
+class AIS_Manipulator : public AIS_InteractiveObject
+{
+public:
+
+ //! Constructs a manipulator object with default placement and all parts to be displayed.
+ Standard_EXPORT AIS_Manipulator();
+
+ //! Constructs a manipulator object with input location and positions of axes and all parts to be displayed.
+ Standard_EXPORT AIS_Manipulator (const gp_Ax2& thePosition);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~AIS_Manipulator() {}
+
+ //! Disable or enable visual parts for translation, rotation or scaling for some axis.
+ //! By default all parts are enabled (will be displayed).
+ //! @warning Enabling or disabling of visual parts of manipulator does not manage the manipulation (selection) mode.
+ //! @warning Raises program error if axis index is < 0 or > 2.
+ Standard_EXPORT void SetPart (const Standard_Integer theAxisIndex, const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled);
+
+ //! Behavior settings to be applied when performing transformation:
+ //! - FollowTranslation - whether the manipulator will be moved together with an object.
+ //! - FollowRotation - whether the manipulator will be rotated together with an object.
+ struct OptionsForAttach {
+
+ OptionsForAttach() : AdjustPosition (Standard_True), AdjustSize (Standard_False), EnableModes (Standard_True) {}
+ OptionsForAttach& SetAdjustPosition (const Standard_Boolean theApply) { AdjustPosition = theApply; return *this; }
+ OptionsForAttach& SetAdjustSize (const Standard_Boolean theApply) { AdjustSize = theApply; return *this; }
+ OptionsForAttach& SetEnableModes (const Standard_Boolean theApply) { EnableModes = theApply; return *this; }
+
+ Standard_Boolean AdjustPosition;
+ Standard_Boolean AdjustSize;
+ Standard_Boolean EnableModes;
+ };
+
+ //! Attaches himself to the input interactive object and become displayed in the same context.
+ //! It is placed in the center of object bounding box, and its size is adjusted to the object bounding box.
+ Standard_EXPORT void Attach (const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions = OptionsForAttach());
+
+ //! Attaches himself to the input interactive object group and become displayed in the same context.
+ //! It become attached to the first object, baut manage manipulation of the whole group.
+ //! It is placed in the center of object bounding box, and its size is adjusted to the object bounding box.
+ Standard_EXPORT void Attach (const Handle(AIS_ManipulatorObjectSequence)& theObject, const OptionsForAttach& theOptions = OptionsForAttach());
+
+ //! Enable manipualtion mode.
+ //! @warning It activates selection mode in the current context.
+ //! If manipulator is not displayed, no mode will be activated.
+ Standard_EXPORT void EnableMode (const AIS_ManipulatorMode theMode);
+
+ //! Enables mode activation on detection (highlighting).
+ //! By default, mode is activated on selection of manipulator part.
+ //! @warning If this mode is enabled, selection of parts does nothing.
+ void SetModeActivationOnDetection (const Standard_Boolean theToEnable)
+ {
+ myIsActivationOnDetection = theToEnable;
+ }
+
+ //! @return true if manual mode activation is enabled.
+ Standard_Boolean IsModeActivationOnDetection() const
+ {
+ return myIsActivationOnDetection;
+ }
+
+public:
+
+ //! Init start (reference) transformation.
+ //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+ //! and is used only for custom transform set. If Transform(const Standard_Integer, const Standard_Integer) is used,
+ //! initial data is set automatically, and it is reset on DeactivateCurrentMode call if it is not reset yet.
+ Standard_EXPORT void StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView);
+
+ //! Apply to the owning objects the input transformation.
+ //! @remark The transformation is set using SetLocalTransformation for owning objects.
+ //! The location of the manipulator is stored also in Local Transformation,
+ //! so that there's no need to redisplay objects.
+ //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+ //! and is used only for custom transform set.
+ //! @warning It will does nothing if transformation is not initiated (with StartTransform() call).
+ Standard_EXPORT void Transform (const gp_Trsf& aTrsf);
+
+ //! Reset start (reference) transformation.
+ //! @param theToApply [in] option to apply or to cancel the started transformation.
+ //! @warning It is used in chain with StartTransform-Transform(gp_Trsf)-StopTransform
+ //! and is used only for custom transform set.
+ Standard_EXPORT void StopTransform (const Standard_Boolean theToApply = Standard_True);
+
+ //! Apply transformation made from mouse moving from start position
+ //! (save on the first Tranform() call and reset on DeactivateCurrentMode() call.)
+ //! to the in/out mouse position (theX, theY)
+ Standard_EXPORT gp_Trsf Transform (const Standard_Integer theX, const Standard_Integer theY,
+ const Handle(V3d_View)& theView);
+
+ //! Computes transformation of parent object according to the active mode and input motion vector.
+ //! You can use this method to get object transformation according to current mode or use own algorithm
+ //! to implement any other tranformation for modes.
+ //! @return transformation of parent object.
+ Standard_EXPORT Standard_Boolean ObjectTransformation (const Standard_Integer theX, const Standard_Integer theY,
+ const Handle(V3d_View)& theView, gp_Trsf& theTrsf);
+
+ //! Make inactive the current selected manipulator part and reset current axis index and current mode.
+ //! After its call HasActiveMode() returns false.
+ //! @sa HasActiveMode()
+ Standard_EXPORT void DeactivateCurrentMode();
+
+ //! Detaches himself from the owner object, and removes itself from context.
+ Standard_EXPORT void Detach();
+
+ //! @return all owning objects.
+ Standard_EXPORT Handle(AIS_ManipulatorObjectSequence) Objects() const;
+
+ //! @return the first (leading) object of the owning objects.
+ Standard_EXPORT Handle(AIS_InteractiveObject) Object() const;
+
+ //! @return one of the owning objects.
+ //! @warning raises program error if theIndex is more than owning objects count or less than 1.
+ Standard_EXPORT Handle(AIS_InteractiveObject) Object (const Standard_Integer theIndex) const;
+
+ //! @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).
+ 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 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);
+ }
+
+public: //! @name Configuration of graphical transformations
+
+ //! Enable or disable zoom persistence mode for the manipulator. With
+ //! this mode turned on the presentation will keep fixed screen size.
+ //! @warning when turned on this option overrides transform persistence
+ //! properties and local transformation to achieve necessary visual effect.
+ //! @warning revise use of AdjustSize argument of of \sa AttachToObjects method
+ //! when enabling zoom persistence.
+ Standard_EXPORT void SetZoomPersistence (const Standard_Boolean theToEnable);
+
+ //! Returns state of zoom persistence mode, whether it turned on or off.
+ Standard_Boolean ZoomPersistence() const { return myIsZoomPersistentMode; }
+
+ //! 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.
+ //! @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
+ //! when enabling zoom persistence.
+ Standard_EXPORT virtual void SetTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint) Standard_OVERRIDE;
+
+ //! Redefines local transformation management method to inform user of inproper use.
+ //! @warning this interactive object does not support setting custom local transformation,
+ //! this class solely uses this property to implement visual positioning of the manipulator
+ //! without need for recomputing presentation.
+ //! @warning Invokes debug assertion in debug to catch incompatible usage of the
+ //! method, silently does nothing in release mode.
+ Standard_EXPORT virtual void SetLocalTransformation (const gp_Trsf& theTransformation) Standard_OVERRIDE;
+
+public: //! @name Setters for parameters
+
+ AIS_ManipulatorMode ActiveMode() const { return myCurrentMode; }
+
+ //! @return poition of manipulator interactive object.
+ const gp_Ax2& Position() const { return myPosition; }
+
+ //! Sets position of the manipulator object.
+ Standard_EXPORT void SetPosition (const gp_Ax2& thePosition);
+
+ Standard_ShortReal Size() const { return myAxes[0].Size(); }
+
+ //! Sets size (length of side of the manipulator cubic bounding box.
+ Standard_EXPORT void SetSize (const Standard_ShortReal theSideLength);
+
+ //! Sets gaps between translator, scaler and rotator sub-presentations.
+ Standard_EXPORT void SetGap (const Standard_ShortReal theValue);
+
+public:
+
+ //! Behavior settings to be applied when performing transformation:
+ //! - FollowTranslation - whether the manipulator will be moved together with an object.
+ //! - FollowRotation - whether the manipulator will be rotated together with an object.
+ struct BehaviorOnTransform {
+
+ BehaviorOnTransform() : FollowTranslation (Standard_True), FollowRotation (Standard_True) {}
+ BehaviorOnTransform& SetFollowTranslation (const Standard_Boolean theApply) { FollowTranslation = theApply; return *this; }
+ BehaviorOnTransform& SetFollowRotation (const Standard_Boolean theApply) { FollowRotation = theApply; return *this; }
+
+ Standard_Boolean FollowTranslation;
+ Standard_Boolean FollowRotation;
+ };
+
+ //! Sets behavior settings for transformation action carried on the manipulator,
+ //! whether it translates, rotates together with the transformed object or not.
+ void SetTransformBehavior (const BehaviorOnTransform& theSettings) { myBehaviorOnTransform = theSettings; }
+
+ //! @return behavior settings for transformation action of the manipulator.
+ BehaviorOnTransform& ChangeTransformBehavior() { return myBehaviorOnTransform; }
+
+ //! @return behavior settings for transformation action of the manipulator.
+ const BehaviorOnTransform& TransformBehavior() const { return myBehaviorOnTransform; }
+
+public: //! @name Presentation computation
+
+ //! Fills presentation.
+ //! @note Manipulator presentation does not use display mode and for all modes has the same presenatation.
+ 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.
+ 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.
+ Standard_EXPORT virtual Standard_Boolean IsAutoHilight() const Standard_OVERRIDE
+ {
+ return Standard_False;
+ }
+
+ //! Method which clear all selected owners belonging
+ //! to this selectable object ( for fast presentation draw ).
+ Standard_EXPORT virtual void ClearSelected() Standard_OVERRIDE;
+
+ //! Method which draws selected owners ( for fast presentation draw ).
+ Standard_EXPORT virtual void HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM, const SelectMgr_SequenceOfOwner& theSeq) Standard_OVERRIDE;
+
+ //! Method which hilight an owner belonging to
+ //! this selectable object ( for fast presentation draw ).
+ Standard_EXPORT virtual void HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, const Quantity_NameOfColor theColor, const Handle(SelectMgr_EntityOwner)& theOwner) Standard_OVERRIDE;
+
+protected:
+
+ Standard_EXPORT void init();
+
+ Standard_EXPORT void updateTransformation();
+
+ Standard_EXPORT Handle(Prs3d_Presentation) getHighlightPresentation (const Handle(SelectMgr_EntityOwner)& theOwner) const;
+
+ Standard_EXPORT Handle(Graphic3d_Group) getGroup (const Standard_Integer theIndex, const AIS_ManipulatorMode theMode) const;
+
+ Standard_EXPORT void attachToBox (const Bnd_Box& theBox);
+
+ Standard_EXPORT void adjustSize (const Bnd_Box& theBox);
+
+ Standard_EXPORT void setTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint);
+
+protected: //! @name Auxilliary classes to fill presentation with proper primitives
+
+ class Quadric
+ {
+ public:
+
+ virtual ~Quadric()
+ {
+ myTriangulation.Nullify();
+ myArray.Nullify();
+ }
+
+
+ const Handle(Poly_Triangulation)& Triangulation() const { return myTriangulation; }
+
+ const Handle(Graphic3d_ArrayOfTriangles)& Array() const { return myArray; }
+
+ protected:
+
+ Handle(Poly_Triangulation) myTriangulation;
+ Handle(Graphic3d_ArrayOfTriangles) myArray;
+ };
+
+ class Cylinder : public Quadric
+ {
+ public:
+
+ Cylinder()
+ : Quadric(),
+ myBottomRad(1.0f),
+ myTopRad(1.0f),
+ myHeight(1.0f)
+ { }
+
+ virtual ~Cylinder() {}
+
+ void Init (const Standard_ShortReal theBotRad, const Standard_ShortReal theTopRad,
+ const Standard_ShortReal theHeight,
+ const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb,
+ const gp_Ax1& thePosition);
+
+ protected:
+
+ gp_Ax1 myPosition;
+ Standard_ShortReal myBottomRad;
+ Standard_ShortReal myTopRad;
+ Standard_ShortReal myHeight;
+ };
+
+ class Disk : public Quadric
+ {
+ public:
+
+ Disk()
+ : Quadric(),
+ myInnerRad(0.0f),
+ myOuterRad(1.0f)
+ { }
+
+ ~Disk() { }
+
+ void Init (const Standard_ShortReal theInnerRadius,
+ const Standard_ShortReal theOuterRadius,
+ const gp_Ax1& thePosition,
+ const Standard_Integer theSlicesNb = 20,
+ const Standard_Integer theStacksNb = 20);
+
+ protected:
+
+ gp_Ax1 myPosition;
+ Standard_ShortReal myInnerRad;
+ Standard_ShortReal myOuterRad;
+ };
+
+ class Sphere : public Quadric
+ {
+ public:
+ Sphere()
+ : Quadric(),
+ myRadius(1.0f)
+ {}
+
+ void Init (const Standard_ShortReal theRadius,
+ const gp_Pnt& thePosition,
+ const Standard_Integer theSlicesNb = 20,
+ const Standard_Integer theStacksNb = 20);
+
+ protected:
+
+ gp_Pnt myPosition;
+ Standard_ShortReal myRadius;
+ };
+
+ class Cube
+ {
+ public:
+
+ Cube() { }
+ ~Cube() { }
+
+ void Init (const gp_Ax1& thePosition, const Standard_ShortReal myBoxSize);
+
+ const Handle(Poly_Triangulation)& Triangulation() const { return myTriangulation; }
+
+ const Handle(Graphic3d_ArrayOfTriangles)& Array() const { return myArray; }
+
+ private:
+
+ void addTriangle (const Standard_Integer theIndex, const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
+ const gp_Dir& theNormal);
+
+ protected:
+
+ Handle(Poly_Triangulation) myTriangulation;
+ Handle(Graphic3d_ArrayOfTriangles) myArray;
+ };
+
+ //! The class describes on axis sub-object.
+ //! It includes sub-objects itself:
+ //! -rotator
+ //! -translator
+ //! -scaler
+ class Axis
+ {
+ public:
+
+ Axis (const gp_Ax1& theAxis = gp_Ax1(),
+ const Quantity_Color& theColor = Quantity_Color(),
+ const Standard_ShortReal theLength = 10.0f);
+
+ void Compute (const Handle_PrsMgr_PresentationManager3d& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Handle(Prs3d_ShadingAspect)& theAspect);
+
+ const gp_Ax1& ReferenceAxis() const { return myReferenceAxis; }
+
+ void SetPosition (const gp_Ax1& thePosition) { myPosition = thePosition; }
+
+ const gp_Ax1& Position() const { return myPosition; }
+
+ void SetTransformPersistence (const Graphic3d_TransModeFlags& theFlags, const gp_Pnt& thePoint)
+ {
+ if (!myHighlightTranslator.IsNull())
+ {
+ myHighlightTranslator->SetTransformPersistence (theFlags, thePoint);
+ }
+
+ if (!myHighlightScaler.IsNull())
+ {
+ myHighlightScaler->SetTransformPersistence (theFlags, thePoint);
+ }
+
+ if (!myHighlightRotator.IsNull())
+ {
+ myHighlightRotator->SetTransformPersistence (theFlags, thePoint);
+ }
+ }
+
+ Graphic3d_TransModeFlags GetTransformPersistenceMode() const { return myHighlightTranslator->TransformPersistenceMode(); }
+
+ gp_Pnt GetTransformPersistencePoint() const { return myHighlightTranslator->TransformPersistencePoint(); }
+
+ void Transform (const Handle(Geom_Transformation)& theTransformation)
+ {
+ if (!myHighlightTranslator.IsNull())
+ {
+ myHighlightTranslator->Transform (theTransformation);
+ }
+
+ if (!myHighlightScaler.IsNull())
+ {
+ myHighlightScaler->Transform (theTransformation);
+ }
+
+ if (!myHighlightRotator.IsNull())
+ {
+ myHighlightRotator->Transform (theTransformation);
+ }
+ }
+
+ Standard_Boolean HasTranslation() const { return myHasTranslation; }
+
+ Standard_Boolean HasRotation() const { return myHasRotation; }
+
+ Standard_Boolean HasScaling() const { return myHasScaling; }
+
+ void SetTranslation (const Standard_Boolean theIsEnabled) { myHasTranslation = theIsEnabled; }
+
+ void SetRotation (const Standard_Boolean theIsEnabled) { myHasRotation = theIsEnabled; }
+
+ void SetScaling (const Standard_Boolean theIsEnabled) { myHasScaling = theIsEnabled; }
+
+ Quantity_Color Color() const { return myColor; }
+
+ Standard_ShortReal AxisLength() const { return myLength; }
+
+ Standard_ShortReal AxisRadius() const { return myAxisRadius; }
+
+ void SetAxisRadius (const Standard_ShortReal theValue) { myAxisRadius = theValue; }
+
+ const Handle(Prs3d_Presentation)& TranslatorHighlightPrs() const { return myHighlightTranslator; }
+
+ const Handle(Prs3d_Presentation)& RotatorHighlightPrs() const { return myHighlightRotator; }
+
+ const Handle(Prs3d_Presentation)& ScalerHighlightPrs() const { return myHighlightScaler; }
+
+ const Handle(Graphic3d_Group)& TranslatorGroup() const { return myTranslatorGroup; }
+
+ const Handle(Graphic3d_Group)& RotatorGroup() const { return myRotatorGroup; }
+
+ const Handle(Graphic3d_Group)& ScalerGroup() const { return myScalerGroup; }
+
+ void SetIndent (const Standard_ShortReal theValue) { myIndent = theValue; }
+
+ Standard_ShortReal Size() const { return myLength + myBoxSize + myDiskThickness + myIndent * 2.0f; }
+
+ gp_Pnt ScalerCenter (const gp_Pnt& theLocation) const { return theLocation.XYZ() + myPosition.Direction().XYZ() * (myLength + myIndent + myBoxSize * 0.5f); }
+
+ void SetSize (const Standard_ShortReal theValue)
+ {
+ if (myIndent > theValue * 0.1f)
+ {
+ myLength = theValue * 0.7f;
+ myBoxSize = theValue * 0.15f;
+ myDiskThickness = theValue * 0.05f;
+ myIndent = theValue * 0.05f;
+ }
+ else // use pre-set value of predent
+ {
+ Standard_ShortReal aLength = theValue - 2 * myIndent;
+ myLength = aLength * 0.8f;
+ myBoxSize = aLength * 0.15f;
+ myDiskThickness = aLength * 0.05f;
+ }
+ myInnerRadius = myIndent * 2 + myBoxSize + myLength;
+ myAxisRadius = myBoxSize / 4.0f;
+ }
+
+ Standard_Integer FacettesNumber() const { return myFacettesNumber; }
+
+ public:
+
+ const Cylinder& TranslatorCylinder() const { return myCylinder; }
+ const Cylinder& TranslatorArrow() const { return myArrow; }
+ const gp_Pnt& TranslatorTipPosition() const { return myArrowTipPos; }
+ const Disk& TranslatorArrowBottom() const { return myArrowBottom; }
+ const Disk& RotatorDisk() const { return myCircle; }
+ float RotatorDiskRadius() const { return myCircleRadius; }
+ const Cube& ScalerCube() const { return myCube; }
+ const gp_Pnt& ScalerCubePosition() const { return myCubePos; }
+
+ protected:
+
+ gp_Ax1 myReferenceAxis; //!< Returns reference axis assignment.
+ gp_Ax1 myPosition; //!< Position of the axis including local transformation.
+ Quantity_Color myColor;
+
+ Standard_Boolean myHasTranslation;
+ Standard_ShortReal myLength; //!< Length of translation axis.
+ Standard_ShortReal myAxisRadius;
+
+ Standard_Boolean myHasScaling;
+ Standard_ShortReal myBoxSize; //!< Size of scaling cube.
+
+ Standard_Boolean myHasRotation;
+ Standard_ShortReal myInnerRadius; //!< Radius of rotation circle.
+ Standard_ShortReal myDiskThickness;
+ Standard_ShortReal myIndent; //!< Gap between visual part of the manipulator.
+
+ protected:
+
+ Standard_Integer myFacettesNumber;
+
+ Cylinder myCylinder;
+ Cylinder myArrow;
+ gp_Pnt myArrowTipPos;
+ Disk myArrowBottom;
+ Disk myCircle;
+ float myCircleRadius;
+ Cube myCube;
+ gp_Pnt myCubePos;
+
+ Handle(Graphic3d_Group) myTranslatorGroup;
+ Handle(Graphic3d_Group) myScalerGroup;
+ Handle(Graphic3d_Group) myRotatorGroup;
+
+ Handle(Prs3d_Presentation) myHighlightTranslator;
+ Handle(Prs3d_Presentation) myHighlightScaler;
+ Handle(Prs3d_Presentation) myHighlightRotator;
+ };
+
+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.
+
+ Standard_Integer myCurrentIndex; //!< Index of active axis.
+ AIS_ManipulatorMode myCurrentMode; //!< Name of active manipualtion 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.
+
+ 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()).
+ gp_Ax2 myStartPosition; //! Start position of manipulator.
+ 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.
+ Handle(Prs3d_ShadingAspect) myHighlightAspect;
+public:
+
+ DEFINE_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject)
+};
+#endif // _AIS_Manipulator_HeaderFile
--- /dev/null
+// Created on: 2015-02-05
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_ManipulatorMode_HeaderFile
+#define _AIS_ManipulatorMode_HeaderFile
+
+//! Mode to make definite kind of transformations with AIS_Manipulator object.
+enum AIS_ManipulatorMode
+{
+ AIS_MM_None = 0,
+ AIS_MM_Translation = 1,
+ AIS_MM_Rotation,
+ AIS_MM_Scaling
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2015-12-23
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_ManipulatorOwner.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(AIS_ManipulatorOwner,SelectMgr_EntityOwner)
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+AIS_ManipulatorOwner::AIS_ManipulatorOwner (const Handle(SelectMgr_SelectableObject)& theSelObject,
+ const Standard_Integer theIndex,
+ const AIS_ManipulatorMode theMode,
+ const Standard_Integer thePriority)
+: SelectMgr_EntityOwner(theSelObject, thePriority),
+ myIndex (theIndex),
+ myMode (theMode)
+{
+ //
+}
+
+//=======================================================================
+//function : HilightWithColor
+//purpose :
+//=======================================================================
+void AIS_ManipulatorOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
+ const Quantity_NameOfColor theColor,
+ const Standard_Integer theMode)
+{
+ if (theMode == 0)
+ {
+ SelectMgr_EntityOwner::HilightWithColor (thePM, theColor, theMode);
+ return;
+ }
+
+ Selectable()->HilightOwnerWithColor (thePM, theColor, this);
+}
+
+//=======================================================================
+//function : IsHilighted
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_ManipulatorOwner::IsHilighted (const Handle(PrsMgr_PresentationManager)& thePM,
+ const Standard_Integer /*theMode*/) const
+{
+ if (!HasSelectable())
+ {
+ return Standard_False;
+ }
+
+ return thePM->IsHighlighted (Selectable(), myMode);
+}
+
+//=======================================================================
+//function : Hilight
+//purpose :
+//=======================================================================
+void AIS_ManipulatorOwner::Hilight (const Handle(PrsMgr_PresentationManager)& thePM,
+ const Standard_Integer /*theMode*/)
+{
+ if (!HasSelectable())
+ {
+ return;
+ }
+
+ thePM->Highlight (Selectable(), myMode);
+}
+
+//=======================================================================
+//function : Unhilight
+//purpose :
+//=======================================================================
+void AIS_ManipulatorOwner::Unhilight (const Handle(PrsMgr_PresentationManager)& thePM,
+ const Standard_Integer /*theMode*/)
+{
+ if (!HasSelectable())
+ {
+ return;
+ }
+
+ thePM->Unhighlight (Selectable(), myMode);
+}
--- /dev/null
+// Created on: 2015-12-23
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_ManipulatorOwner_HeaderFile
+#define _AIS_ManipulatorOwner_HeaderFile
+
+#include <AIS_Manipulator.hxx>
+
+#include <SelectMgr_EntityOwner.hxx>
+#include <SelectMgr_SelectableObject.hxx>
+
+DEFINE_STANDARD_HANDLE(AIS_ManipulatorOwner, SelectMgr_EntityOwner)
+
+//! Entity owner for selection management of AIS_Manipulator object.
+class AIS_ManipulatorOwner : public SelectMgr_EntityOwner
+{
+public:
+
+ DEFINE_STANDARD_RTTIEXT(AIS_ManipulatorOwner, SelectMgr_EntityOwner)
+
+ Standard_EXPORT AIS_ManipulatorOwner (const Handle(SelectMgr_SelectableObject)& theSelObject,
+ const Standard_Integer theIndex,
+ const AIS_ManipulatorMode theMode,
+ const Standard_Integer thePriority = 0);
+
+ Standard_EXPORT virtual ~AIS_ManipulatorOwner() {}
+
+ Standard_EXPORT virtual void HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, const Quantity_NameOfColor theColor, const Standard_Integer theMode) Standard_OVERRIDE;
+
+ Standard_EXPORT Standard_Boolean IsHilighted (const Handle(PrsMgr_PresentationManager)& thePM,
+ const Standard_Integer theMode) const Standard_OVERRIDE;
+
+ Standard_EXPORT virtual void Hilight (const Handle(PrsMgr_PresentationManager)& thePM, const Standard_Integer theMode) Standard_OVERRIDE;
+
+ Standard_EXPORT virtual void Unhilight (const Handle(PrsMgr_PresentationManager)& thePM, const Standard_Integer theMode) Standard_OVERRIDE;
+
+ Standard_EXPORT AIS_ManipulatorMode Mode() const { return myMode; }
+
+ //! @return index of manipulator axis.
+ Standard_EXPORT Standard_Integer Index() const { return myIndex; }
+
+protected:
+
+ Standard_Integer myIndex; //!< index of manipulator axis.
+ AIS_ManipulatorMode myMode;//!< manipulation (highlight) mode.
+};
+
+#endif // _AIS_ManipulatorOwner_HeaderFile
AIS_LocalStatus.cxx
AIS_LocalStatus.hxx
AIS_LocalStatus.lxx
+AIS_Manipulator.hxx
+AIS_Manipulator.cxx
+AIS_ManipulatorMode.hxx
+AIS_ManipulatorOwner.hxx
+AIS_ManipulatorOwner.cxx
AIS_MapIteratorOfMapOfInteractive.hxx
AIS_MapOfInteractive.hxx
AIS_MaxRadiusDimension.cxx
StdPrs_ShadedShape.hxx
StdPrs_ShadedSurface.cxx
StdPrs_ShadedSurface.hxx
+StdPrs_ToolDisk.hxx
+StdPrs_ToolDisk.cxx
+StdPrs_ToolCylinder.hxx
+StdPrs_ToolCylinder.cxx
StdPrs_ToolPoint.cxx
StdPrs_ToolPoint.hxx
+StdPrs_ToolQuadric.hxx
+StdPrs_ToolQuadric.cxx
+StdPrs_ToolSphere.hxx
+StdPrs_ToolSphere.cxx
StdPrs_ToolRFace.cxx
StdPrs_ToolRFace.hxx
StdPrs_ToolTriangulatedShape.cxx
--- /dev/null
+// Created on: 1995-07-27
+// Created by: Modelistation
+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+
+#include <StdPrs_ToolCylinder.hxx>
+
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+StdPrs_ToolCylinder::StdPrs_ToolCylinder (const Standard_ShortReal theBottomRad,
+ const Standard_ShortReal theTopRad,
+ const Standard_ShortReal theHeight,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb)
+: myBottomRadius (theBottomRad),
+ myTopRadius (theTopRad),
+ myHeight (theHeight)
+{
+ myStacksNb = theStacksNb;
+ mySlicesNb = theSlicesNb;
+}
+
+//=======================================================================
+//function : Vertex
+//purpose :
+//=======================================================================
+gp_Pnt StdPrs_ToolCylinder::Vertex (const Standard_Real theU, const Standard_Real theV)
+{
+ const Standard_ShortReal aU = static_cast<Standard_ShortReal> (theU * M_PI * 2.0);
+ const Standard_ShortReal aRadius = myBottomRadius + (myTopRadius - myBottomRadius) * (Standard_ShortReal)theV;
+ return gp_Pnt (cosf(aU) * aRadius,
+ sinf(aU) * aRadius,
+ theV * myHeight);
+}
+
+//=======================================================================
+//function : Add
+//purpose :
+//=======================================================================
+gp_Dir StdPrs_ToolCylinder::Normal (const Standard_Real theU, const Standard_Real /*theV*/)
+{
+ const Standard_ShortReal aU = static_cast<Standard_ShortReal> (theU * M_PI * 2.0);
+ return gp_Dir (gp_Vec(cosf(aU) * myHeight,
+ sinf(aU) * myHeight,
+ myBottomRadius - myTopRadius).Normalized().XYZ());
+}
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _StdPrs_ToolCylinder_HeaderFile
+#define _StdPrs_ToolCylinder_HeaderFile
+
+#include <Standard.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//! Standard presentation algorithm that outputs graphical primitives for cylindrical surface.
+class StdPrs_ToolCylinder : public StdPrs_ToolQuadric
+{
+public:
+
+ DEFINE_STANDARD_ALLOC
+
+ //! Initializes the algorithm.
+ Standard_EXPORT StdPrs_ToolCylinder (const Standard_ShortReal theBottomRad,
+ const Standard_ShortReal theTopRad,
+ const Standard_ShortReal theHeight,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb);
+
+protected:
+
+ //! Computes vertex at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Pnt Vertex (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+ //! Computes normal at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Dir Normal (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+protected:
+
+ Standard_ShortReal myBottomRadius;
+ Standard_ShortReal myTopRadius;
+ Standard_ShortReal myHeight;
+};
+
+#endif // _StdPrs_ToolCylinder_HeaderFile
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+
+#include <StdPrs_ToolDisk.hxx>
+
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+StdPrs_ToolDisk::StdPrs_ToolDisk (const Standard_ShortReal theInnerRadius,
+ const Standard_ShortReal theOuterRadius,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb)
+: myInnerRadius (theInnerRadius),
+ myOuterRadius (theOuterRadius)
+{
+ mySlicesNb = theSlicesNb;
+ myStacksNb = theStacksNb;
+}
+
+//=======================================================================
+//function : Vertex
+//purpose :
+//=======================================================================
+gp_Pnt StdPrs_ToolDisk::Vertex (const Standard_Real theU, const Standard_Real theV)
+{
+ const Standard_ShortReal aU = static_cast<Standard_ShortReal> (theU * M_PI * 2.0);
+ const Standard_ShortReal aRadius = myInnerRadius + (myOuterRadius - myInnerRadius) * (Standard_ShortReal)theV;
+ return gp_Pnt (cosf(aU) * aRadius,
+ sinf(aU) * aRadius,
+ 0.0f);
+}
+
+//=======================================================================
+//function : Add
+//purpose :
+//=======================================================================
+gp_Dir StdPrs_ToolDisk::Normal (const Standard_Real /*theU*/, const Standard_Real /*theV*/)
+{
+ return gp_Dir(0.0f, 0.0f, -1.0f);
+}
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _StdPrs_ToolDisk_HeaderFile
+#define _StdPrs_ToolDisk_HeaderFile
+
+#include <Standard.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//! Standard presentation algorithm that outputs graphical primitives for disk surface.
+class StdPrs_ToolDisk : public StdPrs_ToolQuadric
+{
+public:
+
+ DEFINE_STANDARD_ALLOC
+
+ //! Initializes the algorithm.
+ Standard_EXPORT StdPrs_ToolDisk (const Standard_ShortReal theInnerRadius,
+ const Standard_ShortReal theOuterRadius,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb);
+
+protected:
+
+ //! Computes vertex at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Pnt Vertex (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+ //! Computes normal at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Dir Normal (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+protected:
+
+ Standard_ShortReal myInnerRadius;
+ Standard_ShortReal myOuterRadius;
+};
+
+
+#endif
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <StdPrs_ToolQuadric.hxx>
+
+#include <gp_Quaternion.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+
+//=======================================================================
+//function : fillArrays
+//purpose :
+//=======================================================================
+void StdPrs_ToolQuadric::fillArrays (const gp_Trsf& theTrsf, TColgp_Array1OfPnt& theArray, NCollection_Array1<gp_Dir>& theNormals)
+{
+ Standard_ShortReal aStepU = 1.0f / mySlicesNb;
+ Standard_ShortReal aStepV = 1.0f / myStacksNb;
+
+ for (Standard_Integer aU = 0; aU <= mySlicesNb; aU++)
+ {
+ const Standard_Real aParamU = aU * aStepU;
+ for (Standard_Integer aV = 0; aV <= myStacksNb; aV++)
+ {
+ const Standard_ShortReal aParamV = aV * aStepV;
+ const Standard_Integer aVertId = aU * (myStacksNb + 1) + aV + 1;
+ gp_Pnt aVertex = Vertex(aParamU, aParamV);
+ gp_Dir aNormal = Normal(aParamU, aParamV);
+
+ aVertex.Transform (theTrsf);
+ aNormal.Transform (theTrsf);
+
+ theArray.SetValue (aVertId, aVertex);
+ theNormals.SetValue (aVertId, aNormal);
+ }
+ }
+}
+
+//=======================================================================
+//function : FIllArray
+//purpose :
+//=======================================================================
+void StdPrs_ToolQuadric::FillArray (Handle(Graphic3d_ArrayOfTriangles)& theArray, const gp_Trsf& theTrsf)
+{
+ const Standard_Integer aTrianglesNb = TrianglesNb();
+ theArray = new Graphic3d_ArrayOfTriangles (aTrianglesNb * 3, 0, Standard_True);
+
+ Poly_Array1OfTriangle aPolyTriangles (1, aTrianglesNb);
+ TColgp_Array1OfPnt anArray (1, aTrianglesNb * 3);
+ NCollection_Array1<gp_Dir> aNormals (1, aTrianglesNb * 3);
+ fillArrays (theTrsf, anArray, aNormals);
+
+ // Fill primitives
+ for (Standard_Integer aU = 0; aU < mySlicesNb; ++aU)
+ {
+ for (Standard_Integer aV = 1; aV <= myStacksNb; ++aV)
+ {
+ theArray->AddVertex (anArray.Value (aU * (myStacksNb + 1) + aV), aNormals.Value (aU * (myStacksNb + 1) + aV));
+ theArray->AddVertex (anArray.Value ((aU + 1) * (myStacksNb + 1) + aV), aNormals.Value ((aU + 1) * (myStacksNb + 1) + aV));
+ theArray->AddVertex (anArray.Value ((aU + 1) * (myStacksNb + 1) + (aV + 1)), aNormals.Value ((aU + 1) * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex (anArray.Value ((aU + 1) * (myStacksNb + 1) + (aV + 1)), aNormals.Value ((aU + 1) * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex (anArray.Value (aU * (myStacksNb + 1) + (aV + 1)), aNormals.Value (aU * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex (anArray.Value (aU * (myStacksNb + 1) + aV), aNormals.Value (aU * (myStacksNb + 1) + aV));
+ }
+ }
+}
+
+//=======================================================================
+//function : FillTriangulation
+//purpose :
+//=======================================================================
+void StdPrs_ToolQuadric::FillArray (Handle(Graphic3d_ArrayOfTriangles)& theArray,
+ Handle(Poly_Triangulation)& theTriangulation,
+ const gp_Trsf& theTrsf)
+{
+ const Standard_Integer aTrianglesNb = TrianglesNb();
+ theArray = new Graphic3d_ArrayOfTriangles(aTrianglesNb * 3, 0, Standard_True);
+
+ Poly_Array1OfTriangle aPolyTriangles(1, aTrianglesNb);
+ TColgp_Array1OfPnt anArray(1, aTrianglesNb * 3);
+ NCollection_Array1<gp_Dir> aNormals(1, aTrianglesNb * 3);
+ fillArrays(theTrsf, anArray, aNormals);
+
+ // Fill triangles
+ for (Standard_Integer aU = 0, anIndex = 0; aU < mySlicesNb; ++aU)
+ {
+ for (Standard_Integer aV = 1; aV <= myStacksNb; ++aV)
+ {
+ theArray->AddVertex(anArray.Value(aU * (myStacksNb + 1) + aV), aNormals.Value(aU * (myStacksNb + 1) + aV));
+ theArray->AddVertex(anArray.Value((aU + 1) * (myStacksNb + 1) + aV), aNormals.Value((aU + 1) * (myStacksNb + 1) + aV));
+ theArray->AddVertex(anArray.Value((aU + 1) * (myStacksNb + 1) + (aV + 1)), aNormals.Value((aU + 1) * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex(anArray.Value((aU + 1) * (myStacksNb + 1) + (aV + 1)), aNormals.Value((aU + 1) * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex(anArray.Value(aU * (myStacksNb + 1) + (aV + 1)), aNormals.Value(aU * (myStacksNb + 1) + (aV + 1)));
+ theArray->AddVertex(anArray.Value(aU * (myStacksNb + 1) + aV), aNormals.Value(aU * (myStacksNb + 1) + aV));
+
+ aPolyTriangles.SetValue (++anIndex, Poly_Triangle(aU * (myStacksNb + 1) + aV,
+ (aU + 1) * (myStacksNb + 1) + aV,
+ (aU + 1) * (myStacksNb + 1) + (aV + 1)));
+ aPolyTriangles.SetValue (++anIndex, Poly_Triangle((aU + 1) * (myStacksNb + 1) + (aV + 1),
+ aU * (myStacksNb + 1) + (aV + 1),
+ aU * (myStacksNb + 1) + aV));
+ }
+ }
+
+ theTriangulation = new Poly_Triangulation (anArray, aPolyTriangles);
+}
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _StdPrs_ToolQuadric_HeaderFile
+#define _StdPrs_ToolQuadric_HeaderFile
+
+#include <gp_Ax1.hxx>
+#include <Graphic3d_ArrayOfPrimitives.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <SelectMgr_Selection.hxx>
+#include <Standard.hxx>
+
+//! Base class to build 3D surfaces presentation of quadric surfaces.
+class StdPrs_ToolQuadric
+{
+public:
+
+ DEFINE_STANDARD_ALLOC
+
+ //! Generate primitives for 3D quadric surface and fill the given array. Optional transformation is applied.
+ Standard_EXPORT void FillArray (Handle(Graphic3d_ArrayOfTriangles)& theArray, const gp_Trsf& theTrsf);
+
+ //! Generate primitives for 3D quadric surface presentation and fill the given array and poly triangulation structure. Optional transformation is applied.
+ Standard_EXPORT void FillArray (Handle(Graphic3d_ArrayOfTriangles)& theArray, Handle(Poly_Triangulation)& theTriangulation, const gp_Trsf& theTrsf);
+
+protected:
+
+ //! Method implements an algorithm to generate arrays of vertices and normals for 3D surface.
+ Standard_EXPORT void fillArrays (const gp_Trsf& theTrsf, TColgp_Array1OfPnt& theArray, NCollection_Array1<gp_Dir>& theNormals);
+
+ //! Number of triangles in generated presentation.
+ Standard_Integer TrianglesNb() const
+ {
+ return mySlicesNb * myStacksNb * 2;
+ }
+
+ //! Redefine this method to generate vertex at given parameters.
+ virtual gp_Pnt Vertex (const Standard_Real theU, const Standard_Real theV) = 0;
+
+ //! Redefine this method to generate normal at given parameters.
+ virtual gp_Dir Normal (const Standard_Real theU, const Standard_Real theV) = 0;
+
+protected:
+
+ Standard_Integer mySlicesNb;
+ Standard_Integer myStacksNb;
+};
+
+#endif // _StdPrs_ShadedSurface_HeaderFile
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <StdPrs_ToolSphere.hxx>
+
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+StdPrs_ToolSphere::StdPrs_ToolSphere (const Standard_ShortReal theRadius,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb)
+: myRadius (theRadius)
+{
+ mySlicesNb = theSlicesNb;
+ myStacksNb = theStacksNb;
+}
+
+//=======================================================================
+//function : Vertex
+//purpose :
+//=======================================================================
+gp_Pnt StdPrs_ToolSphere::Vertex (const Standard_Real theU, const Standard_Real theV)
+{
+ const Standard_ShortReal aU = static_cast<Standard_ShortReal> (theU * M_PI * 2.0);
+ const Standard_ShortReal aV = static_cast<Standard_ShortReal> (theV * M_PI);
+ return gp_Pnt (myRadius * cosf(aU) * sinf(aV),
+ -myRadius * sinf(aU) * sinf(aV),
+ myRadius * cosf(aV));
+}
+
+//=======================================================================
+//function : Add
+//purpose :
+//=======================================================================
+gp_Dir StdPrs_ToolSphere::Normal (const Standard_Real theU, const Standard_Real theV)
+{
+ const Standard_ShortReal aU = static_cast<Standard_ShortReal> (theU * M_PI * 2.0);
+ const Standard_ShortReal aV = static_cast<Standard_ShortReal> (theV * M_PI);
+ return gp_Dir (cosf(aU) * sinf(aV),
+ -sinf(aU) * sinf(aV),
+ cosf(aV));
+}
--- /dev/null
+// Created on: 2016-02-04
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _StdPrs_ToolSphere_HeaderFile
+#define _StdPrs_ToolSphere_HeaderFile
+
+#include <Graphic3d_ArrayOfPrimitives.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <SelectMgr_Selection.hxx>
+#include <Standard.hxx>
+#include <Standard_Handle.hxx>
+#include <StdPrs_ToolQuadric.hxx>
+
+//! Standard presentation algorithm that outputs graphical primitives for spherical surface.
+class StdPrs_ToolSphere : public StdPrs_ToolQuadric
+{
+public:
+
+ DEFINE_STANDARD_ALLOC
+
+ //! Initializes the algorithm.
+ Standard_EXPORT StdPrs_ToolSphere (const Standard_ShortReal theRadius,
+ const Standard_Integer theSlicesNb,
+ const Standard_Integer theStacksNb);
+
+protected:
+
+ //! Computes vertex at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Pnt Vertex (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+ //! Computes normal at given parameter location of the surface.
+ Standard_EXPORT virtual gp_Dir Normal (const Standard_Real theU, const Standard_Real theV) Standard_OVERRIDE;
+
+protected:
+
+ Standard_ShortReal myRadius;
+};
+
+
+#endif
//function : ArgVec3f
//purpose :
//===============================================================================================
-Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName)
+Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName, Standard_Integer theArgumentIndex)
{
- return Graphic3d_Vec3 (static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, 0).c_str())),
- static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, 1).c_str())),
- static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, 2).c_str())));
+ return Graphic3d_Vec3 (static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())),
+ static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())),
+ static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())));
}
//===============================================================================================
//function : ArgVec3d
//purpose :
//===============================================================================================
-Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName)
+Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName, Standard_Integer theArgumentIndex)
{
- return Graphic3d_Vec3d ( Draw::Atof (Arg (theOptionName, 0).c_str()),
- Draw::Atof (Arg (theOptionName, 1).c_str()),
- Draw::Atof (Arg (theOptionName, 2).c_str()));
+ return Graphic3d_Vec3d ( Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
+}
+
+//===============================================================================================
+//function : ArgVec
+//purpose :
+//===============================================================================================
+gp_Vec ViewerTest_CmdParser::ArgVec (const std::string& theOptionName, Standard_Integer theArgumentIndex)
+{
+ return gp_Vec ( Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
+}
+
+//===============================================================================================
+//function : ArgPnt
+//purpose :
+//===============================================================================================
+gp_Pnt ViewerTest_CmdParser::ArgPnt (const std::string& theOptionName, Standard_Integer theArgumentIndex)
+{
+ return gp_Pnt ( Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
+ Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
}
//===============================================================================================
//function : ArgDouble
//purpose :
//===============================================================================================
-Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName)
+Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName, Standard_Integer theArgumentIndex)
{
- return Draw::Atof (Arg (theOptionName, 0).c_str());
+ return Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str());
}
//===============================================================================================
//function : ArgFloat
//purpose :
//===============================================================================================
-Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName)
+Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName, Standard_Integer theArgumentIndex)
+{
+ return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
+}
+
+//===============================================================================================
+//function : ArgInt
+//purpose :
+//===============================================================================================
+Standard_Integer ViewerTest_CmdParser::ArgInt (const std::string& theOptionName, const Standard_Integer theArgumentIndex)
+{
+ return static_cast<Standard_Integer> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
+}
+
+//===============================================================================================
+//function : ArgBool
+//purpose :
+//===============================================================================================
+Standard_Boolean ViewerTest_CmdParser::ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex)
{
- return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, 0).c_str()));
+ return static_cast<Standard_Boolean> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
}
#include <Standard.hxx>
#include <Graphic3d_Vec.hxx>
+#include <gp_Vec.hxx>
//! Command parser.
class ViewerTest_CmdParser
//! Accesses local argument of option 'theOptionName' with index 'theArgumentIndex'.
std::string Arg (const std::string& theOptionName, Standard_Integer theArgumentIndex);
- // Interprets arguments of option 'theOptionName' as float vector.
- Graphic3d_Vec3 ArgVec3f (const std::string& theOptionName);
+ // Interprets arguments of option 'theOptionName' as float vector starting with index 'theArgumentIndex'.
+ Graphic3d_Vec3 ArgVec3f (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
- // Interprets arguments of option 'theOptionName' as double vector.
- Graphic3d_Vec3d ArgVec3d (const std::string& theOptionName);
+ // Interprets arguments of option 'theOptionName' as double vector starting with index 'theArgumentIndex'.
+ Graphic3d_Vec3d ArgVec3d (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
- // Interprets arguments of option 'theOptionName' as double.
- Standard_Real ArgDouble (const std::string& theOptionName);
+ // Interprets arguments of option 'theOptionName' as gp vector starting with index 'theArgumentIndex'.
+ gp_Vec ArgVec (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
- // Interprets arguments of option 'theOptionName' as float.
- Standard_ShortReal ArgFloat (const std::string& theOptionName);
+ // Interprets arguments of option 'theOptionName' as gp vector starting with index 'theArgumentIndex'.
+ gp_Pnt ArgPnt (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
+
+ // Interprets arguments of option 'theOptionName' as double at index 'theArgumentIndex'.
+ Standard_Real ArgDouble (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
+
+ // Interprets arguments of option 'theOptionName' as float at index 'theArgumentIndex'.
+ Standard_ShortReal ArgFloat (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
+
+ // Interprets arguments of option 'theOptionName' as integer at index 'theArgumentIndex'.
+ Standard_Integer ArgInt (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
+
+ // Interprets arguments of option 'theOptionName' as boolean at index 'theArgumentIndex'.
+ Standard_Boolean ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex = 0);
private:
#include <OpenGl_GlCore20.hxx>
#include <AIS_ColorScale.hxx>
+#include <AIS_Manipulator.hxx>
#include <AIS_RubberBand.hxx>
#include <AIS_Shape.hxx>
#include <AIS_InteractiveObject.hxx>
#include <ViewerTest_EventManager.hxx>
#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
+#include <ViewerTest_CmdParser.hxx>
#include <V3d_AmbientLight.hxx>
#include <V3d_DirectionalLight.hxx>
#include <V3d_PositionalLight.hxx>
return aBand;
}
+typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
+
+Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
+{
+ static ViewerTest_MapOfAISManipulators aMap;
+ return aMap;
+}
+
+Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
+{
+ ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
+ for (; anIt.More(); anIt.Next())
+ {
+ if (anIt.Value()->HasActiveMode())
+ {
+ return anIt.Value();
+ }
+ }
+ return NULL;
+}
+
//==============================================================================
#ifdef _WIN32
}
}
break;
+
case WM_LBUTTONUP:
- if (!DragFirst)
+ if (IsDragged && !DragFirst)
{
+ if (!GetActiveAISManipulator().IsNull())
+ {
+ GetActiveAISManipulator()->StopTransform();
+ ViewerTest::GetAISContext()->ClearSelected();
+ }
+
if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
{
ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
IsDragged = Standard_False;
return ViewerWindowProc( hwnd, Msg, wParam, lParam );
+ case WM_RBUTTONUP:
+ if (IsDragged && !DragFirst)
+ {
+ if (!GetActiveAISManipulator().IsNull())
+ {
+ GetActiveAISManipulator()->StopTransform (Standard_False);
+ ViewerTest::GetAISContext()->ClearSelected();
+ }
+ IsDragged = Standard_False;
+ }
+ return ViewerWindowProc (hwnd, Msg, wParam, lParam);
+
case WM_LBUTTONDOWN:
- if( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) )
+ if (!GetActiveAISManipulator().IsNull())
+ {
+ IsDragged = ( fwKeys == MK_LBUTTON );
+ }
+ else
+ {
+ IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
+ }
+
+ if (IsDragged)
{
- IsDragged = Standard_True;
DragFirst = Standard_True;
X_ButtonPress = LOWORD(lParam);
Y_ButtonPress = HIWORD(lParam);
}
return ViewerWindowProc( hwnd, Msg, wParam, lParam );
- break;
-
case WM_MOUSEMOVE:
if (IsDragged)
{
- bool toRedraw = false;
- if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
- {
- ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
- toRedraw = true;
- }
-
- DragFirst = Standard_False;
X_Motion = LOWORD (lParam);
Y_Motion = HIWORD (lParam);
-
- RECT aRect;
- if (GetClientRect (hwnd, &aRect))
+ if (!GetActiveAISManipulator().IsNull())
{
- int aHeight = aRect.bottom - aRect.top;
- GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
- ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
- toRedraw = true;
+ if (DragFirst)
+ {
+ GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
+ }
+ else
+ {
+ GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
+ ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
+ }
}
- if (toRedraw)
+ else
{
- ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
+ bool toRedraw = false;
+ if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
+ {
+ ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
+ toRedraw = true;
+ }
+
+ RECT aRect;
+ if (GetClientRect (hwnd, &aRect))
+ {
+ int aHeight = aRect.bottom - aRect.top;
+ GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
+ ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
+ toRedraw = true;
+ }
+ if (toRedraw)
+ {
+ ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
+ }
}
+
+ DragFirst = Standard_False;
}
else
return ViewerWindowProc( hwnd, Msg, wParam, lParam );
return 0;
}
+//===============================================================================================
+//class : ViewerTest_AISManipulator
+//purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
+//===============================================================================================
+DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
+
+class ViewerTest_AISManipulator : public AIS_Manipulator
+{
+public:
+
+ ViewerTest_AISManipulator() : AIS_Manipulator()
+ {
+ GetMapOfAISManipulators().Add (this);
+ }
+
+ virtual ~ViewerTest_AISManipulator()
+ {
+ GetMapOfAISManipulators().Remove (this);
+ }
+
+ DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
+};
+
+IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
+IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
+
+//===============================================================================================
+//function : VManipulator
+//purpose :
+//===============================================================================================
+static int VManipulator (Draw_Interpretor& theDi,
+ Standard_Integer theArgsNb,
+ const char** theArgVec)
+{
+ Handle(V3d_View) aView = ViewerTest::CurrentView();
+ Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
+ ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
+ if (aView.IsNull()
+ || aViewer.IsNull())
+ {
+ std::cerr << "No active viewer!\n";
+ return 1;
+ }
+
+ ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
+ Standard_Integer anArgIter = 1;
+ for (; anArgIter < theArgsNb; ++anArgIter)
+ {
+ anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
+ }
+
+ ViewerTest_CmdParser aCmd;
+ aCmd.AddDescription ("Manages manipulator for interactive objects:");
+ aCmd.AddOption ("attach", "... object - attach manipulator to an object");
+ aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
+ aCmd.AddOption ("adjustSize", "... {0|1} - adjust size when attaching ");
+ aCmd.AddOption ("enableModes", "... {0|1} - enable modes when attaching ");
+ aCmd.AddOption ("detach", "... - detach manipulator");
+
+ aCmd.AddOption ("startTransform", "... mouse_x mouse_y - invoke start transformation");
+ aCmd.AddOption ("transform", "... mouse_x mouse_y - invoke transformation");
+ aCmd.AddOption ("stopTransform", "... [abort] - invoke stop transformation");
+
+ aCmd.AddOption ("move", "... x y z - move object");
+ aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
+ aCmd.AddOption ("scale", "... factor - scale object");
+
+ aCmd.AddOption ("autoActivate", "... {0|1} - set activation on detection");
+ aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
+ aCmd.AddOption ("followRotation", "... {0|1} - set following rotation transform");
+ aCmd.AddOption ("gap", "... value - set gap between sub-parts");
+ aCmd.AddOption ("part", "... axis mode {0|1} - set visual part");
+ aCmd.AddOption ("pos", "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
+ aCmd.AddOption ("size", "... size - set size of manipulator");
+ aCmd.AddOption ("zoomable", "... {0|1} - set zoom persistence");
+
+ aCmd.Parse (theArgsNb, theArgVec);
+
+ if (aCmd.HasOption ("help"))
+ {
+ theDi.PrintHelp (theArgVec[0]);
+ return 0;
+ }
+
+ ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
+
+ TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
+
+ if (aName.IsEmpty())
+ {
+ std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
+ return 1;
+ }
+
+ // ----------------------------------
+ // detach existing manipulator object
+ // ----------------------------------
+
+ if (aCmd.HasOption ("detach"))
+ {
+ if (!aMapAIS.IsBound2 (aName))
+ {
+ std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
+ return 1;
+ }
+
+ Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
+ if (aManipulator.IsNull())
+ {
+ std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
+ return 1;
+ }
+
+ aManipulator->Detach();
+ aMapAIS.UnBind2 (aName);
+ ViewerTest::GetAISContext()->Remove (aManipulator);
+
+ return 0;
+ }
+
+ // -----------------------------------------------
+ // find or create manipulator if it does not exist
+ // -----------------------------------------------
+
+ Handle(AIS_Manipulator) aManipulator;
+ if (!aMapAIS.IsBound2 (aName))
+ {
+ std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
+
+ aManipulator = new ViewerTest_AISManipulator();
+ aMapAIS.Bind (aManipulator, aName);
+ }
+ else
+ {
+ aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
+ if (aManipulator.IsNull())
+ {
+ std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
+ return 1;
+ }
+ }
+
+ // -----------------------------------------
+ // change properties of manipulator instance
+ // -----------------------------------------
+
+ if (aCmd.HasOption ("autoActivate", 1, Standard_True))
+ {
+ aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
+ }
+ if (aCmd.HasOption ("followTranslation", 1, Standard_True))
+ {
+ aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
+ }
+ if (aCmd.HasOption ("followRotation", 1, Standard_True))
+ {
+ aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
+ }
+ if (aCmd.HasOption ("gap", 1, Standard_True))
+ {
+ aManipulator->SetGap (aCmd.ArgFloat ("gap"));
+ }
+ if (aCmd.HasOption ("part", 3, Standard_True))
+ {
+ Standard_Integer anAxis = aCmd.ArgInt ("part", 0);
+ Standard_Integer aMode = aCmd.ArgInt ("part", 1);
+ Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
+ if (aMode < 1 || aMode > 3)
+ {
+ std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
+ return 1;
+ }
+
+ aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
+ }
+ if (aCmd.HasOption ("pos", 3, Standard_True))
+ {
+ gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
+ gp_Dir aVDir = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
+ gp_Dir aXDir = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
+
+ aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
+ }
+ if (aCmd.HasOption ("size", 1, Standard_True))
+ {
+ aManipulator->SetSize (aCmd.ArgFloat ("size"));
+ }
+ if (aCmd.HasOption ("zoomable", 1, Standard_True))
+ {
+ aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
+
+ if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
+ {
+ ViewerTest::GetAISContext()->Remove (aManipulator, Standard_False);
+ ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
+ }
+ }
+
+ // ---------------------------------------------------
+ // attach, detach or access manipulator from an object
+ // ---------------------------------------------------
+
+ if (aCmd.HasOption ("attach"))
+ {
+ // Find an object and attach manipulator to it
+ if (!aCmd.HasOption ("attach", 1, Standard_True))
+ {
+ return 1;
+ }
+
+ TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
+ if (!aMapAIS.IsBound2 (anObjName))
+ {
+ std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
+ return 1;
+ }
+
+ Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
+ ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
+ for (; anIt.More(); anIt.Next())
+ {
+ if (anIt.Value()->IsAttached()
+ && anIt.Value()->Object() == anObject)
+ {
+ std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
+ return 1;
+ }
+ }
+
+ AIS_Manipulator::OptionsForAttach anOptions;
+ if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
+ {
+ anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
+ }
+ if (aCmd.HasOption ("adjustSize", 1, Standard_True))
+ {
+ anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
+ }
+ if (aCmd.HasOption ("enableModes", 1, Standard_True))
+ {
+ anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
+ }
+
+ aManipulator->Attach (anObject, anOptions);
+ }
+
+ // --------------------------------------
+ // apply transformation using manipulator
+ // --------------------------------------
+
+ if (aCmd.HasOption ("startTransform", 2, Standard_True))
+ {
+ aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
+ }
+ if (aCmd.HasOption ("transform", 2, Standard_True))
+ {
+ aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
+ }
+ if (aCmd.HasOption ("stopTransform"))
+ {
+ Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
+
+ aManipulator->StopTransform (toApply);
+ }
+
+ gp_Trsf aT;
+ if (aCmd.HasOption ("move", 3, Standard_True))
+ {
+ aT.SetTranslationPart (aCmd.ArgVec ("move"));
+ }
+ if (aCmd.HasOption ("rotate", 7, Standard_True))
+ {
+ aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
+ }
+ if (aCmd.HasOption ("scale", 1))
+ {
+ aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
+ }
+
+ if (aT.Form() != gp_Identity)
+ {
+ aManipulator->Transform (aT);
+ }
+
+ ViewerTest::GetAISContext()->Redisplay (aManipulator);
+
+ return 0;
+}
+
//=======================================================================
//function : ViewerCommands
//purpose :
"vxrotate",
__FILE__,VXRotate,group);
+ theCommands.Add("vmanipulator",
+ "\n vmanipulator Name [-attach AISObject | -detach | ...]"
+ "\n tool to create and manage AIS manipulators."
+ "\n Options: "
+ "\n '-attach AISObject' attach manipulator to AISObject"
+ "\n '-adjustPosition {0|1}' adjust position when attaching"
+ "\n '-adjustSize {0|1}' adjust size when attaching"
+ "\n '-enableModes {0|1}' enable modes when attaching"
+ "\n '-detach' detach manipulator"
+ "\n '-startTransform mouse_x mouse_y' - invoke start of transformation"
+ "\n '-transform mouse_x mouse_y' - invoke transformation"
+ "\n '-stopTransform [abort]' - invoke stop of transformation"
+ "\n '-move x y z' - move attached object"
+ "\n '-rotate x y z dx dy dz angle' - rotate attached object"
+ "\n '-scale factor' - scale attached object"
+ "\n '-autoActivate {0|1}' - set activation on detection"
+ "\n '-followTranslation {0|1}' - set following translation transform"
+ "\n '-followRotation {0|1}' - set following rotation transform"
+ "\n '-gap value' - set gap between sub-parts"
+ "\n '-part axis mode {0|1}' - set visual part"
+ "\n '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
+ "\n '-size value' - set size of manipulator"
+ "\n '-zoomable {0|1}' - set zoom persistence",
+ __FILE__, VManipulator, group);
+
#if defined(_WIN32)
theCommands.Add("vprogressive",
"vprogressive",
016 ivtk
017 mesh
018 point_cloud
+019 manipulator
--- /dev/null
+puts "=================================="
+puts "AIS_Manipulator - rotate an object"
+puts "=================================="
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+set anImage3 $imagedir/${casename}_3.png
+set anImage4 $imagedir/${casename}_4.png
+set anImage5 $imagedir/${casename}_5.png
+
+# -------------------------------------
+# create manipulated and helper objects
+# -------------------------------------
+
+pcylinder c1_1 5 10
+pcylinder c1_2 3 10
+pcylinder c2 10 20
+ttranslate c1_1 100 0 20
+ttranslate c1_2 100 0 20
+trotate c1_2 100 0 25 0 1 0 90
+trotate c1_2 100 0 25 0 0 1 10
+ttranslate c2 100 0 0
+
+compound c1_1 c1_2 c1
+
+# ------------------------------------
+# display manipulated objects (test 1)
+# ------------------------------------
+
+vdisplay c1
+vdisplay c2
+vsetdispmode 1
+vaxo
+vfit
+
+# ------------------
+# attach manipulator
+# ------------------
+
+vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1
+
+# ----------------------------------------------------
+# test rotation around x axis (object reference frame)
+# ----------------------------------------------------
+
+vmanipulator m -followRotation 1
+
+set mouse_pick {201 092}
+set mouse_drag {176 142}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage1
+
+# ----------------------------------------------------
+# test rotation around y axis (object reference frame)
+# ----------------------------------------------------
+
+vmanipulator m -followRotation 1
+
+set mouse_pick {173 137}
+set mouse_drag {233 140}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage2
+
+# ----------------------------------------------------
+# test rotation around z axis (object reference frame)
+# ----------------------------------------------------
+
+vmanipulator m -followRotation 1
+
+set mouse_pick {200 094}
+set mouse_drag {182 117}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage3
+
+# ------------------------------------
+# display manipulated objects (test 2)
+# ------------------------------------
+
+vremove -all
+vdisplay c1
+vdisplay c2
+vsetdispmode 1
+vaxo
+vfit
+
+vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1
+vmanipulator m -followRotation 0
+
+# ---------------------------------------------------
+# test rotation around y axis (world reference frame)
+# ---------------------------------------------------
+
+set mouse_pick {211 095}
+set mouse_drag {230 127}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage4
+
+# ---------------------------------------------------
+# test rotation around z axis (world reference frame)
+# ---------------------------------------------------
+
+set mouse_pick {225 143}
+set mouse_drag {184 143}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage5
+
+set to_dump_screen 0
\ No newline at end of file
--- /dev/null
+puts "================================="
+puts "AIS_Manipulator - scale an object"
+puts "================================="
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+
+# -------------------------------------
+# create manipulated and helper objects
+# -------------------------------------
+
+pcylinder c1_1 5 10
+pcylinder c1_2 3 10
+pcylinder c2 10 20
+ttranslate c1_1 100 0 20
+ttranslate c1_2 100 0 20
+trotate c1_2 100 0 25 0 1 0 90
+trotate c1_2 100 0 25 0 0 1 10
+ttranslate c2 100 0 0
+
+compound c1_1 c1_2 c1
+
+# ------------------------------------
+# display manipulated objects (test 1)
+# ------------------------------------
+
+vdisplay c1
+vdisplay c2
+vsetdispmode 1
+vaxo
+vfit
+
+# ------------------
+# attach manipulator
+# ------------------
+
+vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1
+
+# --------------------------
+# test hilight and detection
+# --------------------------
+
+set mouse_pick {229 137}
+
+vmoveto {*}$mouse_pick
+vdump $anImage1
+
+# -------------------------
+# test scaling of an object
+# -------------------------
+
+set mouse_pick {229 137}
+set mouse_drag {210 127}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vdump $anImage2
+
+set to_dump_screen 0
--- /dev/null
+puts "====================================="
+puts "AIS_Manipulator - translate an object"
+puts "====================================="
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+set anImage3 $imagedir/${casename}_3.png
+set anImage4 $imagedir/${casename}_4.png
+set anImage5 $imagedir/${casename}_5.png
+
+# -------------------------------------
+# create manipulated and helper objects
+# -------------------------------------
+
+pcylinder c1 5 10
+pcylinder c2 10 20
+ttranslate c1 100 0 20
+ttranslate c2 100 0 0
+trotate c1 100 0 25 0 1 0 90
+trotate c1 100 0 25 0 0 1 10
+
+# -------------------------------------
+# display manipulated objects (scene 1)
+# -------------------------------------
+
+vdisplay c1
+vdisplay c2
+vsetdispmode 1
+vaxo
+vfit
+
+# ------------------
+# attach manipulator
+# ------------------
+
+vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1
+vmanipulator m -followRotation 1
+vmanipulator m -followTranslation 1
+
+# ----------------------------------------------------
+# test x translation transform (world reference frame)
+# ----------------------------------------------------
+
+set mouse_pick {204 112}
+set mouse_drag {204 156}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage1
+
+# ----------------------------------------------------
+# test y translation transform (world reference frame)
+# ----------------------------------------------------
+
+set mouse_pick {215 160}
+set mouse_drag {265 132}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage2
+
+# ----------------------------------------------------
+# test z translation transform (world reference frame)
+# ----------------------------------------------------
+
+set mouse_pick {263 145}
+set mouse_drag {127 065}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage3
+
+# -------------------------------------
+# display manipulated objects (scene 2)
+# -------------------------------------
+
+vremove -all
+vdisplay c1
+vdisplay c2
+vsetdispmode 1
+vaxo
+vfit
+
+# -------------------------------------------
+# attach manipulator and rotate around z axis
+# -------------------------------------------
+
+vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1
+vmanipulator m -followRotation 1
+vmanipulator m -followTranslation 1
+
+set mouse_pick {223 143}
+set mouse_drag {181 141}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+
+# ----------------------------------------------------
+# test x translation transform (object reference frame)
+# ----------------------------------------------------
+
+set mouse_pick {199 131}
+set mouse_drag {175 168}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage4
+
+# ----------------------------------------------------
+# test y translation transform (object reference frame)
+# ----------------------------------------------------
+
+set mouse_pick {199 164}
+set mouse_drag {246 177}
+
+vmoveto {*}$mouse_pick
+vselect {*}$mouse_pick
+vmanipulator m -startTransform {*}$mouse_pick
+vmanipulator m -transform {*}$mouse_drag
+vmanipulator m -stopTransform
+vselect 0 0
+vmoveto {*}$mouse_drag
+vdump $anImage5
+
+set to_dump_screen 0
\ No newline at end of file
--- /dev/null
+puts "==============================================="
+puts "AIS_Manipulator - check zoom persistence option"
+puts "==============================================="
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+set anImage3 $imagedir/${casename}_3.png
+set anImage4 $imagedir/${casename}_4.png
+set anImage5 $imagedir/${casename}_5.png
+set anImage6 $imagedir/${casename}_6.png
+
+# -------------------------------------
+# create manipulated and helper objects
+# -------------------------------------
+
+box b1 0 0 0 20 20 20
+box b2 80 0 0 20 20 20
+vdisplay b1
+vdisplay b2
+vtrihedron tri
+vsetdispmode 1
+vaxo
+vfit
+
+# --------------------------------------------------------
+# create and test non-zoom persistent manipulator (test 1)
+# --------------------------------------------------------
+
+vmanipulator m1 -attach b1 -adjustPosition 1 -adjustSize 1 -enableModes 1 -zoomable 1
+
+set mouse_pick_1 {84 135}
+set mouse_pick_2 {29 103}
+set mouse_pick_3 {29 103}
+set mouse_drag_3 {121 126}
+
+# pick at default zoom
+vmoveto 0 0
+vmoveto {*}$mouse_pick_1
+vdump $anImage1
+
+# pick at changed zoom
+vzoom 1.5
+vmoveto 0 0
+vmoveto {*}$mouse_pick_2
+vdump $anImage2
+
+# drag object
+vselect {*}$mouse_pick_3
+vmanipulator m1 -startTransform {*}$mouse_pick_3
+vmanipulator m1 -transform {*}$mouse_drag_3
+vmanipulator m1 -stopTransform
+vselect 0 0
+vdump $anImage3
+
+# ----------------------------------------------------
+# create and test zoom persistent manipulator (test 2)
+# ----------------------------------------------------
+
+vfit
+
+vmanipulator m2 -attach b2 -adjustPosition 1 -adjustSize 0 -enableModes 1 -zoomable 0 -size 100
+
+set mouse_pick_1 {341 283}
+set mouse_pick_2 {277 246}
+set mouse_pick_3 {277 246}
+set mouse_drag_3 {210 210}
+
+# pick at default zoom
+vmoveto 0 0
+vmoveto {*}$mouse_pick_1
+vdump $anImage4
+
+# pick at changed zoom
+vzoom 0.5
+vmoveto 0 0
+vmoveto {*}$mouse_pick_2
+vdump $anImage5
+
+# drag object
+vselect {*}$mouse_pick_3
+vmanipulator m2 -startTransform {*}$mouse_pick_3
+vmanipulator m2 -transform {*}$mouse_drag_3
+vmanipulator m2 -stopTransform
+vselect 0 0
+vdump $anImage6
+
+set to_dump_screen 0
\ No newline at end of file