Handle(Graphic3d_Camera) aCamera = myView->Camera();
Graphic3d_CameraLerp aCamLerp (myCamStart, myCamEnd);
- aCamLerp.Interpolate (theProgress.LocalNormalized, aCamera);
+ aCamLerp.Interpolate (HasOwnDuration() ? theProgress.LocalNormalized : 1.0, aCamera);
const Standard_Boolean aPrevImmUpdate = myView->SetImmediateUpdate (Standard_False);
myView->SetCamera (aCamera);
//! Return the target view.
const Handle(V3d_View)& View() const { return myView; }
+ //! Set target view.
+ void SetView (const Handle(V3d_View)& theView) { myView = theView; }
+
//! Return camera start position.
const Handle(Graphic3d_Camera)& CameraStart() const { return myCamStart; }
}
}
+//=======================================================================
+//function : LastActiveView
+//purpose :
+//=======================================================================
+Handle(V3d_View) AIS_InteractiveContext::LastActiveView() const
+{
+ if (myLastActiveView == NULL
+ || myMainVwr.IsNull())
+ {
+ return Handle(V3d_View)();
+ }
+
+ // as a precaution - check that myLastActiveView pointer is a valid active View
+ for (V3d_ListOfViewIterator aViewIter = myMainVwr->ActiveViewIterator(); aViewIter.More(); aViewIter.Next())
+ {
+ if (aViewIter.Value() == myLastActiveView)
+ {
+ return aViewIter.Value();
+ }
+ }
+ return Handle(V3d_View)();
+}
+
//=======================================================================
//function : UpdateCurrentViewer
//purpose :
}
//=======================================================================
-//function : FitSelected
-//purpose : Fits the view corresponding to the bounds of selected objects
+//function : BoundingBoxOfSelection
+//purpose :
//=======================================================================
-void AIS_InteractiveContext::FitSelected (const Handle(V3d_View)& theView,
- const Standard_Real theMargin,
- const Standard_Boolean theToUpdate)
+Bnd_Box AIS_InteractiveContext::BoundingBoxOfSelection() const
{
Bnd_Box aBndSelected;
AIS_MapOfObjectOwners anObjectOwnerMap;
aBndSelected.Add (aTmpBox);
}
- anObjectOwnerMap.Clear();
-
- if (aBndSelected.IsVoid())
- return;
+ return aBndSelected;
+}
- theView->FitAll (aBndSelected, theMargin, theToUpdate);
+//=======================================================================
+//function : FitSelected
+//purpose : Fits the view corresponding to the bounds of selected objects
+//=======================================================================
+void AIS_InteractiveContext::FitSelected (const Handle(V3d_View)& theView,
+ const Standard_Real theMargin,
+ const Standard_Boolean theToUpdate)
+{
+ Bnd_Box aBndSelected = BoundingBoxOfSelection();
+ if (!aBndSelected.IsVoid())
+ {
+ theView->FitAll (aBndSelected, theMargin, theToUpdate);
+ }
}
//=======================================================================
const Standard_Integer theMode,
const Standard_Integer theNewSensitivity);
+ //! Returns last active View (argument of MoveTo()/Select() methods).
+ Standard_EXPORT Handle(V3d_View) LastActiveView() const;
+
//! Relays mouse position in pixels theXPix and theYPix to the interactive context selectors.
//! This is done by the view theView passing this position to the main viewer and updating it.
//! If theToRedrawOnUpdate is set to false, callee should call RedrawImmediate() to highlight detected object.
const Handle(V3d_View)& theView,
const Standard_Boolean theToUpdateViewer);
+ //! Returns bounding box of selected objects.
+ Standard_EXPORT Bnd_Box BoundingBoxOfSelection() const;
+
//! Fits the view correspondingly to the bounds of selected objects.
//! Infinite objects are ignored if infinite state of AIS_InteractiveObject is set to true.
Standard_EXPORT void FitSelected (const Handle(V3d_View)& theView,
Handle(PrsMgr_PresentationManager3d) myMainPM;
Handle(V3d_Viewer) myMainVwr;
Handle(StdSelect_ViewerSelector3d) myMainSel;
+ V3d_View* myLastActiveView;
Handle(SelectMgr_EntityOwner) myLastPicked;
Standard_Boolean myToHilightSelected;
Handle(AIS_Selection) mySelection;
myCurDetected = 0;
myCurHighlighted = 0;
myDetectedSeq.Clear();
+ myLastActiveView = theView.get();
// preliminaires
AIS_StatusOfDetection aStatus = AIS_SOD_Nothing;
// all objects detected by the selector are taken, previous current objects are emptied,
// new objects are put...
ClearSelected (Standard_False);
+ myLastActiveView = theView.get();
myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
{
// all objects detected by the selector are taken, previous current objects are emptied,
// new objects are put...
ClearSelected (Standard_False);
+ myLastActiveView = theView.get();
myMainSel->Pick (thePolyline, theView);
for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
{
{
if (!myLastPicked.IsNull())
{
+ Graphic3d_Vec2i aMousePos (-1, -1);
+ if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
+ {
+ aMousePos.SetValues ((Standard_Integer )myMainSel->GetManager().GetMousePosition().X(),
+ (Standard_Integer )myMainSel->GetManager().GetMousePosition().Y());
+ }
+ if (myLastPicked->HandleMouseClick (aMousePos, Aspect_VKeyMouse_LeftButton, Aspect_VKeyFlags_NONE, false))
+ {
+ return AIS_SOP_NothingSelected;
+ }
+
if (myAutoHilight)
{
clearDynamicHighlight();
throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument");
}
+ myLastActiveView = theView.get();
if (myAutoHilight)
{
UnhilightSelected (Standard_False);
throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument");
}
+ myLastActiveView = theView.get();
if (myAutoHilight)
{
UnhilightSelected (Standard_False);
#include "AIS_ViewController.hxx"
+#include <AIS_AnimationCamera.hxx>
#include <AIS_InteractiveContext.hxx>
#include <AIS_Manipulator.hxx>
#include <AIS_Point.hxx>
myThrustSpeed (0.0f),
myHasThrust (false),
//
+ myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
myPrevMoveTo (-1, -1),
myHasHlrOnBeforeRotation (false),
//
return aWalk;
}
+// =======================================================================
+// function : AbortViewAnimation
+// purpose :
+// =======================================================================
+void AIS_ViewController::AbortViewAnimation()
+{
+ if (!myViewAnimation.IsNull()
+ && !myViewAnimation->IsStopped())
+ {
+ myViewAnimation->Stop();
+ myViewAnimation->SetView (Handle(V3d_View)());
+ }
+}
+
// =======================================================================
// function : handlePanning
// purpose :
return;
}
+ AbortViewAnimation();
+
const Handle(Graphic3d_Camera)& aCam = theView->Camera();
if (aCam->IsOrthographic()
|| !hasPanningAnchorPoint())
return;
}
+ AbortViewAnimation();
+
Graphic3d_Vec2i aViewPort;
theView->Window()->Size (aViewPort.x(), aViewPort.y());
Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
return;
}
+ AbortViewAnimation();
+
const Handle(Graphic3d_Camera)& aCam = theView->Camera();
if (thePnt != NULL)
{
return;
}
+ AbortViewAnimation();
if (theToLockZUp)
{
// amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
return;
}
+ AbortViewAnimation();
+
Graphic3d_Vec2i aWinXY;
theView->Window()->Size (aWinXY.x(), aWinXY.y());
double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
{
for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
{
- if (!myGL.Selection.IsXOR)
- {
- theCtx->ClearSelected (false);
- }
-
const bool hadPrevMoveTo = HasPreviousMoveTo();
contextLazyMoveTo (theCtx, theView, aPntIter.Value());
if (!hadPrevMoveTo)
void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
const Handle(V3d_View)& theView)
{
+ // manage animation state
+ if (!myViewAnimation.IsNull()
+ && !myViewAnimation->IsStopped())
+ {
+ myViewAnimation->UpdateTimer();
+ ResetPreviousMoveTo();
+ setAskNextFrame();
+ }
+
for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
{
const Handle(V3d_View)& aView = aViewIter.Value();
#include <Precision.hxx>
#include <Standard_Mutex.hxx>
+class AIS_AnimationCamera;
class AIS_InteractiveObject;
class AIS_InteractiveContext;
class AIS_Point;
//! Return input buffer.
AIS_ViewInputBuffer& ChangeInputBuffer (AIS_ViewInputBufferType theType) { return theType == AIS_ViewInputBufferType_UI ? myUI : myGL; }
+ //! Return view animation; empty (but not NULL) animation by default.
+ const Handle(AIS_AnimationCamera)& ViewAnimation() const { return myViewAnimation; }
+
+ //! Set view animation to be handled within handleViewRedraw().
+ void SetViewAnimation (const Handle(AIS_AnimationCamera)& theAnimation) { myViewAnimation = theAnimation; }
+
+ //! Interrupt active view animation.
+ Standard_EXPORT void AbortViewAnimation();
+
public: //! @name global parameters
//! Return camera rotation mode, AIS_RotationMode_BndBoxActive by default.
Standard_ShortReal myThrustSpeed; //!< active thrust value
Standard_Boolean myHasThrust; //!< flag indicating active thrust
+ Handle(AIS_AnimationCamera) myViewAnimation; //!< view animation
Handle(AIS_RubberBand) myRubberBand; //!< Rubber-band presentation
Handle(AIS_InteractiveObject) myDragObject; //!< currently dragged object
Graphic3d_Vec2i myPrevMoveTo; //!< previous position of MoveTo event in 3D viewer
--- /dev/null
+// Created on: 2017-07-25
+// Created by: Anastasia BOBYLEVA
+// Copyright (c) 2017-2019 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_ViewCube.hxx>
+
+#include <AIS_AnimationCamera.hxx>
+#include <AIS_InteractiveContext.hxx>
+#include <gp_Ax2.hxx>
+#include <Graphic3d_ViewAffinity.hxx>
+#include <NCollection_Lerp.hxx>
+#include <Prs3d.hxx>
+#include <Prs3d_Arrow.hxx>
+#include <Prs3d_DatumAspect.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_Text.hxx>
+#include <Prs3d_ToolDisk.hxx>
+#include <Prs3d_ToolSphere.hxx>
+#include <Select3D_SensitivePrimitiveArray.hxx>
+#include <SelectMgr_SequenceOfOwner.hxx>
+#include <V3d.hxx>
+#include <V3d_View.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCube, AIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCubeOwner, SelectMgr_EntityOwner)
+
+namespace
+{
+ static const Standard_Integer THE_NB_ROUND_SPLITS = 8;
+ static const Standard_Integer THE_NB_DISK_SLICES = 20;
+ static const Standard_Integer THE_NB_ARROW_FACETTES = 20;
+
+ //! Return the number of non-zero components.
+ static Standard_Integer nbDirectionComponents (const gp_Dir& theDir)
+ {
+ Standard_Integer aNbComps = 0;
+ for (Standard_Integer aCompIter = 1; aCompIter <= 3; ++aCompIter)
+ {
+ if (Abs (theDir.Coord (aCompIter)) > gp::Resolution())
+ {
+ ++aNbComps;
+ }
+ }
+ return aNbComps;
+ }
+}
+
+//! Simple sensitive element for picking by point only.
+class AIS_ViewCubeSensitive : public Select3D_SensitivePrimitiveArray
+{
+ DEFINE_STANDARD_RTTI_INLINE(AIS_ViewCubeSensitive, Select3D_SensitivePrimitiveArray)
+public:
+ //! Constructor.
+ AIS_ViewCubeSensitive (const Handle(SelectMgr_EntityOwner)& theOwner,
+ const Handle(Graphic3d_ArrayOfTriangles)& theTris)
+ : Select3D_SensitivePrimitiveArray (theOwner)
+ {
+ InitTriangulation (theTris->Attributes(), theTris->Indices(), TopLoc_Location());
+ }
+
+ //! Checks whether element overlaps current selecting volume.
+ virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
+ SelectBasics_PickResult& thePickResult) Standard_OVERRIDE
+ {
+ return isValidRay (theMgr)
+ && Select3D_SensitivePrimitiveArray::Matches (theMgr, thePickResult);
+ }
+
+ //! Checks if picking ray can be used for detection.
+ bool isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
+ {
+ if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+ {
+ // disallow rectangular selection
+ return false;
+ }
+
+ if (AIS_ViewCubeOwner* anOwner = dynamic_cast<AIS_ViewCubeOwner* >(myOwnerId.get()))
+ {
+ const Standard_Real anAngleToler = 10.0 * M_PI / 180.0;
+ const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt());
+ const gp_Dir aDir = V3d::GetProjAxis (anOwner->MainOrientation());
+ return !aRay.IsNormal (aDir, anAngleToler);
+ }
+ return true;
+ }
+};
+
+//=======================================================================
+//function : IsBoxSide
+//purpose :
+//=======================================================================
+bool AIS_ViewCube::IsBoxSide (V3d_TypeOfOrientation theOrient)
+{
+ return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 1;
+}
+
+//=======================================================================
+//function : IsBoxEdge
+//purpose :
+//=======================================================================
+bool AIS_ViewCube::IsBoxEdge (V3d_TypeOfOrientation theOrient)
+{
+ return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 2;
+}
+
+//=======================================================================
+//function : IsBoxCorner
+//purpose :
+//=======================================================================
+bool AIS_ViewCube::IsBoxCorner (V3d_TypeOfOrientation theOrient)
+{
+ return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 3;
+}
+
+//=======================================================================
+//function : AIS_ViewCube
+//purpose :
+//=======================================================================
+AIS_ViewCube::AIS_ViewCube()
+: myBoxEdgeAspect (new Prs3d_ShadingAspect()),
+ myBoxCornerAspect (new Prs3d_ShadingAspect()),
+ mySize (1.0),
+ myBoxEdgeMinSize (2.0),
+ myBoxEdgeGap (0.0),
+ myBoxFacetExtension (1.0),
+ myAxesPadding (1.0),
+ myCornerMinSize (2.0),
+ myRoundRadius (0.0),
+ myToDisplayAxes (true),
+ myToDisplayEdges (true),
+ myToDisplayVertices (true),
+ myIsYup (false),
+ myViewAnimation (new AIS_AnimationCamera ("AIS_ViewCube", Handle(V3d_View)())),
+ myStartState(new Graphic3d_Camera()),
+ myEndState (new Graphic3d_Camera()),
+ myDuration (0.5),
+ myToAutoStartAnim (true),
+ myIsFixedAnimation (true),
+ myToFitSelected (true),
+ myToResetCameraUp (false)
+{
+ myInfiniteState = true;
+ myIsMutable = true;
+ myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
+ myTransformPersistence = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (100, 100));
+
+ myDrawer->SetTextAspect (new Prs3d_TextAspect());
+ myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+
+ myDynHilightDrawer = new Prs3d_Drawer();
+ myDynHilightDrawer->SetLink (myDrawer);
+ myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+
+ setDefaultAttributes();
+ setDefaultHighlightAttributes();
+
+ // setup default labels
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Front, "FRONT");
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Back, "BACK");
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Top, "TOP");
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Bottom, "BOTTOM");
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Left, "LEFT");
+ myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Right, "RIGHT");
+
+ myAxesLabels.Bind (Prs3d_DP_XAxis, "X");
+ myAxesLabels.Bind (Prs3d_DP_YAxis, "Y");
+ myAxesLabels.Bind (Prs3d_DP_ZAxis, "Z");
+
+ // define default size
+ SetSize (70.0);
+}
+
+//=======================================================================
+//function : setDefaultAttributes
+//purpose :
+//=======================================================================
+void AIS_ViewCube::setDefaultAttributes()
+{
+ myDrawer->TextAspect()->SetHorizontalJustification(Graphic3d_HTA_CENTER);
+ myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_CENTER);
+ myDrawer->TextAspect()->SetColor (Quantity_NOC_BLACK);
+ myDrawer->TextAspect()->SetFont (Font_NOF_SANS_SERIF);
+ myDrawer->TextAspect()->SetHeight (16.0);
+ // this should be forced back-face culling regardless Closed flag
+ myDrawer->TextAspect()->Aspect()->SetSuppressBackFaces (true);
+
+ Graphic3d_MaterialAspect aMat (Graphic3d_NOM_UserDefined);
+ aMat.SetColor (Quantity_NOC_WHITE);
+ aMat.SetAmbientColor (Quantity_NOC_GRAY60);
+
+ const Handle(Graphic3d_AspectFillArea3d)& aShading = myDrawer->ShadingAspect()->Aspect();
+ aShading->SetInteriorStyle (Aspect_IS_SOLID);
+ // this should be forced back-face culling regardless Closed flag
+ aShading->SetSuppressBackFaces (true);
+ aShading->SetInteriorColor (aMat.Color());
+ aShading->SetFrontMaterial (aMat);
+ myDrawer->SetFaceBoundaryDraw (false);
+
+ *myBoxEdgeAspect ->Aspect() = *aShading;
+ myBoxEdgeAspect->SetColor (Quantity_NOC_GRAY30);
+ *myBoxCornerAspect->Aspect() = *aShading;
+ myBoxCornerAspect->SetColor (Quantity_NOC_GRAY30);
+}
+
+//=======================================================================
+//function : setDefaultHighlightAttributes
+//purpose :
+//=======================================================================
+void AIS_ViewCube::setDefaultHighlightAttributes()
+{
+ Graphic3d_MaterialAspect aHighlightMaterial;
+ aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
+ aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
+ aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
+ aHighlightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
+ myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+ myDynHilightDrawer->ShadingAspect()->SetMaterial (aHighlightMaterial);
+ myDynHilightDrawer->ShadingAspect()->SetColor (Quantity_NOC_CYAN1);
+ myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
+ myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
+}
+
+//=======================================================================
+//function : SetYup
+//purpose :
+//=======================================================================
+void AIS_ViewCube::SetYup (Standard_Boolean theIsYup,
+ Standard_Boolean theToUpdateLabels)
+{
+ if (myIsYup == theIsYup)
+ {
+ return;
+ }
+
+ myIsYup = theIsYup;
+
+ static const V3d_TypeOfOrientation THE_ZUP_ORI_LIST[6] =
+ {
+ V3d_TypeOfOrientation_Zup_Front, V3d_TypeOfOrientation_Zup_Back,
+ V3d_TypeOfOrientation_Zup_Top, V3d_TypeOfOrientation_Zup_Bottom,
+ V3d_TypeOfOrientation_Zup_Left, V3d_TypeOfOrientation_Zup_Right
+ };
+ static const V3d_TypeOfOrientation THE_YUP_ORI_LIST[6] =
+ {
+ V3d_TypeOfOrientation_Yup_Front, V3d_TypeOfOrientation_Yup_Back,
+ V3d_TypeOfOrientation_Yup_Top, V3d_TypeOfOrientation_Yup_Bottom,
+ V3d_TypeOfOrientation_Yup_Left, V3d_TypeOfOrientation_Yup_Right
+ };
+ if (theToUpdateLabels)
+ {
+ NCollection_Array1<TCollection_AsciiString> aLabels (0, 5);
+ for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter)
+ {
+ myBoxSideLabels.Find (!myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter],
+ aLabels.ChangeValue (aLabelIter));
+ }
+ for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter)
+ {
+ myBoxSideLabels.Bind (myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter],
+ aLabels.Value (aLabelIter));
+ }
+ }
+
+ SetToUpdate();
+}
+
+//=======================================================================
+//function : ResetStyles
+//purpose :
+//=======================================================================
+void AIS_ViewCube::ResetStyles()
+{
+ UnsetAttributes();
+ UnsetHilightAttributes();
+
+ myBoxEdgeMinSize = 2.0;
+ myCornerMinSize = 2.0;
+ myBoxEdgeGap = 0.0;
+ myRoundRadius = 0.0;
+
+ myToDisplayAxes = true;
+ myToDisplayEdges = true;
+ myToDisplayVertices = true;
+
+ myBoxFacetExtension = 1.0;
+ myAxesPadding = 1.0;
+ SetSize (70.0);
+}
+
+//=======================================================================
+//function : SetSize
+//purpose :
+//=======================================================================
+void AIS_ViewCube::SetSize (Standard_Real theValue,
+ Standard_Boolean theToAdaptAnother)
+{
+ const bool isNewSize = Abs (mySize - theValue) > Precision::Confusion();
+ mySize = theValue;
+ if (theToAdaptAnother)
+ {
+ if (myBoxFacetExtension > 0.0)
+ {
+ SetBoxFacetExtension (mySize * 0.15);
+ }
+ if (myAxesPadding > 0.0)
+ {
+ SetAxesPadding (mySize * 0.1);
+ }
+ SetFontHeight (mySize * 0.16);
+ }
+ if (isNewSize)
+ {
+ SetToUpdate();
+ }
+}
+
+//=======================================================================
+//function : SetRoundRadius
+//purpose :
+//=======================================================================
+void AIS_ViewCube::SetRoundRadius (const Standard_Real theValue)
+{
+ Standard_OutOfRange_Raise_if (theValue < 0.0 || theValue > 0.5,
+ "AIS_ViewCube::SetRoundRadius(): theValue should be in [0; 0.5]");
+ if (Abs (myRoundRadius - theValue) > Precision::Confusion())
+ {
+ myRoundRadius = theValue;
+ SetToUpdate();
+ }
+}
+
+//=======================================================================
+//function : createRoundRectangleTriangles
+//purpose :
+//=======================================================================
+Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createRoundRectangleTriangles (const gp_XY& theSize,
+ Standard_Real theRadius,
+ const gp_Trsf& theTrsf)
+{
+ const Standard_Real aRadius = Min (theRadius, Min (theSize.X(), theSize.Y()) * 0.5);
+ const gp_XY aHSize (theSize.X() * 0.5 - aRadius, theSize.Y() * 0.5 - aRadius);
+ const gp_Dir aNorm = gp::DZ().Transformed (theTrsf);
+ Handle(Graphic3d_ArrayOfTriangles) aTris;
+ if (aRadius > 0.0)
+ {
+ const Standard_Integer aNbNodes = (THE_NB_ROUND_SPLITS + 1) * 4 + 1;
+ aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbNodes * 3, Graphic3d_ArrayFlags_VertexNormal);
+
+ aTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (theTrsf));
+ for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
+ {
+ const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (M_PI * 0.5, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
+ aTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
+ }
+ for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
+ {
+ const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (0.0, -M_PI * 0.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
+ aTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
+ }
+ for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
+ {
+ const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI * 0.5, -M_PI, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
+ aTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
+ }
+ for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
+ {
+ const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI, -M_PI * 1.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
+ aTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
+ }
+
+ // split triangle fan
+ for (Standard_Integer aNodeIter = 2; aNodeIter <= aTris->VertexNumber(); ++aNodeIter)
+ {
+ aTris->AddEdge (1);
+ aTris->AddEdge (aNodeIter - 1);
+ aTris->AddEdge (aNodeIter);
+ }
+ aTris->AddEdge (1);
+ aTris->AddEdge (aTris->VertexNumber());
+ aTris->AddEdge (2);
+ }
+ else
+ {
+ aTris = new Graphic3d_ArrayOfTriangles (4, 6, Graphic3d_ArrayFlags_VertexNormal);
+ aTris->AddVertex (gp_Pnt (-aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
+ aTris->AddVertex (gp_Pnt (-aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
+ aTris->AddVertex (gp_Pnt ( aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf));
+ aTris->AddVertex (gp_Pnt ( aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
+ aTris->AddEdges (3, 1, 2);
+ aTris->AddEdges (1, 3, 4);
+ }
+
+ for (Standard_Integer aVertIter = 1; aVertIter <= aTris->VertexNumber(); ++aVertIter)
+ {
+ aTris->SetVertexNormal (aVertIter, -aNorm);
+ }
+ return aTris;
+}
+
+//=======================================================================
+//function : createBoxPartTriangles
+//purpose :
+//=======================================================================
+Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxPartTriangles (V3d_TypeOfOrientation theDir) const
+{
+ if (IsBoxSide (theDir))
+ {
+ return createBoxSideTriangles (theDir);
+ }
+ else if (IsBoxEdge (theDir)
+ && myToDisplayEdges)
+ {
+ return createBoxEdgeTriangles (theDir);
+ }
+ else if (IsBoxCorner (theDir)
+ && myToDisplayVertices)
+ {
+ return createBoxCornerTriangles (theDir);
+ }
+ return Handle(Graphic3d_ArrayOfTriangles)();
+}
+
+//=======================================================================
+//function : createBoxSideTriangles
+//purpose :
+//=======================================================================
+Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxSideTriangles (V3d_TypeOfOrientation theDirection) const
+{
+ const gp_Dir aDir = V3d::GetProjAxis (theDirection);
+ const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension);
+ const gp_Ax2 aPosition (aPos, aDir.Reversed());
+
+ gp_Ax3 aSystem (aPosition);
+ gp_Trsf aTrsf;
+ aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+ return createRoundRectangleTriangles (gp_XY (mySize, mySize), myRoundRadius * mySize, aTrsf);
+}
+
+//=======================================================================
+//function : createBoxEdgeTriangles
+//purpose :
+//=======================================================================
+Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxEdgeTriangles (V3d_TypeOfOrientation theDirection) const
+{
+ const Standard_Real aThickness = Max (myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() - myBoxEdgeGap, myBoxEdgeMinSize);
+
+ const gp_Dir aDir = V3d::GetProjAxis (theDirection);
+ const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 * gp_XY (1.0, 1.0).Modulus() + myBoxFacetExtension * Cos (M_PI_4));
+ const gp_Ax2 aPosition (aPos, aDir.Reversed());
+
+ gp_Ax3 aSystem (aPosition);
+ gp_Trsf aTrsf;
+ aTrsf.SetTransformation (aSystem, gp_Ax3());
+
+ return createRoundRectangleTriangles (gp_XY (aThickness, mySize), myRoundRadius * mySize, aTrsf);
+}
+
+//=======================================================================
+//function : createBoxCornerTriangles
+//purpose :
+//=======================================================================
+Handle(Graphic3d_ArrayOfTriangles) AIS_ViewCube::createBoxCornerTriangles (V3d_TypeOfOrientation theDir) const
+{
+ const Standard_Real aHSize = mySize * 0.5;
+ const gp_Dir aDir = V3d::GetProjAxis (theDir);
+ const gp_XYZ aHSizeDir = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude());
+ if (myRoundRadius > 0.0)
+ {
+ const Standard_Real anEdgeHWidth = myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() * 0.5;
+ const Standard_Real aHeight = anEdgeHWidth * Sqrt (2.0 / 3.0); // tetrahedron height
+ const gp_Pnt aPos = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude() + aHeight);
+ const gp_Ax2 aPosition (aPos, aDir.Reversed());
+ gp_Ax3 aSystem (aPosition);
+ gp_Trsf aTrsf;
+ aTrsf.SetTransformation (aSystem, gp_Ax3());
+ const Standard_Real aRadius = Max (myBoxFacetExtension * 0.5 / Cos (M_PI_4), myCornerMinSize);
+ return Prs3d_ToolDisk::Create (0.0, aRadius, THE_NB_DISK_SLICES, 1, aTrsf);
+ }
+
+ Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (3, 3, Graphic3d_ArrayFlags_VertexNormal);
+
+ aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (aDir.X(), 0.0, 0.0).XYZ());
+ aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, aDir.Y(), 0.0).XYZ());
+ aTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, 0.0, aDir.Z()).XYZ());
+
+ const gp_XYZ aNode1 = aTris->Vertice (1).XYZ();
+ const gp_XYZ aNode2 = aTris->Vertice (2).XYZ();
+ const gp_XYZ aNode3 = aTris->Vertice (3).XYZ();
+ const gp_XYZ aNormTri = ((aNode2 - aNode1).Crossed (aNode3 - aNode1));
+ if (aNormTri.Dot (aDir.XYZ()) < 0.0)
+ {
+ aTris->AddEdges (1, 3, 2);
+ }
+ else
+ {
+ aTris->AddEdges (1, 2, 3);
+ }
+
+ for (Standard_Integer aVertIter = 1; aVertIter <= aTris->VertexNumber(); ++aVertIter)
+ {
+ aTris->SetVertexNormal (aVertIter, aDir);
+ }
+ return aTris;
+}
+
+//=======================================================================
+//function : Compute
+//purpose :
+//=======================================================================
+void AIS_ViewCube::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ thePrs->SetInfiniteState (true);
+ if (theMode != 0)
+ {
+ return;
+ }
+
+ const gp_Pnt aLocation = (mySize * 0.5 + myBoxFacetExtension + myAxesPadding) * gp_XYZ (-1.0, -1.0, -1.0);
+
+ // Display axes
+ if (myToDisplayAxes)
+ {
+ const Standard_Real anAxisSize = mySize + 2.0 * myBoxFacetExtension + myAxesPadding;
+ const Handle(Prs3d_DatumAspect)& aDatumAspect = myDrawer->DatumAspect();
+ for (Standard_Integer anAxisIter = Prs3d_DP_XAxis; anAxisIter <= Prs3d_DP_ZAxis; ++anAxisIter)
+ {
+ const Prs3d_DatumParts aPart = (Prs3d_DatumParts )anAxisIter;
+ if (!aDatumAspect->DrawDatumPart (aPart))
+ {
+ continue;
+ }
+
+ gp_Ax1 anAx1;
+ switch (aPart)
+ {
+ case Prs3d_DP_XAxis: anAx1 = gp_Ax1 (aLocation, gp::DX()); break;
+ case Prs3d_DP_YAxis: anAx1 = gp_Ax1 (aLocation, gp::DY()); break;
+ case Prs3d_DP_ZAxis: anAx1 = gp_Ax1 (aLocation, gp::DZ()); break;
+ default: break;
+ }
+
+ Handle(Graphic3d_Group) anAxisGroup = thePrs->NewGroup();
+ anAxisGroup->SetGroupPrimitivesAspect (aDatumAspect->ShadingAspect (aPart)->Aspect());
+
+ const Standard_Real anArrowLength = 0.2 * anAxisSize;
+ Handle(Graphic3d_ArrayOfTriangles) aTriangleArray = Prs3d_Arrow::DrawShaded (anAx1, 1.0, anAxisSize, 3.0, anArrowLength, THE_NB_ARROW_FACETTES);
+ anAxisGroup->AddPrimitiveArray (aTriangleArray);
+
+ TCollection_AsciiString anAxisLabel;
+ if (aDatumAspect->ToDrawLabels()
+ && myAxesLabels.Find (aPart, anAxisLabel)
+ && !anAxisLabel.IsEmpty())
+ {
+ Handle(Graphic3d_Group) anAxisLabelGroup = thePrs->NewGroup();
+ gp_Pnt aTextOrigin = anAx1.Location().Translated (gp_Vec (anAx1.Direction().X() * (anAxisSize + anArrowLength),
+ anAx1.Direction().Y() * (anAxisSize + anArrowLength),
+ anAx1.Direction().Z() * (anAxisSize + anArrowLength)));
+ Prs3d_Text::Draw (anAxisLabelGroup, aDatumAspect->TextAspect(), TCollection_ExtendedString (anAxisLabel), aTextOrigin);
+ }
+ }
+
+ // Display center
+ {
+ Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
+ Handle(Prs3d_ShadingAspect) anAspectCen = new Prs3d_ShadingAspect();
+ anAspectCen->SetColor (Quantity_NOC_WHITE);
+ aGroup->SetGroupPrimitivesAspect (anAspectCen->Aspect());
+ Prs3d_ToolSphere aTool (4.0, THE_NB_DISK_SLICES, THE_NB_DISK_SLICES);
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation (gp_Vec (gp::Origin(), aLocation));
+ Handle(Graphic3d_ArrayOfTriangles) aCenterArray;
+ aTool.FillArray (aCenterArray, aTrsf);
+ aGroup->AddPrimitiveArray (aCenterArray);
+ }
+ }
+
+ // Display box
+ {
+ Handle(Graphic3d_Group) aGroupSides = thePrs->NewGroup(), aGroupEdges = thePrs->NewGroup(), aGroupCorners = thePrs->NewGroup();
+ aGroupSides->SetClosed (true); // should be replaced by forced back-face culling aspect
+ aGroupSides->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
+
+ aGroupEdges->SetClosed (true);
+ aGroupEdges->SetGroupPrimitivesAspect (myBoxEdgeAspect->Aspect());
+
+ aGroupCorners->SetClosed (true);
+ aGroupCorners->SetGroupPrimitivesAspect (myBoxCornerAspect->Aspect());
+
+ Handle(Graphic3d_Group) aTextGroup = thePrs->NewGroup();
+ //aTextGroup->SetClosed (true);
+ aTextGroup->SetGroupPrimitivesAspect (myDrawer->TextAspect()->Aspect());
+ for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
+ {
+ const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
+ if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (anOrient))
+ {
+ if (IsBoxSide (anOrient))
+ {
+ aGroupSides->AddPrimitiveArray (aTris);
+
+ TCollection_AsciiString aLabel;
+ if (!myBoxSideLabels.Find (anOrient, aLabel)
+ || aLabel.IsEmpty())
+ {
+ continue;
+ }
+
+ const gp_Dir aDir = V3d::GetProjAxis (anOrient);
+ gp_Dir anUp = myIsYup ? gp::DY() : gp::DZ();
+ if (myIsYup)
+ {
+ if (anOrient == V3d_Ypos
+ || anOrient == V3d_Yneg)
+ {
+ anUp = -gp::DZ();
+ }
+ }
+ else
+ {
+ if (anOrient == V3d_Zpos)
+ {
+ anUp = gp::DY();
+ }
+ else if (anOrient == V3d_Zneg)
+ {
+ anUp = -gp::DY();
+ }
+ }
+
+ const Standard_Real anOffset = 2.0; // extra offset to avoid overlapping with triangulation
+ const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension + anOffset);
+ const gp_Ax2 aPosition (aPos, aDir, anUp.Crossed (aDir));
+ Prs3d_Text::Draw (aTextGroup, myDrawer->TextAspect(), aLabel, aPosition);
+ }
+ else if (IsBoxEdge (anOrient))
+ {
+ aGroupEdges->AddPrimitiveArray (aTris);
+ }
+ else if (IsBoxCorner (anOrient))
+ {
+ aGroupCorners->AddPrimitiveArray (aTris);
+ }
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : ComputeSelection
+//purpose :
+//=======================================================================
+void AIS_ViewCube::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+ const Standard_Integer theMode)
+{
+ if (theMode != 0)
+ {
+ return;
+ }
+
+ for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
+ {
+ const V3d_TypeOfOrientation anOri = (V3d_TypeOfOrientation )aPartIter;
+ if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (anOri))
+ {
+ Standard_Integer aSensitivity = 2;
+ if (IsBoxCorner (anOri))
+ {
+ aSensitivity = 8;
+ }
+ else if (IsBoxEdge (anOri))
+ {
+ aSensitivity = 4;
+ }
+ Handle(AIS_ViewCubeOwner) anOwner = new AIS_ViewCubeOwner (this, anOri);
+ Handle(AIS_ViewCubeSensitive) aTriSens = new AIS_ViewCubeSensitive (anOwner, aTris);
+ aTriSens->SetSensitivityFactor (aSensitivity);
+ theSelection->Add (aTriSens);
+ }
+ }
+}
+
+//=======================================================================
+//function : HasAnimation
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_ViewCube::HasAnimation() const
+{
+ return !myViewAnimation->IsStopped();
+}
+
+//=======================================================================
+//function : StartAnimation
+//purpose :
+//=======================================================================
+void AIS_ViewCube::StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner)
+{
+ Handle(V3d_View) aView = GetContext()->LastActiveView();
+ if (theOwner.IsNull()
+ || aView.IsNull())
+ {
+ return;
+ }
+
+ myStartState->Copy (aView->Camera());
+ myEndState ->Copy (aView->Camera());
+
+ {
+ Handle(Graphic3d_Camera) aBackupCamera = new Graphic3d_Camera (aView->Camera());
+
+ const bool wasImmediateUpdate = aView->SetImmediateUpdate (false);
+ aView->SetCamera (myEndState);
+ aView->SetProj (theOwner->MainOrientation(), myIsYup);
+
+ const gp_Dir aNewDir = aView->Camera()->Direction();
+ if (!myToResetCameraUp
+ && !aNewDir.IsEqual (aBackupCamera->Direction(), Precision::Angular()))
+ {
+ // find the Up direction closest to current instead of default one
+ const gp_Ax1 aNewDirAx1 (gp::Origin(), aNewDir);
+ const gp_Dir anOldUp = aBackupCamera->Up();
+ const gp_Dir anUpList[4] =
+ {
+ aView->Camera()->Up(),
+ aView->Camera()->Up().Rotated (aNewDirAx1, M_PI_2),
+ aView->Camera()->Up().Rotated (aNewDirAx1, M_PI),
+ aView->Camera()->Up().Rotated (aNewDirAx1, M_PI * 1.5),
+ };
+
+ Standard_Real aBestAngle = Precision::Infinite();
+ gp_Dir anUpBest;
+ for (Standard_Integer anUpIter = 0; anUpIter < 4; ++anUpIter)
+ {
+ Standard_Real anAngle = anUpList[anUpIter].Angle (anOldUp);
+ if (aBestAngle > anAngle)
+ {
+ aBestAngle = anAngle;
+ anUpBest = anUpList[anUpIter];
+ }
+ }
+ aView->Camera()->SetUp (anUpBest);
+ }
+
+ const Bnd_Box aBndSelected = myToFitSelected ? GetContext()->BoundingBoxOfSelection() : Bnd_Box();
+ if (!aBndSelected.IsVoid())
+ {
+ aView->FitAll (aBndSelected, 0.01, false);
+ }
+ else
+ {
+ aView->FitAll (0.01, false);
+ }
+ aView->SetCamera (aBackupCamera);
+ aView->SetImmediateUpdate (wasImmediateUpdate);
+ }
+
+ myViewAnimation->SetView (aView);
+ myViewAnimation->SetCameraStart (myStartState);
+ myViewAnimation->SetCameraEnd (myEndState);
+ myViewAnimation->SetOwnDuration (myDuration);
+ myViewAnimation->StartTimer (0.0, 1.0, true, false);
+}
+
+//=======================================================================
+//function : updateAnimation
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_ViewCube::updateAnimation()
+{
+ const Standard_Real aPts = myViewAnimation->UpdateTimer();
+ if (aPts >= myDuration)
+ {
+ myViewAnimation->Stop();
+ onAnimationFinished();
+ myViewAnimation->SetView (Handle(V3d_View)());
+ return Standard_False;
+ }
+ return Standard_True;
+}
+
+//=======================================================================
+//function : UpdateAnimation
+//purpose :
+//=======================================================================
+Standard_Boolean AIS_ViewCube::UpdateAnimation (const Standard_Boolean theToUpdate)
+{
+ Handle(V3d_View) aView = myViewAnimation->View();
+ if (!HasAnimation()
+ || !updateAnimation())
+ {
+ return Standard_False;
+ }
+
+ if (theToUpdate
+ && !aView.IsNull())
+ {
+ aView->IsInvalidated() ? aView->Redraw() : aView->RedrawImmediate();
+ }
+
+ onAfterAnimation();
+ return Standard_True;
+}
+
+//=======================================================================
+//function : HandleClick
+//purpose :
+//=======================================================================
+void AIS_ViewCube::HandleClick (const Handle(AIS_ViewCubeOwner)& theOwner)
+{
+ if (!myToAutoStartAnim)
+ {
+ return;
+ }
+
+ StartAnimation (theOwner);
+ if (!myIsFixedAnimation)
+ {
+ return;
+ }
+ for (; HasAnimation(); )
+ {
+ UpdateAnimation (true);
+ }
+}
+
+//=======================================================================
+//function : HilightOwnerWithColor
+//purpose :
+//=======================================================================
+void AIS_ViewCube::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Drawer)& theStyle,
+ const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+ if (theOwner.IsNull()
+ || !thePrsMgr->IsImmediateModeOn())
+ {
+ return;
+ }
+
+ const Graphic3d_ZLayerId aLayer = theStyle->ZLayer() != Graphic3d_ZLayerId_UNKNOWN ? theStyle->ZLayer() : myDrawer->ZLayer();
+ const AIS_ViewCubeOwner* aCubeOwner = dynamic_cast<AIS_ViewCubeOwner* >(theOwner.get());
+
+ Handle(Prs3d_Presentation) aHiPrs = GetHilightPresentation (thePrsMgr);
+ aHiPrs->Clear();
+ aHiPrs->CStructure()->ViewAffinity = thePrsMgr->StructureManager()->ObjectAffinity (Handle(Standard_Transient)(this));
+ aHiPrs->SetTransformPersistence (TransformPersistence());
+ aHiPrs->SetZLayer (aLayer);
+
+ {
+ Handle(Graphic3d_Group) aGroup = aHiPrs->NewGroup();
+ aGroup->SetGroupPrimitivesAspect (theStyle->ShadingAspect()->Aspect());
+ if (Handle(Graphic3d_ArrayOfTriangles) aTris = createBoxPartTriangles (aCubeOwner->MainOrientation()))
+ {
+ aGroup->AddPrimitiveArray (aTris);
+ }
+ }
+
+ if (thePrsMgr->IsImmediateModeOn())
+ {
+ thePrsMgr->AddToImmediateList (aHiPrs);
+ }
+}
+
+//=======================================================================
+//function : HilightSelected
+//purpose :
+//=======================================================================
+void AIS_ViewCube::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& ,
+ const SelectMgr_SequenceOfOwner& theSeq)
+{
+ // this method should never be called since AIS_InteractiveObject::HandleClick() has been overridden
+ if (theSeq.Size() == 1)
+ {
+ //HandleClick (Handle(AIS_ViewCubeOwner)::DownCast (theSeq.First()));
+ }
+}
--- /dev/null
+// Created on: 2017-07-25
+// Created by: Anastasia BOBYLEVA
+// Copyright (c) 2017-2019 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_ViewCube_HeaderFile
+#define _AIS_ViewCube_HeaderFile
+
+#include <AIS_InteractiveObject.hxx>
+#include <Graphic3d_Camera.hxx>
+#include <Graphic3d_Vec2.hxx>
+#include <Prs3d_DatumParts.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <Prs3d_TextAspect.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <V3d_TypeOfOrientation.hxx>
+
+class AIS_AnimationCamera;
+class AIS_ViewCubeOwner;
+class Graphic3d_ArrayOfTriangles;
+
+//! Interactive object for displaying the view manipulation cube.
+//!
+//! View cube consists of several parts that are responsible for different camera manipulations:
+//! @li Cube sides represent main views: top, bottom, left, right, front and back.
+//! @li Edges represent rotation of one of main views on 45 degrees.
+//! @li Vertices represent rotation of one of man views in two directions.
+//!
+//! The object is expected to behave like a trihedron in the view corner,
+//! therefore its position should be defined using transformation persistence flags:
+//! @code SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (100, 100)); @endcode
+//!
+//! View Cube parts are sensitive to detection, or dynamic highlighting (but not selection),
+//! and every its owner AIS_ViewCubeOwner corresponds to camera transformation.
+//! @code
+//! for (aViewCube->StartAnimation (aDetectedOwner); aViewCube->HasAnimation(); )
+//! {
+//! aViewCube->UpdateAnimation();
+//! ... // updating of application window
+//! }
+//! @endcode
+//! or
+//! @code aViewCube->HandleClick (aDetectedOwner); @endcode
+//! that includes transformation loop.
+//! This loop allows external actions like application updating. For this purpose AIS_ViewCube has virtual interface onAfterAnimation(),
+//! that is to be redefined on application level.
+class AIS_ViewCube : public AIS_InteractiveObject
+{
+ DEFINE_STANDARD_RTTIEXT(AIS_ViewCube, AIS_InteractiveObject)
+public:
+
+ //! Return TRUE if specified orientation belongs to box side.
+ Standard_EXPORT static bool IsBoxSide (V3d_TypeOfOrientation theOrient);
+
+ //! Return TRUE if specified orientation belongs to box edge.
+ Standard_EXPORT static bool IsBoxEdge (V3d_TypeOfOrientation theOrient);
+
+ //! Return TRUE if specified orientation belongs to box corner (vertex).
+ Standard_EXPORT static bool IsBoxCorner (V3d_TypeOfOrientation theOrient);
+
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT AIS_ViewCube();
+
+ //! Return view animation.
+ const Handle(AIS_AnimationCamera)& ViewAnimation() const { return myViewAnimation; }
+
+ //! Set view animation.
+ void SetViewAnimation (const Handle(AIS_AnimationCamera)& theAnimation) { myViewAnimation = theAnimation; }
+
+ //! Return TRUE if automatic camera transformation on selection (highlighting) is enabled; TRUE by default.
+ Standard_Boolean ToAutoStartAnimation() const { return myToAutoStartAnim; }
+
+ //! Enable/disable automatic camera transformation on selection (highlighting).
+ //! The automatic logic can be disabled if application wants performing action manually
+ //! basing on picking results (AIS_ViewCubeOwner).
+ void SetAutoStartAnimation (bool theToEnable) { myToAutoStartAnim = theToEnable; }
+
+ //! Return TRUE if camera animation should be done in uninterruptible loop; TRUE by default.
+ Standard_Boolean IsFixedAnimationLoop() const { return myIsFixedAnimation; }
+
+ //! Set if camera animation should be done in uninterruptible loop.
+ void SetFixedAnimationLoop (bool theToEnable) { myIsFixedAnimation = theToEnable; }
+
+ //! Reset all size and style parameters to default.
+ //! @warning It doesn't reset position of View Cube
+ Standard_EXPORT void ResetStyles();
+
+protected:
+
+ //! Set default visual attributes
+ Standard_EXPORT void setDefaultAttributes();
+
+ //! Set default dynamic highlight properties
+ Standard_EXPORT void setDefaultHighlightAttributes();
+
+public: //! @name Geometry management API
+
+ //! @return size (width and height) of View cube sides; 100 by default.
+ Standard_Real Size() const { return mySize; }
+
+ //! Sets size (width and height) of View cube sides.
+ //! @param theToAdaptAnother if TRUE, then other parameters will be adapted to specified size
+ Standard_EXPORT void SetSize (Standard_Real theValue,
+ Standard_Boolean theToAdaptAnother = true);
+
+ //! Return box facet extension to edge/corner facet split; 10 by default.
+ Standard_Real BoxFacetExtension() const { return myBoxFacetExtension; }
+
+ //! Set new value of box facet extension.
+ void SetBoxFacetExtension (Standard_Real theValue)
+ {
+ if (Abs (myBoxFacetExtension - theValue) > Precision::Confusion())
+ {
+ myBoxFacetExtension = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return padding between axes and 3D part (box); 10 by default.
+ Standard_Real AxesPadding() const { return myAxesPadding; }
+
+ //! Set new value of padding between axes and 3D part (box).
+ void SetAxesPadding (Standard_Real theValue)
+ {
+ if (Abs (myAxesPadding - theValue) > Precision::Confusion())
+ {
+ myAxesPadding = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return gap between box edges and box sides; 0 by default.
+ Standard_Real BoxEdgeGap() const { return myBoxEdgeGap; }
+
+ //! Set new value of box edges gap.
+ void SetBoxEdgeGap (Standard_Real theValue)
+ {
+ if (Abs (myBoxEdgeGap - theValue) > Precision::Confusion())
+ {
+ myBoxEdgeGap = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return minimal size of box edge; 2 by default.
+ Standard_Real BoxEdgeMinSize() const { return myBoxEdgeMinSize; }
+
+ //! Set new value of box edge minimal size.
+ void SetBoxEdgeMinSize (Standard_Real theValue)
+ {
+ if (Abs (myBoxEdgeMinSize - theValue) > Precision::Confusion())
+ {
+ myBoxEdgeMinSize = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return minimal size of box corner; 2 by default.
+ Standard_Real BoxCornerMinSize() const { return myCornerMinSize; }
+
+ //! Set new value of box corner minimal size.
+ void SetBoxCornerMinSize (Standard_Real theValue)
+ {
+ if (Abs (myCornerMinSize - theValue) > Precision::Confusion())
+ {
+ myCornerMinSize = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return relative radius of side corners (round rectangle); 0.0 by default.
+ //! The value in within [0, 0.5] range meaning absolute radius = RoundRadius() / Size().
+ Standard_Real RoundRadius() const { return myRoundRadius; }
+
+ //! Set relative radius of View Cube sides corners (round rectangle).
+ //! The value should be within [0, 0.5] range.
+ Standard_EXPORT void SetRoundRadius (const Standard_Real theValue);
+
+ //! @return TRUE if trihedron is drawn; TRUE by default.
+ Standard_Boolean ToDrawAxes() const { return myToDisplayAxes; }
+
+ //! Enable/disable drawing of trihedron.
+ void SetDrawAxes (Standard_Boolean theValue)
+ {
+ if (myToDisplayAxes != theValue)
+ {
+ myToDisplayAxes = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! @return TRUE if edges of View Cube is drawn; TRUE by default.
+ Standard_Boolean ToDrawEdges() const { return myToDisplayEdges; }
+
+ //! Enable/disable drawing of edges of View Cube.
+ void SetDrawEdges (Standard_Boolean theValue)
+ {
+ if (myToDisplayEdges != theValue)
+ {
+ myToDisplayEdges = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return TRUE if vertices (vertex) of View Cube is drawn; TRUE by default.
+ Standard_Boolean ToDrawVertices() const { return myToDisplayVertices; }
+
+ //! Enable/disable drawing of vertices (corners) of View Cube.
+ void SetDrawVertices (Standard_Boolean theValue)
+ {
+ if (myToDisplayVertices != theValue)
+ {
+ myToDisplayVertices = theValue;
+ SetToUpdate();
+ }
+ }
+
+ //! Return TRUE if application expects Y-up viewer orientation instead of Z-up; FALSE by default.
+ Standard_Boolean IsYup() const { return myIsYup; }
+
+ //! Set if application expects Y-up viewer orientation instead of Z-up.
+ Standard_EXPORT void SetYup (Standard_Boolean theIsYup,
+ Standard_Boolean theToUpdateLabels = Standard_True);
+
+public: //! @name Style management API
+
+ //! Return shading style of box sides.
+ const Handle(Prs3d_ShadingAspect)& BoxSideStyle() const { return myDrawer->ShadingAspect(); }
+
+ //! Return shading style of box edges.
+ const Handle(Prs3d_ShadingAspect)& BoxEdgeStyle() const { return myBoxEdgeAspect; }
+
+ //! Return shading style of box corners.
+ const Handle(Prs3d_ShadingAspect)& BoxCornerStyle() const { return myBoxCornerAspect; }
+
+ //! Return value of front color for the 3D part of object.
+ const Quantity_Color& BoxColor() const { return myDrawer->ShadingAspect()->Color(); }
+
+ //! Set new value of front color for the 3D part of object.
+ //! @param theColor [in] input color value.
+ void SetBoxColor (const Quantity_Color& theColor)
+ {
+ if (!myDrawer->ShadingAspect()->Color().IsEqual (theColor)
+ || !myBoxEdgeAspect ->Color().IsEqual (theColor)
+ || !myBoxCornerAspect->Color().IsEqual (theColor))
+ {
+ myDrawer->ShadingAspect()->SetColor (theColor);
+ myBoxEdgeAspect->SetColor (theColor);
+ myBoxCornerAspect->SetColor (theColor);
+ SynchronizeAspects();
+ }
+ }
+
+ //! Return transparency for 3D part of object.
+ Standard_Real BoxTransparency() const { return myDrawer->ShadingAspect()->Transparency(); }
+
+ //! Set new value of transparency for 3D part of object.
+ //! @param theValue [in] input transparency value
+ void SetBoxTransparency (Standard_Real theValue)
+ {
+ if (Abs (myDrawer->ShadingAspect()->Transparency() - theValue) > Precision::Confusion()
+ || Abs (myBoxEdgeAspect ->Transparency() - theValue) > Precision::Confusion()
+ || Abs (myBoxCornerAspect->Transparency() - theValue) > Precision::Confusion())
+ {
+ myDrawer->ShadingAspect()->SetTransparency (theValue);
+ myBoxEdgeAspect->SetTransparency (theValue);
+ myBoxCornerAspect->SetTransparency (theValue);
+ SynchronizeAspects();
+ }
+ }
+
+ //! Return color of sides back material.
+ const Quantity_Color& InnerColor() const { return myDrawer->ShadingAspect()->Color (Aspect_TOFM_BACK_SIDE); }
+
+ //! Set color of sides back material. Alias for:
+ //! @code Attributes()->ShadingAspect()->Aspect()->ChangeBackMaterial().SetColor() @endcode
+ void SetInnerColor (const Quantity_Color& theColor)
+ {
+ myDrawer->ShadingAspect()->SetColor (theColor, Aspect_TOFM_BACK_SIDE);
+ SynchronizeAspects();
+ }
+
+ //! Return box side label or empty string if undefined.
+ //! Default labels: FRONT, BACK, LEFT, RIGHT, TOP, BOTTOM.
+ TCollection_AsciiString BoxSideLabel (V3d_TypeOfOrientation theSide) const
+ {
+ const TCollection_AsciiString* aLabel = myBoxSideLabels.Seek (theSide);
+ return aLabel != NULL ? *aLabel : TCollection_AsciiString();
+ }
+
+ //! Set box side label.
+ void SetBoxSideLabel (const V3d_TypeOfOrientation theSide,
+ const TCollection_AsciiString& theLabel)
+ {
+ if (!IsBoxSide (theSide))
+ {
+ throw Standard_ProgramError ("AIS_ViewCube::SetBoxSideLabel(), invalid enumeration value");
+ }
+ myBoxSideLabels.Bind (theSide, theLabel);
+ SetToUpdate();
+ }
+
+ //! Return text color of labels of box sides; BLACK by default.
+ const Quantity_Color& TextColor() const { return myDrawer->TextAspect()->Aspect()->Color(); }
+
+ //! Set color of text labels on box sides. Alias for:
+ //! @code Attributes()->TextAspect()->SetColor() @endcode
+ void SetTextColor (const Quantity_Color& theColor)
+ {
+ myDrawer->TextAspect()->SetColor (theColor);
+ SynchronizeAspects();
+ }
+
+ //! Return font name that is used for displaying of sides and axes text. Alias for:
+ //! @code Attributes()->TextAspect()->Aspect()->SetFont() @endcode
+ const TCollection_AsciiString& Font() const { return myDrawer->TextAspect()->Aspect()->Font(); }
+
+ //! Set font name that is used for displaying of sides and axes text. Alias for:
+ //! @code Attributes()->TextAspect()->SetFont() @endcode
+ void SetFont (const TCollection_AsciiString& theFont)
+ {
+ myDrawer->TextAspect()->Aspect()->SetFont (theFont);
+ SynchronizeAspects();
+ }
+
+ //! Return height of font
+ Standard_Real FontHeight() const { return myDrawer->TextAspect()->Height(); }
+
+ //! Change font height. Alias for:
+ //! @code Attributes()->TextAspect()->SetHeight() @endcode
+ void SetFontHeight (Standard_Real theValue)
+ {
+ if (Abs (myDrawer->TextAspect()->Height() - theValue) > Precision::Confusion())
+ {
+ myDrawer->TextAspect()->SetHeight (theValue);
+ SetToUpdate();
+ }
+ }
+
+ //! Return axes labels or empty string if undefined.
+ //! Default labels: X, Y, Z.
+ TCollection_AsciiString AxisLabel (Prs3d_DatumParts theAxis) const
+ {
+ const TCollection_AsciiString* aLabel = myAxesLabels.Seek (theAxis);
+ return aLabel != NULL ? *aLabel : TCollection_AsciiString();
+ }
+
+ //! Set axes labels.
+ void SetAxesLabels (const TCollection_AsciiString& theX,
+ const TCollection_AsciiString& theY,
+ const TCollection_AsciiString& theZ)
+ {
+ myAxesLabels.Bind (Prs3d_DP_XAxis, theX);
+ myAxesLabels.Bind (Prs3d_DP_YAxis, theY);
+ myAxesLabels.Bind (Prs3d_DP_ZAxis, theZ);
+ SetToUpdate();
+ }
+
+public:
+
+ //! Set new value of color for the whole object.
+ //! @param theColor [in] input color value.
+ virtual void SetColor (const Quantity_Color& theColor) Standard_OVERRIDE
+ {
+ SetBoxColor (theColor);
+ }
+
+ //! Reset color for the whole object.
+ virtual void UnsetColor() Standard_OVERRIDE
+ {
+ myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE);
+ myBoxEdgeAspect ->SetColor (Quantity_NOC_GRAY30);
+ myBoxCornerAspect->SetColor (Quantity_NOC_GRAY30);
+ SynchronizeAspects();
+ }
+
+ //! Set new value of transparency for the whole object.
+ //! @param theValue [in] input transparency value.
+ virtual void SetTransparency (const Standard_Real theValue) Standard_OVERRIDE
+ {
+ SetBoxTransparency (theValue);
+ }
+
+ //! Reset transparency for the whole object.
+ virtual void UnsetTransparency() Standard_OVERRIDE
+ {
+ SetBoxTransparency (0.0f);
+ }
+
+ //! Sets the material for the interactive object.
+ virtual void SetMaterial (const Graphic3d_MaterialAspect& theMat) Standard_OVERRIDE
+ {
+ myDrawer->ShadingAspect()->SetMaterial (theMat);
+ myBoxEdgeAspect ->SetMaterial (theMat);
+ myBoxCornerAspect->SetMaterial (theMat);
+ SynchronizeAspects();
+ }
+
+ //! Sets the material for the interactive object.
+ virtual void UnsetMaterial() Standard_OVERRIDE
+ {
+ Graphic3d_MaterialAspect aMat (Graphic3d_NOM_UserDefined);
+ aMat.SetColor (Quantity_NOC_WHITE);
+ aMat.SetAmbientColor (Quantity_NOC_GRAY60);
+ myDrawer->ShadingAspect()->SetMaterial (aMat);
+ myBoxEdgeAspect ->SetMaterial (aMat);
+ myBoxEdgeAspect ->SetColor (Quantity_NOC_GRAY30);
+ myBoxCornerAspect->SetMaterial (aMat);
+ myBoxCornerAspect->SetColor (Quantity_NOC_GRAY30);
+ SynchronizeAspects();
+ }
+
+public: //! @name animation methods
+
+ //! Return duration of animation in seconds; 0.5 sec by default
+ Standard_Real Duration() const { return myDuration; }
+
+ //! Set duration of animation.
+ //! @param theValue [in] input value of duration in seconds
+ void SetDuration (Standard_Real theValue) { myDuration = theValue; }
+
+ //! Return TRUE if new camera Up direction should be always set to default value for a new camera Direction; FALSE by default.
+ //! When this flag is FALSE, the new camera Up will be set as current Up orthogonalized to the new camera Direction,
+ //! and will set to default Up on second click.
+ Standard_Boolean ToResetCameraUp() const { return myToResetCameraUp; }
+
+ //! Set if new camera Up direction should be always set to default value for a new camera Direction.
+ void SetResetCamera (Standard_Boolean theToReset) { myToResetCameraUp = theToReset; }
+
+ //! Return TRUE if animation should fit selected objects and FALSE to fit entire scene; TRUE by default.
+ Standard_Boolean ToFitSelected() const { return myToFitSelected; }
+
+ //! Set if animation should fit selected objects or to fit entire scene.
+ void SetFitSelected (Standard_Boolean theToFitSelected) { myToFitSelected = theToFitSelected; }
+
+ //! @return TRUE if View Cube has unfinished animation of view camera.
+ Standard_EXPORT Standard_Boolean HasAnimation() const;
+
+ //! Start camera transformation corresponding to the input detected owner.
+ //! @param theOwner [in] detected owner.
+ Standard_EXPORT virtual void StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner);
+
+ //! Perform one step of current camera transformation.
+ //! theToUpdate [in] enable/disable update of view.
+ //! @return TRUE if animation is not stopped.
+ Standard_EXPORT virtual Standard_Boolean UpdateAnimation (const Standard_Boolean theToUpdate);
+
+ //! Perform camera transformation corresponding to the input detected owner.
+ Standard_EXPORT virtual void HandleClick (const Handle(AIS_ViewCubeOwner)& theOwner);
+
+protected:
+
+ //! Perform internal single step of animation.
+ //! @return FALSE if animation has been finished
+ Standard_EXPORT Standard_Boolean updateAnimation();
+
+protected: //! @name protected virtual API
+
+ //! Method that is called after one step of transformation.
+ virtual void onAfterAnimation() {}
+
+ //! Method that is called after transformation finish.
+ virtual void onAnimationFinished() {}
+
+public: //! @name Presentation computation
+
+ //! Return TRUE for supported display mode.
+ virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; }
+
+ //! Global selection has no meaning for this class.
+ virtual Handle(SelectMgr_EntityOwner) GlobalSelOwner() const Standard_OVERRIDE { return Handle(SelectMgr_EntityOwner)(); }
+
+ //! Compute 3D part of View Cube.
+ //! @param thePrsMgr [in] presentation manager.
+ //! @param thePrs [in] input presentation that is to be filled with flat presentation primitives.
+ //! @param theMode [in] display mode.
+ //! @warning this object accept only 0 display mode.
+ Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode = 0) Standard_OVERRIDE;
+
+ //! Redefine computing of sensitive entities for View Cube.
+ //! @param theSelection [in] input selection object that is to be filled with sensitive entities.
+ //! @param theMode [in] selection mode.
+ //! @warning object accepts only 0 selection 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() overridden methods.
+ virtual Standard_Boolean IsAutoHilight() const Standard_OVERRIDE { return Standard_False; }
+
+ //! Method which clear all selected owners belonging to this selectable object.
+ //! @warning this object does not support selection.
+ virtual void ClearSelected() Standard_OVERRIDE {}
+
+ //! Method which highlights input owner belonging to this selectable object.
+ //! @param thePM [in] presentation manager
+ //! @param theStyle [in] style for dynamic highlighting.
+ //! @param theOwner [in] input entity owner.
+ Standard_EXPORT virtual void HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
+ const Handle(Prs3d_Drawer)& theStyle,
+ const Handle(SelectMgr_EntityOwner)& theOwner) Standard_OVERRIDE;
+
+ //! Method which draws selected owners.
+ Standard_EXPORT virtual void HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
+ const SelectMgr_SequenceOfOwner& theSeq) Standard_OVERRIDE;
+
+ //! Set default parameters for visual attributes
+ //! @sa Attributes()
+ virtual void UnsetAttributes() Standard_OVERRIDE
+ {
+ setDefaultAttributes();
+ SetToUpdate();
+ }
+
+ //! Set default parameters for dynamic highlighting attributes, reset highlight attributes
+ virtual void UnsetHilightAttributes() Standard_OVERRIDE
+ {
+ myHilightDrawer.Nullify();
+ setDefaultHighlightAttributes();
+ SetToUpdate();
+ }
+
+protected: //! @name Auxiliary classes to fill presentation with proper primitives
+
+ //! Create triangulation for a box part - for presentation and selection purposes.
+ Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxPartTriangles (V3d_TypeOfOrientation theDir) const;
+
+ //! Create triangulation for a box side.
+ Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxSideTriangles (V3d_TypeOfOrientation theDir) const;
+
+ //! Create triangulation for a box edge.
+ Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxEdgeTriangles (V3d_TypeOfOrientation theDir) const;
+
+ //! Create triangulation for a box corner (vertex).
+ Standard_EXPORT virtual Handle(Graphic3d_ArrayOfTriangles) createBoxCornerTriangles (V3d_TypeOfOrientation theDir) const;
+
+protected:
+
+ //! Create triangulation for a rectangle with round corners.
+ //! @param theSize rectangle dimensions
+ //! @param theRadius radius at corners
+ //! @param theTrsf transformation
+ Standard_EXPORT static Handle(Graphic3d_ArrayOfTriangles) createRoundRectangleTriangles (const gp_XY& theSize,
+ Standard_Real theRadius,
+ const gp_Trsf& theTrsf);
+
+protected:
+
+ //! Trivial hasher to avoid ambiguity with enumeration type.
+ struct IntegerHasher
+ {
+ static Standard_Integer HashCode (Standard_Integer theValue, Standard_Integer theUpper) { return ::HashCode (theValue, theUpper); }
+ static Standard_Boolean IsEqual (Standard_Integer theA, Standard_Integer theB) { return theA == theB; }
+ };
+
+protected:
+
+ NCollection_DataMap<V3d_TypeOfOrientation, TCollection_AsciiString, IntegerHasher>
+ myBoxSideLabels; //!< map with box side labels
+ NCollection_DataMap<Prs3d_DatumParts, TCollection_AsciiString, IntegerHasher>
+ myAxesLabels; //!< map with axes labels
+ Handle(Prs3d_ShadingAspect) myBoxEdgeAspect; //!< style for box edges
+ Handle(Prs3d_ShadingAspect) myBoxCornerAspect; //!< style for box corner
+
+ Standard_Real mySize; //!< size of box side, length of one axis
+ Standard_Real myBoxEdgeMinSize; //!< minimal size of box edge
+ Standard_Real myBoxEdgeGap; //!< gap between box side and box edge
+ Standard_Real myBoxFacetExtension; //!< box facet extension
+ Standard_Real myAxesPadding; //!< Padding between box and axes
+ Standard_Real myCornerMinSize; //!< minimal size of box corner
+ Standard_Real myRoundRadius; //!< relative round radius within [0; 0.5] range
+ Standard_Boolean myToDisplayAxes; //!< trihedron visibility
+ Standard_Boolean myToDisplayEdges; //!< box edges visibility
+ Standard_Boolean myToDisplayVertices; //!< box corners (vertices) visibility
+ Standard_Boolean myIsYup; //!< flag indicating that application expects Y-up viewer orientation instead of Z-up
+
+protected: //! @name Animation options
+
+ Handle(AIS_AnimationCamera) myViewAnimation; //!< Camera animation object
+ Handle(Graphic3d_Camera) myStartState; //!< Start state of view camera
+ Handle(Graphic3d_Camera) myEndState; //!< End state of view camera
+ Standard_Real myDuration; //!< Duration of animation. By default it is half a second
+ Standard_Boolean myToAutoStartAnim; //!< start animation automatically on click
+ Standard_Boolean myIsFixedAnimation; //!< fixed-loop animation
+ Standard_Boolean myToFitSelected; //!< fit selected or fit entire scene
+ Standard_Boolean myToResetCameraUp; //!< always reset camera up direction to default
+
+};
+
+//! Redefined entity owner that is highlighted when owner is detected,
+//! even if Interactive Context highlighted on last detection procedure.
+class AIS_ViewCubeOwner : public SelectMgr_EntityOwner
+{
+ DEFINE_STANDARD_RTTIEXT(AIS_ViewCubeOwner, SelectMgr_EntityOwner)
+public:
+
+ //! Main constructor.
+ AIS_ViewCubeOwner (const Handle(AIS_ViewCube)& theObject,
+ V3d_TypeOfOrientation theOrient,
+ Standard_Integer thePriority = 5)
+ : SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)& )theObject, thePriority),
+ myMainOrient (theOrient)
+ {
+ myFromDecomposition = true;
+ }
+
+ //! @return TRUE. This owner will always call method
+ //! Hilight for its Selectable Object when the owner is detected.
+ virtual Standard_Boolean IsForcedHilight() const Standard_OVERRIDE { return Standard_True; }
+
+ //! Return new orientation to set.
+ V3d_TypeOfOrientation MainOrientation() const { return myMainOrient; }
+
+ //! Handle mouse button click event.
+ virtual Standard_Boolean HandleMouseClick (const Graphic3d_Vec2i& thePoint,
+ Aspect_VKeyMouse theButton,
+ Aspect_VKeyFlags theModifiers,
+ bool theIsDoubleClick) Standard_OVERRIDE
+ {
+ (void )thePoint; (void )theButton; (void )theModifiers; (void )theIsDoubleClick;
+ AIS_ViewCube* aCubePrs = dynamic_cast<AIS_ViewCube* >(mySelectable);
+ aCubePrs->HandleClick (this);
+ return Standard_True;
+ }
+
+protected:
+
+ V3d_TypeOfOrientation myMainOrient; //!< new orientation to set
+
+};
+
+#endif // _AIS_ViewCube_HeaderFile
AIS_ViewController.cxx
AIS_ViewController.hxx
AIS_ViewInputBuffer.hxx
+AIS_ViewCube.cxx
+AIS_ViewCube.hxx
AIS_WalkDelta.hxx
Colors[Graphic3d_TOR_SPECULAR] = Quantity_Color (Graphic3d_Vec3 (0.970f, 0.970f, 0.970f));
break;
case Graphic3d_NOM_UserDefined:
+ MaterialType = Graphic3d_MATERIAL_PHYSIC;
+ ColorCoef[Graphic3d_TOR_AMBIENT] = 1.00f;
+ ColorCoef[Graphic3d_TOR_DIFFUSE] = 1.00f;
+ ColorCoef[Graphic3d_TOR_SPECULAR] = 1.00f;
+ ColorCoef[Graphic3d_TOR_EMISSION] = 1.00f;
+ Colors[Graphic3d_TOR_AMBIENT] = Quantity_Color (Graphic3d_Vec3 (0.1f, 0.1f, 0.1f));
+ Colors[Graphic3d_TOR_DIFFUSE] = Quantity_Color (Graphic3d_Vec3 (0.8f, 0.8f, 0.8f));
+ Colors[Graphic3d_TOR_SPECULAR] = Quantity_Color (Graphic3d_Vec3 (0.2f, 0.2f, 0.2f));
+ Colors[Graphic3d_TOR_EMISSION] = Quantity_Color (Graphic3d_Vec3 (0.0f, 0.0f, 0.0f));
break;
case Graphic3d_NOM_DEFAULT:
break;
//! Returns the right-handed coordinate system set in SetComponent.
Standard_EXPORT Handle(Prs3d_ShadingAspect) ShadingAspect (Prs3d_DatumParts thePart) const;
- //! Returns the right-handed coordinate system set in SetComponent.
+ //! Returns the text attributes for rendering labels.
const Handle(Prs3d_TextAspect)& TextAspect() const { return myTextAspect; }
+ //! Sets text attributes for rendering labels.
+ void SetTextAspect (const Handle(Prs3d_TextAspect)& theTextAspect) { myTextAspect = theTextAspect; }
+
//! Returns the point aspect of origin wireframe presentation
const Handle(Prs3d_PointAspect)& PointAspect() const { return myPointAspect; }
+ //! Returns the point aspect of origin wireframe presentation
+ void SetPointAspect (const Handle(Prs3d_PointAspect)& theAspect) { myPointAspect = theAspect; }
+
//! Returns the arrow aspect of presentation
const Handle(Prs3d_ArrowAspect)& ArrowAspect() const { return myArrowAspect; }
+ //! Sets the arrow aspect of presentation
+ void SetArrowAspect (const Handle(Prs3d_ArrowAspect)& theAspect) { myArrowAspect = theAspect; }
+
//! Returns the attributes for display of the first axis.
Standard_DEPRECATED("This method is deprecated - LineAspect() should be called instead")
const Handle(Prs3d_LineAspect)& FirstAxisAspect() const { return myLineAspects.Find (Prs3d_DP_XAxis); }
const Standard_Integer theNbSlices,
const Standard_Integer theNbStacks)
: myInnerRadius (theInnerRadius),
- myOuterRadius (theOuterRadius)
+ myOuterRadius (theOuterRadius),
+ myStartAngle (0.0),
+ myEndAngle (M_PI * 2.0)
{
mySlicesNb = theNbSlices;
myStacksNb = theNbStacks;
//=======================================================================
gp_Pnt Prs3d_ToolDisk::Vertex (const Standard_Real theU, const Standard_Real theV)
{
- const Standard_Real aU = theU * M_PI * 2.0;
+ const Standard_Real aU = myStartAngle + theU * (myEndAngle - myStartAngle);
const Standard_Real aRadius = myInnerRadius + (myOuterRadius - myInnerRadius) * theV;
return gp_Pnt (Cos (aU) * aRadius,
Sin (aU) * aRadius,
0.0);
}
-//=======================================================================
-//function : Add
-//purpose :
-//=======================================================================
-gp_Dir Prs3d_ToolDisk::Normal (const Standard_Real /*theU*/, const Standard_Real /*theV*/)
-{
- return gp_Dir (0.0, 0.0, -1.0);
-}
-
//=======================================================================
//function : Perform
//purpose :
const Standard_Real theOuterRadius,
const Standard_Integer theNbSlices,
const Standard_Integer theNbStacks);
+
+ //! Set angle range in radians [0, 2*PI] by default.
+ //! @param theStartAngle [in] Start angle in counter clockwise order
+ //! @param theEndAngle [in] End angle in counter clockwise order
+ void SetAngleRange (Standard_Real theStartAngle,
+ Standard_Real theEndAngle)
+ {
+ myStartAngle = theStartAngle;
+ myEndAngle = theEndAngle;
+ }
+
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;
+ virtual gp_Dir Normal (const Standard_Real , const Standard_Real ) Standard_OVERRIDE { return gp_Dir (0.0, 0.0, -1.0); }
protected:
Standard_Real myInnerRadius;
Standard_Real myOuterRadius;
+ Standard_Real myStartAngle; //!< Start angle in counter clockwise order
+ Standard_Real myEndAngle; //!< End angle in counter clockwise order
};
#ifndef _SelectMgr_EntityOwner_HeaderFile
#define _SelectMgr_EntityOwner_HeaderFile
+#include <Aspect_VKey.hxx>
#include <PrsMgr_PresentationManager.hxx>
#include <SelectMgr_SelectableObject.hxx>
#include <TopLoc_Location.hxx>
//! Sets the selectable object.
virtual void SetSelectable (const Handle(SelectMgr_SelectableObject)& theSelObj) { mySelectable = theSelObj.get(); }
+ //! Handle mouse button click event.
+ //! Does nothing by default and returns FALSE.
+ //! @param thePoint mouse cursor position
+ //! @param theButton clicked button
+ //! @param theModifiers key modifiers
+ //! @param theIsDoubleClick flag indicating double mouse click
+ //! @return TRUE if object handled click
+ virtual Standard_Boolean HandleMouseClick (const Graphic3d_Vec2i& thePoint,
+ Aspect_VKeyMouse theButton,
+ Aspect_VKeyFlags theModifiers,
+ bool theIsDoubleClick)
+ {
+ (void )thePoint; (void )theButton; (void )theModifiers; (void )theIsDoubleClick;
+ return Standard_False;
+ }
+
//! Returns true if the presentation manager highlights selections corresponding to the selection mode.
virtual Standard_Boolean IsHilighted (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
const Standard_Integer theMode = 0) const
#include <ViewerTest_EventManager.hxx>
+#include <AIS_AnimationCamera.hxx>
#include <AIS_InteractiveContext.hxx>
#include <AIS_Shape.hxx>
#include <Aspect_Grid.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_EventManager,Standard_Transient)
+//=======================================================================
+//function : GlobalViewAnimation
+//purpose :
+//=======================================================================
+const Handle(AIS_AnimationCamera)& ViewerTest_EventManager::GlobalViewAnimation()
+{
+ static Handle(AIS_AnimationCamera) THE_CAMERA_ANIM = new AIS_AnimationCamera ("ViewerTest_EventManager_ViewAnimation", Handle(V3d_View)());
+ return THE_CAMERA_ANIM;
+}
+
//=======================================================================
//function : ViewerTest_EventManager
//purpose :
: myCtx (theCtx),
myView (theView),
myToPickPnt (Standard_False)
-{}
+{
+ myViewAnimation = GlobalViewAnimation();
+}
+
+//=======================================================================
+//function : ~ViewerTest_EventManager
+//purpose :
+//=======================================================================
+ViewerTest_EventManager::~ViewerTest_EventManager()
+{
+ if (!myViewAnimation.IsNull()
+ && myViewAnimation->View() == myView)
+ {
+ myViewAnimation->Stop();
+ myViewAnimation->SetView (Handle(V3d_View)());
+ }
+}
//=======================================================================
//function : UpdateMouseButtons
return Draw_ToExitOnCloseView;
}
+ //! Use global camera animation object shared across all Views in ViewerTest.
+ Standard_EXPORT static const Handle(AIS_AnimationCamera)& GlobalViewAnimation();
+
public:
//! Main constructor.
Standard_EXPORT ViewerTest_EventManager(const Handle(V3d_View)& aView, const Handle(AIS_InteractiveContext)& aCtx);
-
+
+ //! Destructor.
+ Standard_EXPORT virtual ~ViewerTest_EventManager();
+
//! Return interactive context.
const Handle(AIS_InteractiveContext)& Context() const { return myCtx; }
#include <AIS_ListOfInteractive.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <AIS_Manipulator.hxx>
+#include <AIS_ViewCube.hxx>
#include <AIS_Shape.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Aspect_Grid.hxx>
return 0;
}
+//===============================================================================================
+//function : VViewCube
+//purpose :
+//===============================================================================================
+static int VViewCube (Draw_Interpretor& ,
+ Standard_Integer theNbArgs,
+ const char** theArgVec)
+{
+ const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+ const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+ if (aContext.IsNull() || aView.IsNull())
+ {
+ std::cout << "Error: no active view.\n";
+ return 1;
+ }
+ else if (theNbArgs < 2)
+ {
+ std::cout << "Syntax error: wrong number arguments\n";
+ return 1;
+ }
+
+ Handle(AIS_ViewCube) aViewCube;
+ ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
+ Quantity_Color aColorRgb;
+ TCollection_AsciiString aName;
+ for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+ if (anUpdateTool.parseRedrawMode (anArg))
+ {
+ //
+ }
+ else if (aViewCube.IsNull())
+ {
+ aName = theArgVec[anArgIter];
+ if (aName.StartsWith ("-"))
+ {
+ std::cout << "Syntax error: object name should be specified.\n";
+ return 1;
+ }
+ Handle(AIS_InteractiveObject) aPrs;
+ GetMapOfAIS().Find2 (aName, aPrs);
+ aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
+ if (aViewCube.IsNull())
+ {
+ aViewCube = new AIS_ViewCube();
+ aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
+ aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
+ aViewCube->SetFixedAnimationLoop (false);
+ }
+ }
+ else if (anArg == "-reset")
+ {
+ aViewCube->ResetStyles();
+ }
+ else if (anArg == "-color"
+ || anArg == "-boxcolor"
+ || anArg == "-boxsidecolor"
+ || anArg == "-sidecolor"
+ || anArg == "-boxedgecolor"
+ || anArg == "-edgecolor"
+ || anArg == "-boxcornercolor"
+ || anArg == "-cornercolor"
+ || anArg == "-innercolor"
+ || anArg == "-textcolor")
+ {
+ Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
+ theArgVec + anArgIter + 1,
+ aColorRgb);
+ if (aNbParsed == 0)
+ {
+ std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+ return 1;
+ }
+ anArgIter += aNbParsed;
+ if (anArg == "-boxcolor")
+ {
+ aViewCube->SetBoxColor (aColorRgb);
+ }
+ else if (anArg == "-boxsidecolor"
+ || anArg == "-sidecolor")
+ {
+ aViewCube->BoxSideStyle()->SetColor (aColorRgb);
+ aViewCube->SynchronizeAspects();
+ }
+ else if (anArg == "-boxedgecolor"
+ || anArg == "-edgecolor")
+ {
+ aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
+ aViewCube->SynchronizeAspects();
+ }
+ else if (anArg == "-boxcornercolor"
+ || anArg == "-cornercolor")
+ {
+ aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
+ aViewCube->SynchronizeAspects();
+ }
+ else if (anArg == "-innercolor")
+ {
+ aViewCube->SetInnerColor (aColorRgb);
+ }
+ else if (anArg == "-textcolor")
+ {
+ aViewCube->SetTextColor (aColorRgb);
+ }
+ else
+ {
+ aViewCube->SetColor (aColorRgb);
+ }
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-transparency"
+ || anArg == "-boxtransparency"))
+ {
+ const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
+ if (aValue < 0.0 || aValue > 1.0)
+ {
+ std::cout << "Syntax error: invalid transparency value " << theArgVec[anArgIter] << "\n";
+ return 1;
+ }
+
+ if (anArg == "-boxtransparency")
+ {
+ aViewCube->SetBoxTransparency (aValue);
+ }
+ else
+ {
+ aViewCube->SetTransparency (aValue);
+ }
+ }
+ else if (anArg == "-axes"
+ || anArg == "-edges"
+ || anArg == "-vertices"
+ || anArg == "-vertexes"
+ || anArg == "-fixedanimation")
+ {
+ bool toShow = true;
+ if (anArgIter + 1 < theNbArgs
+ && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toShow))
+ {
+ ++anArgIter;
+ }
+ if (anArg == "-fixedanimation")
+ {
+ aViewCube->SetFixedAnimationLoop (toShow);
+ }
+ else if (anArg == "-axes")
+ {
+ aViewCube->SetDrawAxes (toShow);
+ }
+ else if (anArg == "-edges")
+ {
+ aViewCube->SetDrawEdges (toShow);
+ }
+ else
+ {
+ aViewCube->SetDrawVertices (toShow);
+ }
+ }
+ else if (anArg == "-yup"
+ || anArg == "-zup")
+ {
+ bool isOn = true;
+ if (anArgIter + 1 < theNbArgs
+ && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isOn))
+ {
+ ++anArgIter;
+ }
+ if (anArg == "-yup")
+ {
+ aViewCube->SetYup (isOn);
+ }
+ else
+ {
+ aViewCube->SetYup (!isOn);
+ }
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && anArg == "-font")
+ {
+ aViewCube->SetFont (theArgVec[++anArgIter]);
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && anArg == "-fontheight")
+ {
+ aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-size"
+ || anArg == "-boxsize"))
+ {
+ aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
+ anArg != "-boxsize");
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-boxfacet"
+ || anArg == "-boxfacetextension"
+ || anArg == "-facetextension"
+ || anArg == "-extension"))
+ {
+ aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-boxedgegap"
+ || anArg == "-edgegap"))
+ {
+ aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-boxedgeminsize"
+ || anArg == "-edgeminsize"))
+ {
+ aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && (anArg == "-boxcornerminsize"
+ || anArg == "-cornerminsize"))
+ {
+ aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && anArg == "-axespadding")
+ {
+ aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && anArg == "-roundradius")
+ {
+ aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else if (anArgIter + 1 < theNbArgs
+ && anArg == "-duration")
+ {
+ aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
+ }
+ else
+ {
+ std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
+ return 1;
+ }
+ }
+ if (aViewCube.IsNull())
+ {
+ std::cout << "Syntax error: wrong number of arguments\n";
+ return 1;
+ }
+
+ ViewerTest::Display (aName, aViewCube, false);
+ return 0;
+}
+
//=======================================================================
//function : ViewerCommands
//purpose :
"\n\t\t: selMode color of selection mode"
"\n\t\t: entity color of etected entity",
__FILE__, VDumpSelectionImage, group);
-}
+ theCommands.Add ("vviewcube",
+ "vviewcube name"
+ "\n\t\t: Displays interactive view manipualtion object."
+ "\n\t\t: Options: "
+ "\n\t\t: -reset reset geomertical and visual attributes'"
+ "\n\t\t: -size Size adapted size of View Cube"
+ "\n\t\t: -boxSize Size box size"
+ "\n\t\t: -axes {0|1 } show/hide axes (trihedron)"
+ "\n\t\t: -edges {0|1} show/hide edges of View Cube"
+ "\n\t\t: -vertices {0|1} show/hide vertices of View Cube"
+ "\n\t\t: -Yup {0|1} -Zup {0|1} set Y-up or Z-up view orientation"
+ "\n\t\t: -color Color color of View Cube"
+ "\n\t\t: -boxColor Color box color"
+ "\n\t\t: -boxSideColor Color box sides color"
+ "\n\t\t: -boxEdgeColor Color box edges color"
+ "\n\t\t: -boxCornerColor Color box corner color"
+ "\n\t\t: -textColor Color color of side text of view cube"
+ "\n\t\t: -innerColor Color inner box color"
+ "\n\t\t: -transparency Value transparency of object within [0, 1] range"
+ "\n\t\t: -boxTransparency Value transparency of box within [0, 1] range"
+ "\n\t\t: -font Name font name"
+ "\n\t\t: -fontHeight Value font height"
+ "\n\t\t: -boxFacetExtension Value box facet extension"
+ "\n\t\t: -boxEdgeGap Value gap between box edges and box sides"
+ "\n\t\t: -boxEdgeMinSize Value minimal box edge size"
+ "\n\t\t: -boxCornerMinSize Value minimal box corner size"
+ "\n\t\t: -axesPadding Value padding between box and arrows"
+ "\n\t\t: -roundRadius Value relative radius of corners of sides within [0.0, 0.5] range"
+ "\n\t\t: -fixedanimation {0|1} uninterruptible animation loop"
+ "\n\t\t: -duration Seconds animation duration in seconds",
+ __FILE__, VViewCube, group);
+
+}
020 anim
021 dimensions
022 transparency
+023 viewcube
--- /dev/null
+puts "=================================="
+puts "0028954: Visualization - implement interactive object AIS_ViewCube for camera manipulations"
+puts "Display and erase with default settings"
+puts "=================================="
+
+vclear
+vinit View1
+
+box b 15 20 70
+vdisplay -dispMode 1 b
+vaxo
+vfit
+vviewcube vc -fixedAnimation 1 -duration 0
+
+vmoveto 70 340
+if {[vreadpixel 70 340 name rgb] != "CYAN1"} { puts "Error: Highlighting of view cube Side is wrong." }
+vmoveto 0 0
+vdump $imagedir/${casename}_axo.png
+
+# check FRONT side
+vselect 70 340
+if {[vreadpixel 255 300 name rgb] != "BLACK"} { puts "Error: Position of FRONT camera is wrong." }
+vdump $imagedir/${casename}_side.png
+
+# check FRONT/TOP edge
+vselect 100 270
+if {[vreadpixel 100 300 name rgb] != "GRAY51"} { puts "Error: Position of FRONT-TOP camera is wrong." }
+if {[vreadpixel 100 310 name rgb] != "CYAN1"} { puts "Error: Position of FRONT-TOP camera is wrong." }
+vdump $imagedir/${casename}_edge.png
+
+# Check vertex
+vselect 140 310
+if {[vreadpixel 100 290 name rgb] != "GRAY42"} { puts "Error: Position of TOP-FRONT-RIGHT camera is wrong." }
+if {[vreadpixel 100 310 name rgb] != "CYAN1"} { puts "Error: Position of TOP-FRONT-RIGHT camera is wrong." }
+if {[vreadpixel 100 320 name rgb] != "MATRAGRAY"} { puts "Error: Position of TOP-FRONT-RIGHT camera is wrong." }
+vdump $imagedir/${casename}_corner.png
--- /dev/null
+puts "=================================="
+puts "0028954: Visualization - implement interactive object AIS_ViewCube for camera manipulations"
+puts "Display custom styled View Cube"
+puts "=================================="
+
+vclear
+vinit View1
+
+vviewcube vc -edges 0
+if {[vreadpixel 70 295 name rgb] != "BLACK"} { puts "Error: Invalid display of View Cube without edges." }
+vdump $imagedir/${casename}_noedges.png
+
+vviewcube vc -edges 1 -vertices 0
+if {[vreadpixel 100 308 name rgb] != "BLACK"} { puts "Error: Invalid display of View Cube without vertices." }
+vdump $imagedir/${casename}_noverts.png
+
+vviewcube vc -edges 0 -vertices 0
+
+if {[vreadpixel 70 295 name rgb] != "BLACK" || [vreadpixel 100 308 name rgb] != "BLACK"} {
+ puts "Error: Invalid display of View Cube without edges & vertices."
+}
+vdump $imagedir/${casename}_noedgeandvert.png
+vclear
+
+# Color
+vviewcube vc1 -boxColor 0.69 0.88 1 -textColor 0 0.4 0.54
+vdisplay vc1 -trihedron bottomLeft 100 100
+
+# Transparency
+vviewcube vc2 -transparency 0.5
+vdisplay vc2 -trihedron topLeft 100 100
+
+# Font
+vviewcube vc3 -reset -boxSideColor WHITE -font "monospace" -fontHeight 16
+vdisplay vc3 -trihedron bottomRight 100 100
+
+# Corner radius
+vviewcube vc4 -reset -boxSideColor WHITE -roundRadius 0.2 -boxEdgeGap 2
+vdisplay vc4 -trihedron topRight 100 100
+
+# Padding
+vviewcube vc5 -reset -boxFacetExtension 0 -axesPadding 0
+vdisplay vc5 -trihedron center
+vdump $imagedir/${casename}_styles.png
--- /dev/null
+puts "=================================="
+puts "0028954: Visualization - implement interactive object AIS_ViewCube for camera manipulations"
+puts "Check view affinity"
+puts "=================================="
+
+vclear
+vclose ALL
+vinit View1
+vinit View2
+
+vviewcube vc
+verase vc -view
+
+if {[vreadpixel 100 350 name rgb] != "BLACK"} { puts "Error: hiding Cube in View2 fails." }
+vdump $imagedir/${casename}_v2.png
+
+vactivate View1
+
+if {[vreadpixel 100 350 name rgb] == "BLACK"} { puts "Error: showing Cube in View1 fails." }
+vdump $imagedir/${casename}_v1.png
+
+vactivate View2