0027038: Visualization - add new presentation for object manipulation
authorapl <apl@opencascade.com>
Fri, 27 May 2016 10:15:40 +0000 (13:15 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 2 Jun 2016 11:23:22 +0000 (14:23 +0300)
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)

23 files changed:
src/AIS/AIS_Manipulator.cxx [new file with mode: 0644]
src/AIS/AIS_Manipulator.hxx [new file with mode: 0644]
src/AIS/AIS_ManipulatorMode.hxx [new file with mode: 0644]
src/AIS/AIS_ManipulatorOwner.cxx [new file with mode: 0644]
src/AIS/AIS_ManipulatorOwner.hxx [new file with mode: 0644]
src/AIS/FILES
src/StdPrs/FILES
src/StdPrs/StdPrs_ToolCylinder.cxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolCylinder.hxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolDisk.cxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolDisk.hxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolQuadric.cxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolQuadric.hxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolSphere.cxx [new file with mode: 0644]
src/StdPrs/StdPrs_ToolSphere.hxx [new file with mode: 0644]
src/ViewerTest/ViewerTest_CmdParser.cxx
src/ViewerTest/ViewerTest_CmdParser.hxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/grids.list
tests/v3d/manipulator/rotate [new file with mode: 0644]
tests/v3d/manipulator/scale [new file with mode: 0644]
tests/v3d/manipulator/translate [new file with mode: 0644]
tests/v3d/manipulator/zoom_persistence [new file with mode: 0644]

diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx
new file mode 100644 (file)
index 0000000..2434229
--- /dev/null
@@ -0,0 +1,1219 @@
+// 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());
+  }
+}
diff --git a/src/AIS/AIS_Manipulator.hxx b/src/AIS/AIS_Manipulator.hxx
new file mode 100644 (file)
index 0000000..15d7c5c
--- /dev/null
@@ -0,0 +1,670 @@
+// 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
diff --git a/src/AIS/AIS_ManipulatorMode.hxx b/src/AIS/AIS_ManipulatorMode.hxx
new file mode 100644 (file)
index 0000000..648876b
--- /dev/null
@@ -0,0 +1,28 @@
+// 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
diff --git a/src/AIS/AIS_ManipulatorOwner.cxx b/src/AIS/AIS_ManipulatorOwner.cxx
new file mode 100644 (file)
index 0000000..dd8e98f
--- /dev/null
@@ -0,0 +1,94 @@
+// 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);
+}
diff --git a/src/AIS/AIS_ManipulatorOwner.hxx b/src/AIS/AIS_ManipulatorOwner.hxx
new file mode 100644 (file)
index 0000000..95b31bb
--- /dev/null
@@ -0,0 +1,60 @@
+// 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
index 2882a7c..c4ea146 100644 (file)
@@ -99,6 +99,11 @@ AIS_LocalContext_1.cxx
 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
index 94ffef1..31829a8 100644 (file)
@@ -21,8 +21,16 @@ StdPrs_ShadedShape.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
diff --git a/src/StdPrs/StdPrs_ToolCylinder.cxx b/src/StdPrs/StdPrs_ToolCylinder.cxx
new file mode 100644 (file)
index 0000000..a2c119c
--- /dev/null
@@ -0,0 +1,64 @@
+// 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());
+}
diff --git a/src/StdPrs/StdPrs_ToolCylinder.hxx b/src/StdPrs/StdPrs_ToolCylinder.hxx
new file mode 100644 (file)
index 0000000..e9c2ca8
--- /dev/null
@@ -0,0 +1,51 @@
+// 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
diff --git a/src/StdPrs/StdPrs_ToolDisk.cxx b/src/StdPrs/StdPrs_ToolDisk.cxx
new file mode 100644 (file)
index 0000000..c5cd1f9
--- /dev/null
@@ -0,0 +1,58 @@
+// 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);
+}
diff --git a/src/StdPrs/StdPrs_ToolDisk.hxx b/src/StdPrs/StdPrs_ToolDisk.hxx
new file mode 100644 (file)
index 0000000..cc30fbc
--- /dev/null
@@ -0,0 +1,50 @@
+// 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
diff --git a/src/StdPrs/StdPrs_ToolQuadric.cxx b/src/StdPrs/StdPrs_ToolQuadric.cxx
new file mode 100644 (file)
index 0000000..f06b1fc
--- /dev/null
@@ -0,0 +1,118 @@
+// 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);
+}
diff --git a/src/StdPrs/StdPrs_ToolQuadric.hxx b/src/StdPrs/StdPrs_ToolQuadric.hxx
new file mode 100644 (file)
index 0000000..264f7bf
--- /dev/null
@@ -0,0 +1,64 @@
+// 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
diff --git a/src/StdPrs/StdPrs_ToolSphere.cxx b/src/StdPrs/StdPrs_ToolSphere.cxx
new file mode 100644 (file)
index 0000000..0489ae7
--- /dev/null
@@ -0,0 +1,59 @@
+// 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));
+}
diff --git a/src/StdPrs/StdPrs_ToolSphere.hxx b/src/StdPrs/StdPrs_ToolSphere.hxx
new file mode 100644 (file)
index 0000000..fad606e
--- /dev/null
@@ -0,0 +1,55 @@
+// 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
index 001f2b6..bc38896 100644 (file)
@@ -175,38 +175,78 @@ std::string ViewerTest_CmdParser::Arg (const std::string& theOptionName, Standar
 //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()));
 }
index 2158a16..d53c942 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <Standard.hxx>
 #include <Graphic3d_Vec.hxx>
+#include <gp_Vec.hxx>
 
 //! Command parser.
 class ViewerTest_CmdParser
@@ -57,17 +58,29 @@ public:
   //! 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:
 
index 9e63f23..96db8d8 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <OpenGl_GlCore20.hxx>
 #include <AIS_ColorScale.hxx>
+#include <AIS_Manipulator.hxx>
 #include <AIS_RubberBand.hxx>
 #include <AIS_Shape.hxx>
 #include <AIS_InteractiveObject.hxx>
@@ -36,6 +37,7 @@
 #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>
@@ -207,6 +209,27 @@ Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
   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
@@ -1912,9 +1935,16 @@ static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
         }
       }
       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);
@@ -1926,44 +1956,77 @@ static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
       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 );
@@ -8786,6 +8849,295 @@ static Standard_Integer VXRotate (Draw_Interpretor& di,
   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  :
@@ -9308,6 +9660,31 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "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",
index 2c20c13..bb50862 100644 (file)
@@ -15,3 +15,4 @@
 016 ivtk
 017 mesh
 018 point_cloud
+019 manipulator
diff --git a/tests/v3d/manipulator/rotate b/tests/v3d/manipulator/rotate
new file mode 100644 (file)
index 0000000..92f67fd
--- /dev/null
@@ -0,0 +1,142 @@
+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
diff --git a/tests/v3d/manipulator/scale b/tests/v3d/manipulator/scale
new file mode 100644 (file)
index 0000000..85ddaa1
--- /dev/null
@@ -0,0 +1,63 @@
+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
diff --git a/tests/v3d/manipulator/translate b/tests/v3d/manipulator/translate
new file mode 100644 (file)
index 0000000..159651e
--- /dev/null
@@ -0,0 +1,150 @@
+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
diff --git a/tests/v3d/manipulator/zoom_persistence b/tests/v3d/manipulator/zoom_persistence
new file mode 100644 (file)
index 0000000..31bc356
--- /dev/null
@@ -0,0 +1,87 @@
+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