1 // Created on: 2017-07-25
2 // Created by: Anastasia BOBYLEVA
3 // Copyright (c) 2017-2019 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <AIS_ViewCube.hxx>
17 
18 #include <AIS_AnimationCamera.hxx>
19 #include <AIS_InteractiveContext.hxx>
20 #include <gp_Ax2.hxx>
21 #include <Graphic3d_ViewAffinity.hxx>
22 #include <Graphic3d_Text.hxx>
23 #include <NCollection_Lerp.hxx>
24 #include <Prs3d.hxx>
25 #include <Prs3d_Arrow.hxx>
26 #include <Prs3d_DatumAspect.hxx>
27 #include <Prs3d_Text.hxx>
28 #include <Prs3d_ToolDisk.hxx>
29 #include <Prs3d_ToolSphere.hxx>
30 #include <SelectMgr_SequenceOfOwner.hxx>
31 #include <V3d.hxx>
32 #include <V3d_View.hxx>
33 
34 IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCube, AIS_InteractiveObject)
35 IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCubeOwner, SelectMgr_EntityOwner)
36 IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCubeSensitive, Select3D_SensitivePrimitiveArray)
37 
38 namespace
39 {
40   static const Standard_Integer THE_NB_ROUND_SPLITS = 8;
41   static const Standard_Integer THE_NB_DISK_SLICES = 20;
42   static const Standard_Integer THE_NB_ARROW_FACETTES = 20;
43 
44   //! Return the number of non-zero components.
nbDirectionComponents(const gp_Dir & theDir)45   static Standard_Integer nbDirectionComponents (const gp_Dir& theDir)
46   {
47     Standard_Integer aNbComps = 0;
48     for (Standard_Integer aCompIter = 1; aCompIter <= 3; ++aCompIter)
49     {
50       if (Abs (theDir.Coord (aCompIter)) > gp::Resolution())
51       {
52         ++aNbComps;
53       }
54     }
55     return aNbComps;
56   }
57 }
58 
59 //=======================================================================
60 //function : AIS_ViewCubeSensitive
61 //purpose  :
62 //=======================================================================
AIS_ViewCubeSensitive(const Handle (SelectMgr_EntityOwner)& theOwner,const Handle (Graphic3d_ArrayOfTriangles)& theTris)63 AIS_ViewCubeSensitive::AIS_ViewCubeSensitive (const Handle(SelectMgr_EntityOwner)& theOwner,
64                                               const Handle(Graphic3d_ArrayOfTriangles)& theTris)
65 : Select3D_SensitivePrimitiveArray (theOwner)
66 {
67   InitTriangulation (theTris->Attributes(), theTris->Indices(), TopLoc_Location());
68 }
69 
70 //=======================================================================
71 //function : Matches
72 //purpose  :
73 //=======================================================================
Matches(SelectBasics_SelectingVolumeManager & theMgr,SelectBasics_PickResult & thePickResult)74 Standard_Boolean AIS_ViewCubeSensitive::Matches (SelectBasics_SelectingVolumeManager& theMgr,
75                                                  SelectBasics_PickResult& thePickResult)
76 {
77   return isValidRay (theMgr) && Select3D_SensitivePrimitiveArray::Matches (theMgr, thePickResult);
78 }
79 
80 //=======================================================================
81 //function : isValidRay
82 //purpose  :
83 //=======================================================================
isValidRay(const SelectBasics_SelectingVolumeManager & theMgr) const84 bool AIS_ViewCubeSensitive::isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
85 {
86   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
87   {
88     // disallow rectangular selection
89     return false;
90   }
91 
92   if (AIS_ViewCubeOwner* anOwner = dynamic_cast<AIS_ViewCubeOwner* >(myOwnerId.get()))
93   {
94     const Standard_Real anAngleToler = 10.0 * M_PI / 180.0;
95     const gp_Dir aRay = theMgr.GetViewRayDirection();
96     const gp_Dir aDir = V3d::GetProjAxis (anOwner->MainOrientation());
97     return !aRay.IsNormal (aDir, anAngleToler);
98   }
99   return true;
100 }
101 
102 //=======================================================================
103 //function : IsBoxSide
104 //purpose  :
105 //=======================================================================
IsBoxSide(V3d_TypeOfOrientation theOrient)106 bool AIS_ViewCube::IsBoxSide (V3d_TypeOfOrientation theOrient)
107 {
108   return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 1;
109 }
110 
111 //=======================================================================
112 //function : IsBoxEdge
113 //purpose  :
114 //=======================================================================
IsBoxEdge(V3d_TypeOfOrientation theOrient)115 bool AIS_ViewCube::IsBoxEdge (V3d_TypeOfOrientation theOrient)
116 {
117   return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 2;
118 }
119 
120 //=======================================================================
121 //function : IsBoxCorner
122 //purpose  :
123 //=======================================================================
IsBoxCorner(V3d_TypeOfOrientation theOrient)124 bool AIS_ViewCube::IsBoxCorner (V3d_TypeOfOrientation theOrient)
125 {
126   return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 3;
127 }
128 
129 //=======================================================================
130 //function : AIS_ViewCube
131 //purpose  :
132 //=======================================================================
AIS_ViewCube()133 AIS_ViewCube::AIS_ViewCube()
134 : myBoxEdgeAspect (new Prs3d_ShadingAspect()),
135   myBoxCornerAspect (new Prs3d_ShadingAspect()),
136   mySize (1.0),
137   myBoxEdgeMinSize (2.0),
138   myBoxEdgeGap (0.0),
139   myBoxFacetExtension (1.0),
140   myAxesPadding (1.0),
141   myAxesRadius (1.0),
142   myAxesConeRadius (3.0),
143   myAxesSphereRadius (4.0),
144   myCornerMinSize (2.0),
145   myRoundRadius  (0.0),
146   myToDisplayAxes (true),
147   myToDisplayEdges (true),
148   myToDisplayVertices (true),
149   myIsYup (false),
150   myViewAnimation (new AIS_AnimationCamera ("AIS_ViewCube", Handle(V3d_View)())),
151   myStartState(new Graphic3d_Camera()),
152   myEndState  (new Graphic3d_Camera()),
153   myToAutoStartAnim (true),
154   myIsFixedAnimation (true),
155   myToFitSelected (true),
156   myToResetCameraUp (false)
157 {
158   myViewAnimation->SetOwnDuration (0.5);
159   myInfiniteState = true;
160   myIsMutable = true;
161   myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
162   myTransformPersistence = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (100, 100));
163 
164   myDrawer->SetTextAspect  (new Prs3d_TextAspect());
165   myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
166 
167   myDynHilightDrawer = new Prs3d_Drawer();
168   myDynHilightDrawer->SetLink (myDrawer);
169   myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
170 
171   setDefaultAttributes();
172   setDefaultHighlightAttributes();
173 
174   // setup default labels
175   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Front,  "FRONT");
176   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Back,   "BACK");
177   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Top,    "TOP");
178   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Bottom, "BOTTOM");
179   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Left,   "LEFT");
180   myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Right,  "RIGHT");
181 
182   myAxesLabels.Bind (Prs3d_DatumParts_XAxis, "X");
183   myAxesLabels.Bind (Prs3d_DatumParts_YAxis, "Y");
184   myAxesLabels.Bind (Prs3d_DatumParts_ZAxis, "Z");
185 
186   // define default size
187   SetSize (70.0);
188 }
189 
190 //=======================================================================
191 //function : setDefaultAttributes
192 //purpose  :
193 //=======================================================================
setDefaultAttributes()194 void AIS_ViewCube::setDefaultAttributes()
195 {
196   myDrawer->TextAspect()->SetHorizontalJustification(Graphic3d_HTA_CENTER);
197   myDrawer->TextAspect()->SetVerticalJustification  (Graphic3d_VTA_CENTER);
198   myDrawer->TextAspect()->SetColor (Quantity_NOC_BLACK);
199   myDrawer->TextAspect()->SetFont (Font_NOF_SANS_SERIF);
200   myDrawer->TextAspect()->SetHeight (16.0);
201   myDrawer->TextAspect()->Aspect()->SetTextZoomable (true); // the whole object is drawn within transformation-persistence
202   // this should be forced back-face culling regardless Closed flag
203   myDrawer->TextAspect()->Aspect()->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled);
204 
205   Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_UserDefined);
206   aMat.SetColor (Quantity_NOC_WHITE);
207   aMat.SetAmbientColor (Quantity_NOC_GRAY60);
208 
209   const Handle(Graphic3d_AspectFillArea3d)& aShading = myDrawer->ShadingAspect()->Aspect();
210   aShading->SetInteriorStyle (Aspect_IS_SOLID);
211   // this should be forced back-face culling regardless Closed flag
212   aShading->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled);
213   aShading->SetInteriorColor (aMat.Color());
214   aShading->SetFrontMaterial (aMat);
215   myDrawer->SetFaceBoundaryDraw (false);
216 
217   *myBoxEdgeAspect  ->Aspect() = *aShading;
218   myBoxEdgeAspect->SetColor (Quantity_NOC_GRAY30);
219   *myBoxCornerAspect->Aspect() = *aShading;
220   myBoxCornerAspect->SetColor (Quantity_NOC_GRAY30);
221 }
222 
223 //=======================================================================
224 //function : setDefaultHighlightAttributes
225 //purpose  :
226 //=======================================================================
setDefaultHighlightAttributes()227 void AIS_ViewCube::setDefaultHighlightAttributes()
228 {
229   Graphic3d_MaterialAspect aHighlightMaterial;
230   aHighlightMaterial.SetAmbientColor (Quantity_NOC_BLACK);
231   aHighlightMaterial.SetDiffuseColor (Quantity_NOC_BLACK);
232   aHighlightMaterial.SetSpecularColor(Quantity_NOC_BLACK);
233   aHighlightMaterial.SetEmissiveColor(Quantity_NOC_BLACK);
234   aHighlightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
235   myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
236   myDynHilightDrawer->ShadingAspect()->SetMaterial (aHighlightMaterial);
237   myDynHilightDrawer->ShadingAspect()->SetColor (Quantity_NOC_CYAN1);
238   myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
239   myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
240 }
241 
242 //=======================================================================
243 //function : SetYup
244 //purpose  :
245 //=======================================================================
SetYup(Standard_Boolean theIsYup,Standard_Boolean theToUpdateLabels)246 void AIS_ViewCube::SetYup (Standard_Boolean theIsYup,
247                            Standard_Boolean theToUpdateLabels)
248 {
249   if (myIsYup == theIsYup)
250   {
251     return;
252   }
253 
254   myIsYup = theIsYup;
255 
256   static const V3d_TypeOfOrientation THE_ZUP_ORI_LIST[6] =
257   {
258     V3d_TypeOfOrientation_Zup_Front, V3d_TypeOfOrientation_Zup_Back,
259     V3d_TypeOfOrientation_Zup_Top,   V3d_TypeOfOrientation_Zup_Bottom,
260     V3d_TypeOfOrientation_Zup_Left,  V3d_TypeOfOrientation_Zup_Right
261   };
262   static const V3d_TypeOfOrientation THE_YUP_ORI_LIST[6] =
263   {
264     V3d_TypeOfOrientation_Yup_Front, V3d_TypeOfOrientation_Yup_Back,
265     V3d_TypeOfOrientation_Yup_Top,   V3d_TypeOfOrientation_Yup_Bottom,
266     V3d_TypeOfOrientation_Yup_Left,  V3d_TypeOfOrientation_Yup_Right
267   };
268   if (theToUpdateLabels)
269   {
270     NCollection_Array1<TCollection_AsciiString> aLabels (0, 5);
271     for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter)
272     {
273       myBoxSideLabels.Find (!myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter],
274                             aLabels.ChangeValue (aLabelIter));
275     }
276     for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter)
277     {
278       myBoxSideLabels.Bind (myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter],
279                             aLabels.Value (aLabelIter));
280     }
281   }
282 
283   SetToUpdate();
284 }
285 
286 //=======================================================================
287 //function : ResetStyles
288 //purpose  :
289 //=======================================================================
ResetStyles()290 void AIS_ViewCube::ResetStyles()
291 {
292   UnsetAttributes();
293   UnsetHilightAttributes();
294 
295   myBoxEdgeMinSize = 2.0;
296   myCornerMinSize  = 2.0;
297   myBoxEdgeGap     = 0.0;
298   myRoundRadius    = 0.0;
299 
300   myToDisplayAxes = true;
301   myToDisplayEdges = true;
302   myToDisplayVertices = true;
303 
304   myBoxFacetExtension = 1.0;
305   myAxesPadding = 1.0;
306   SetSize (70.0);
307 }
308 
309 //=======================================================================
310 //function : SetSize
311 //purpose  :
312 //=======================================================================
SetSize(Standard_Real theValue,Standard_Boolean theToAdaptAnother)313 void AIS_ViewCube::SetSize (Standard_Real theValue,
314                             Standard_Boolean theToAdaptAnother)
315 {
316   const bool isNewSize = Abs (mySize - theValue) > Precision::Confusion();
317   mySize = theValue;
318   if (theToAdaptAnother)
319   {
320     if (myBoxFacetExtension > 0.0)
321     {
322       SetBoxFacetExtension (mySize * 0.15);
323     }
324     if (myAxesPadding > 0.0)
325     {
326       SetAxesPadding (mySize * 0.1);
327     }
328     SetFontHeight (mySize * 0.16);
329   }
330   if (isNewSize)
331   {
332     SetToUpdate();
333   }
334 }
335 
336 //=======================================================================
337 //function : SetRoundRadius
338 //purpose  :
339 //=======================================================================
SetRoundRadius(const Standard_Real theValue)340 void AIS_ViewCube::SetRoundRadius (const Standard_Real theValue)
341 {
342   Standard_OutOfRange_Raise_if (theValue < 0.0 || theValue > 0.5,
343                                 "AIS_ViewCube::SetRoundRadius(): theValue should be in [0; 0.5]");
344   if (Abs (myRoundRadius - theValue) > Precision::Confusion())
345   {
346     myRoundRadius = theValue;
347     SetToUpdate();
348   }
349 }
350 
351 //=======================================================================
352 //function : createRoundRectangleTriangles
353 //purpose  :
354 //=======================================================================
createRoundRectangleTriangles(const Handle (Graphic3d_ArrayOfTriangles)& theTris,Standard_Integer & theNbNodes,Standard_Integer & theNbTris,const gp_XY & theSize,Standard_Real theRadius,const gp_Trsf & theTrsf)355 void AIS_ViewCube::createRoundRectangleTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
356                                                   Standard_Integer& theNbNodes,
357                                                   Standard_Integer& theNbTris,
358                                                   const gp_XY& theSize,
359                                                   Standard_Real theRadius,
360                                                   const gp_Trsf& theTrsf)
361 {
362   const Standard_Real aRadius = Min (theRadius, Min (theSize.X(), theSize.Y()) * 0.5);
363   const gp_XY  aHSize (theSize.X() * 0.5 - aRadius, theSize.Y() * 0.5 - aRadius);
364   const gp_Dir aNorm = gp::DZ().Transformed (theTrsf);
365   const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0;
366   if (aRadius > 0.0)
367   {
368     const Standard_Integer aNbNodes = (THE_NB_ROUND_SPLITS + 1) * 4 + 1;
369     theNbNodes += aNbNodes;
370     theNbTris  += aNbNodes;
371     if (theTris.IsNull())
372     {
373       return;
374     }
375 
376     theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (theTrsf));
377     for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
378     {
379       const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (M_PI * 0.5, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
380       theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
381     }
382     for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
383     {
384       const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (0.0, -M_PI * 0.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
385       theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
386     }
387     for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
388     {
389       const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI * 0.5, -M_PI, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
390       theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
391     }
392     for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter)
393     {
394       const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI, -M_PI * 1.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS));
395       theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf));
396     }
397 
398     // split triangle fan
399     theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true);
400   }
401   else
402   {
403     theNbNodes += 4;
404     theNbTris  += 2;
405     if (theTris.IsNull())
406     {
407       return;
408     }
409 
410     theTris->AddVertex (gp_Pnt (-aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
411     theTris->AddVertex (gp_Pnt (-aHSize.X(),  aHSize.Y(), 0.0).Transformed (theTrsf));
412     theTris->AddVertex (gp_Pnt ( aHSize.X(),  aHSize.Y(), 0.0).Transformed (theTrsf));
413     theTris->AddVertex (gp_Pnt ( aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf));
414     theTris->AddQuadTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3, aVertFirst + 4);
415   }
416 
417   for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter)
418   {
419     theTris->SetVertexNormal (aVertIter, -aNorm);
420   }
421 }
422 
423 //=======================================================================
424 //function : createBoxPartTriangles
425 //purpose  :
426 //=======================================================================
createBoxPartTriangles(const Handle (Graphic3d_ArrayOfTriangles)& theTris,Standard_Integer & theNbNodes,Standard_Integer & theNbTris,V3d_TypeOfOrientation theDir) const427 void AIS_ViewCube::createBoxPartTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
428                                            Standard_Integer& theNbNodes,
429                                            Standard_Integer& theNbTris,
430                                            V3d_TypeOfOrientation theDir) const
431 {
432   if (IsBoxSide (theDir))
433   {
434     createBoxSideTriangles (theTris, theNbNodes, theNbTris, theDir);
435   }
436   else if (IsBoxEdge (theDir)
437         && myToDisplayEdges)
438   {
439     createBoxEdgeTriangles (theTris, theNbNodes, theNbTris, theDir);
440   }
441   else if (IsBoxCorner (theDir)
442         && myToDisplayVertices)
443   {
444     createBoxCornerTriangles (theTris, theNbNodes, theNbTris, theDir);
445   }
446 }
447 
448 //=======================================================================
449 //function : createBoxSideTriangles
450 //purpose  :
451 //=======================================================================
createBoxSideTriangles(const Handle (Graphic3d_ArrayOfTriangles)& theTris,Standard_Integer & theNbNodes,Standard_Integer & theNbTris,V3d_TypeOfOrientation theDirection) const452 void AIS_ViewCube::createBoxSideTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
453                                            Standard_Integer& theNbNodes,
454                                            Standard_Integer& theNbTris,
455                                            V3d_TypeOfOrientation theDirection) const
456 {
457   const gp_Dir aDir = V3d::GetProjAxis (theDirection);
458   const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension);
459   const gp_Ax2 aPosition (aPos, aDir.Reversed());
460 
461   gp_Ax3 aSystem (aPosition);
462   gp_Trsf aTrsf;
463   aTrsf.SetTransformation (aSystem, gp_Ax3());
464 
465   createRoundRectangleTriangles (theTris, theNbNodes, theNbTris,
466                                  gp_XY (mySize, mySize), myRoundRadius * mySize, aTrsf);
467 }
468 
469 //=======================================================================
470 //function : createBoxEdgeTriangles
471 //purpose  :
472 //=======================================================================
createBoxEdgeTriangles(const Handle (Graphic3d_ArrayOfTriangles)& theTris,Standard_Integer & theNbNodes,Standard_Integer & theNbTris,V3d_TypeOfOrientation theDirection) const473 void AIS_ViewCube::createBoxEdgeTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
474                                            Standard_Integer& theNbNodes,
475                                            Standard_Integer& theNbTris,
476                                            V3d_TypeOfOrientation theDirection) const
477 {
478   const Standard_Real aThickness = Max (myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() - myBoxEdgeGap, myBoxEdgeMinSize);
479 
480   const gp_Dir aDir = V3d::GetProjAxis (theDirection);
481   const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 * gp_XY (1.0, 1.0).Modulus() + myBoxFacetExtension * Cos (M_PI_4));
482   const gp_Ax2 aPosition (aPos, aDir.Reversed());
483 
484   gp_Ax3 aSystem (aPosition);
485   gp_Trsf aTrsf;
486   aTrsf.SetTransformation (aSystem, gp_Ax3());
487 
488   createRoundRectangleTriangles (theTris, theNbNodes, theNbTris,
489                                  gp_XY (aThickness, mySize), myRoundRadius * mySize, aTrsf);
490 }
491 
492 //=======================================================================
493 //function : createBoxCornerTriangles
494 //purpose  :
495 //=======================================================================
createBoxCornerTriangles(const Handle (Graphic3d_ArrayOfTriangles)& theTris,Standard_Integer & theNbNodes,Standard_Integer & theNbTris,V3d_TypeOfOrientation theDir) const496 void AIS_ViewCube::createBoxCornerTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris,
497                                              Standard_Integer& theNbNodes,
498                                              Standard_Integer& theNbTris,
499                                              V3d_TypeOfOrientation theDir) const
500 {
501   const Standard_Real aHSize = mySize * 0.5;
502   const gp_Dir aDir = V3d::GetProjAxis (theDir);
503   const gp_XYZ aHSizeDir = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude());
504   const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0;
505   if (myRoundRadius > 0.0)
506   {
507     theNbNodes += THE_NB_DISK_SLICES + 1;
508     theNbTris  += THE_NB_DISK_SLICES + 1;
509     if (theTris.IsNull())
510     {
511       return;
512     }
513 
514     const Standard_Real anEdgeHWidth = myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() * 0.5;
515     const Standard_Real aHeight = anEdgeHWidth * Sqrt (2.0 / 3.0); // tetrahedron height
516     const gp_Pnt aPos = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude() + aHeight);
517     const gp_Ax2 aPosition (aPos, aDir.Reversed());
518     gp_Ax3 aSystem (aPosition);
519     gp_Trsf aTrsf;
520     aTrsf.SetTransformation (aSystem, gp_Ax3());
521     const Standard_Real aRadius = Max (myBoxFacetExtension * 0.5 / Cos (M_PI_4), myCornerMinSize);
522 
523     theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (aTrsf));
524     for (Standard_Integer aNodeIter = 0; aNodeIter < THE_NB_DISK_SLICES; ++aNodeIter)
525     {
526       const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (2.0 * M_PI, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_DISK_SLICES));
527       theTris->AddVertex (gp_Pnt (aRadius * Cos (anAngle), aRadius * Sin (anAngle), 0.0).Transformed (aTrsf));
528     }
529     theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true);
530   }
531   else
532   {
533     theNbNodes += 3;
534     theNbTris  += 1;
535     if (theTris.IsNull())
536     {
537       return;
538     }
539 
540     theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (aDir.X(), 0.0, 0.0).XYZ());
541     theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, aDir.Y(), 0.0).XYZ());
542     theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, 0.0, aDir.Z()).XYZ());
543 
544     const gp_XYZ aNode1 = theTris->Vertice (aVertFirst + 1).XYZ();
545     const gp_XYZ aNode2 = theTris->Vertice (aVertFirst + 2).XYZ();
546     const gp_XYZ aNode3 = theTris->Vertice (aVertFirst + 3).XYZ();
547     const gp_XYZ aNormTri = ((aNode2 - aNode1).Crossed (aNode3 - aNode1));
548     if (aNormTri.Dot (aDir.XYZ()) < 0.0)
549     {
550       theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 3, aVertFirst + 2);
551     }
552     else
553     {
554       theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3);
555     }
556   }
557 
558   for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter)
559   {
560     theTris->SetVertexNormal (aVertIter, aDir);
561   }
562 }
563 
564 //=======================================================================
565 //function : Compute
566 //purpose  :
567 //=======================================================================
Compute(const Handle (PrsMgr_PresentationManager)&,const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)568 void AIS_ViewCube::Compute (const Handle(PrsMgr_PresentationManager)& ,
569                             const Handle(Prs3d_Presentation)& thePrs,
570                             const Standard_Integer theMode)
571 {
572   thePrs->SetInfiniteState (true);
573   if (theMode != 0)
574   {
575     return;
576   }
577 
578   const gp_Pnt aLocation = (mySize * 0.5 + myBoxFacetExtension + myAxesPadding) * gp_XYZ (-1.0, -1.0, -1.0);
579 
580   // Display axes
581   if (myToDisplayAxes)
582   {
583     const Standard_Real anAxisSize = mySize + 2.0 * myBoxFacetExtension + myAxesPadding;
584     const Handle(Prs3d_DatumAspect)& aDatumAspect = myDrawer->DatumAspect();
585     for (Standard_Integer anAxisIter = Prs3d_DatumParts_XAxis; anAxisIter <= Prs3d_DatumParts_ZAxis; ++anAxisIter)
586     {
587       const Prs3d_DatumParts aPart = (Prs3d_DatumParts )anAxisIter;
588       if (!aDatumAspect->DrawDatumPart (aPart))
589       {
590         continue;
591       }
592 
593       gp_Ax1 anAx1;
594       switch (aPart)
595       {
596         case Prs3d_DatumParts_XAxis: anAx1 = gp_Ax1 (aLocation, gp::DX()); break;
597         case Prs3d_DatumParts_YAxis: anAx1 = gp_Ax1 (aLocation, gp::DY()); break;
598         case Prs3d_DatumParts_ZAxis: anAx1 = gp_Ax1 (aLocation, gp::DZ()); break;
599         default: break;
600       }
601 
602       Handle(Graphic3d_Group) anAxisGroup = thePrs->NewGroup();
603       anAxisGroup->SetClosed (true);
604       anAxisGroup->SetGroupPrimitivesAspect (aDatumAspect->ShadingAspect (aPart)->Aspect());
605 
606       const Standard_Real anArrowLength = 0.2 * anAxisSize;
607       Handle(Graphic3d_ArrayOfTriangles) aTriangleArray = Prs3d_Arrow::DrawShaded (anAx1, myAxesRadius, anAxisSize, myAxesConeRadius, anArrowLength, THE_NB_ARROW_FACETTES);
608       anAxisGroup->AddPrimitiveArray (aTriangleArray);
609 
610       TCollection_AsciiString anAxisLabel;
611       if (aDatumAspect->ToDrawLabels()
612       &&  myAxesLabels.Find (aPart, anAxisLabel)
613       && !anAxisLabel.IsEmpty())
614       {
615         Handle(Graphic3d_Group) anAxisLabelGroup = thePrs->NewGroup();
616         gp_Pnt aTextOrigin = anAx1.Location().Translated (gp_Vec (anAx1.Direction().X() * (anAxisSize + anArrowLength),
617                                                                   anAx1.Direction().Y() * (anAxisSize + anArrowLength),
618                                                                   anAx1.Direction().Z() * (anAxisSize + anArrowLength)));
619         Prs3d_Text::Draw (anAxisLabelGroup, aDatumAspect->TextAspect (aPart), TCollection_ExtendedString (anAxisLabel), aTextOrigin);
620       }
621     }
622 
623     // Display center
624     {
625       Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
626       aGroup->SetClosed (true);
627       Handle(Prs3d_ShadingAspect) anAspectCen = new Prs3d_ShadingAspect();
628       anAspectCen->SetColor (Quantity_NOC_WHITE);
629       aGroup->SetGroupPrimitivesAspect (anAspectCen->Aspect());
630       Prs3d_ToolSphere aTool (myAxesSphereRadius, THE_NB_DISK_SLICES, THE_NB_DISK_SLICES);
631       gp_Trsf aTrsf;
632       aTrsf.SetTranslation (gp_Vec (gp::Origin(), aLocation));
633       Handle(Graphic3d_ArrayOfTriangles) aCenterArray;
634       aTool.FillArray (aCenterArray, aTrsf);
635       aGroup->AddPrimitiveArray (aCenterArray);
636     }
637   }
638 
639   // Display box sides
640   {
641     Standard_Integer aNbNodes = 0, aNbTris = 0;
642     for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
643     {
644       createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
645     }
646     if (aNbNodes > 0)
647     {
648       Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
649       Handle(Graphic3d_ArrayOfSegments) aSegs;
650       if (myDrawer->FaceBoundaryDraw())
651       {
652         aSegs = new Graphic3d_ArrayOfSegments (aNbNodes, aNbNodes * 2, Graphic3d_ArrayFlags_None);
653       }
654       aNbNodes = aNbTris = 0;
655       for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
656       {
657         Standard_Integer aTriNodesFrom = aTris->VertexNumber();
658         const Standard_Integer aTriFrom = aNbTris;
659         createBoxPartTriangles (aTris, aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
660         if (aSegs.IsNull())
661         {
662           continue;
663         }
664 
665         const Standard_Integer aFirstNode = aSegs->VertexNumber();
666         for (Standard_Integer aVertIter = (aNbTris - aTriFrom) > 2 ? aTriNodesFrom + 2 : aTriNodesFrom + 1; // skip triangle fan center
667              aVertIter <= aTris->VertexNumber(); ++aVertIter)
668         {
669           aSegs->AddVertex (aTris->Vertice (aVertIter));
670         }
671         aSegs->AddPolylineEdges (aFirstNode + 1, aSegs->VertexNumber(), true);
672       }
673 
674       {
675         Handle(Graphic3d_Group) aGroupSides = thePrs->NewGroup();
676         aGroupSides->SetClosed (true);
677         aGroupSides->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
678         aGroupSides->AddPrimitiveArray (aTris);
679       }
680 
681       if (!aSegs.IsNull())
682       {
683         Handle(Graphic3d_Group) aGroupSegs = thePrs->NewGroup();
684         aGroupSegs->SetGroupPrimitivesAspect (myDrawer->FaceBoundaryAspect()->Aspect());
685         aGroupSegs->AddPrimitiveArray (aSegs);
686       }
687     }
688 
689     // Display box sides labels
690     Handle(Graphic3d_Group) aTextGroup = thePrs->NewGroup();
691     aTextGroup->SetGroupPrimitivesAspect (myDrawer->TextAspect()->Aspect());
692     for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter)
693     {
694       const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
695 
696       TCollection_AsciiString aLabel;
697       if (!myBoxSideLabels.Find (anOrient, aLabel)
698         || aLabel.IsEmpty())
699       {
700         continue;
701       }
702 
703       const gp_Dir aDir = V3d::GetProjAxis (anOrient);
704       gp_Dir anUp = myIsYup ? gp::DY() : gp::DZ();
705       if (myIsYup)
706       {
707         if (anOrient == V3d_Ypos
708           || anOrient == V3d_Yneg)
709         {
710           anUp = -gp::DZ();
711         }
712       }
713       else
714       {
715         if (anOrient == V3d_Zpos)
716         {
717           anUp = gp::DY();
718         }
719         else if (anOrient == V3d_Zneg)
720         {
721           anUp = -gp::DY();
722         }
723       }
724 
725       const Standard_Real anOffset = 2.0; // extra offset to avoid overlapping with triangulation
726       const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension + anOffset);
727       const gp_Ax2 aPosition (aPos, aDir, anUp.Crossed (aDir));
728 
729       Handle(Graphic3d_Text) aText = new Graphic3d_Text ((Standard_ShortReal)myDrawer->TextAspect()->Height());
730       aText->SetText (aLabel);
731       aText->SetOrientation (aPosition);
732       aText->SetOwnAnchorPoint (false);
733       aText->SetHorizontalAlignment(myDrawer->TextAspect()->HorizontalJustification());
734       aText->SetVerticalAlignment  (myDrawer->TextAspect()->VerticalJustification());
735       aTextGroup->AddText (aText);
736     }
737   }
738 
739   // Display box edges
740   {
741     Standard_Integer aNbNodes = 0, aNbTris = 0;
742     for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter)
743     {
744       createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
745     }
746     if (aNbNodes > 0)
747     {
748       Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
749       aNbNodes = aNbTris = 0;
750       for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter)
751       {
752         const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
753         createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient);
754       }
755 
756       Handle(Graphic3d_Group) aGroupEdges = thePrs->NewGroup();
757       aGroupEdges->SetClosed (true);
758       aGroupEdges->SetGroupPrimitivesAspect (myBoxEdgeAspect->Aspect());
759       aGroupEdges->AddPrimitiveArray (aTris);
760     }
761   }
762 
763   // Display box corners
764   {
765     Standard_Integer aNbNodes = 0, aNbTris = 0;
766     for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
767     {
768       createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter);
769     }
770     if (aNbNodes > 0)
771     {
772       Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal);
773       aNbNodes = aNbTris = 0;
774       for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
775       {
776         const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter;
777         createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient);
778       }
779 
780       Handle(Graphic3d_Group) aGroupCorners = thePrs->NewGroup();
781       aGroupCorners->SetClosed (true);
782       aGroupCorners->SetGroupPrimitivesAspect (myBoxCornerAspect->Aspect());
783       aGroupCorners->AddPrimitiveArray (aTris);
784     }
785   }
786 }
787 
788 //=======================================================================
789 //function : ComputeSelection
790 //purpose  :
791 //=======================================================================
ComputeSelection(const Handle (SelectMgr_Selection)& theSelection,const Standard_Integer theMode)792 void AIS_ViewCube::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
793                                      const Standard_Integer theMode)
794 {
795   if (theMode != 0)
796   {
797     return;
798   }
799 
800   for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter)
801   {
802     const V3d_TypeOfOrientation anOri = (V3d_TypeOfOrientation )aPartIter;
803     Standard_Integer aNbNodes = 0, aNbTris = 0;
804     createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, anOri);
805     if (aNbNodes <= 0)
806     {
807       continue;
808     }
809 
810     Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None);
811     aNbNodes = aNbTris = 0;
812     createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOri);
813 
814     Standard_Integer aSensitivity = 2;
815     if (IsBoxCorner (anOri))
816     {
817       aSensitivity = 8;
818     }
819     else if (IsBoxEdge (anOri))
820     {
821       aSensitivity = 4;
822     }
823     Handle(AIS_ViewCubeOwner) anOwner = new AIS_ViewCubeOwner (this, anOri);
824     Handle(AIS_ViewCubeSensitive) aTriSens = new AIS_ViewCubeSensitive (anOwner, aTris);
825     aTriSens->SetSensitivityFactor (aSensitivity);
826     theSelection->Add (aTriSens);
827   }
828 }
829 
830 //=======================================================================
831 //function : Duration
832 //purpose  :
833 //=======================================================================
Duration() const834 Standard_Real AIS_ViewCube::Duration() const
835 {
836   return myViewAnimation->OwnDuration();
837 }
838 
839 //=======================================================================
840 //function : SetDuration
841 //purpose  :
842 //=======================================================================
SetDuration(Standard_Real theDurationSec)843 void AIS_ViewCube::SetDuration (Standard_Real theDurationSec)
844 {
845   myViewAnimation->SetOwnDuration (theDurationSec);
846 }
847 
848 //=======================================================================
849 //function : HasAnimation
850 //purpose  :
851 //=======================================================================
HasAnimation() const852 Standard_Boolean AIS_ViewCube::HasAnimation() const
853 {
854   return !myViewAnimation->IsStopped();
855 }
856 
857 //=======================================================================
858 //function : viewFitAll
859 //purpose  :
860 //=======================================================================
viewFitAll(const Handle (V3d_View)& theView,const Handle (Graphic3d_Camera)& theCamera)861 void AIS_ViewCube::viewFitAll (const Handle(V3d_View)& theView,
862                                const Handle(Graphic3d_Camera)& theCamera)
863 {
864   Bnd_Box aBndBox = myToFitSelected ? GetContext()->BoundingBoxOfSelection() : theView->View()->MinMaxValues();
865   if (aBndBox.IsVoid()
866    && myToFitSelected)
867   {
868     aBndBox = theView->View()->MinMaxValues();
869   }
870   if (!aBndBox.IsVoid())
871   {
872     theView->FitMinMax (theCamera, aBndBox, 0.01, 10.0 * Precision::Confusion());
873   }
874 }
875 
876 //=======================================================================
877 //function : StartAnimation
878 //purpose  :
879 //=======================================================================
StartAnimation(const Handle (AIS_ViewCubeOwner)& theOwner)880 void AIS_ViewCube::StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner)
881 {
882   Handle(V3d_View) aView = GetContext()->LastActiveView();
883   if (theOwner.IsNull()
884    || aView.IsNull())
885   {
886     return;
887   }
888 
889   myStartState->Copy (aView->Camera());
890   myEndState  ->Copy (aView->Camera());
891 
892   {
893     {
894       Handle(Graphic3d_Camera) aBackupCamera = aView->Camera();
895       const bool wasImmediateUpdate = aView->SetImmediateUpdate (false);
896       aView->SetCamera (myEndState);
897       aView->SetProj (theOwner->MainOrientation(), myIsYup);
898       aView->SetCamera (aBackupCamera);
899       aView->SetImmediateUpdate (wasImmediateUpdate);
900     }
901 
902     const gp_Dir aNewDir = myEndState->Direction();
903     if (!myToResetCameraUp
904      && !aNewDir.IsEqual (myStartState->Direction(), Precision::Angular()))
905     {
906       // find the Up direction closest to current instead of default one
907       const gp_Ax1 aNewDirAx1 (gp::Origin(), aNewDir);
908       const gp_Dir anOldUp = myStartState->Up();
909       const gp_Dir anUpList[4] =
910       {
911         myEndState->Up(),
912         myEndState->Up().Rotated (aNewDirAx1, M_PI_2),
913         myEndState->Up().Rotated (aNewDirAx1, M_PI),
914         myEndState->Up().Rotated (aNewDirAx1, M_PI * 1.5),
915       };
916 
917       Standard_Real aBestAngle = Precision::Infinite();
918       gp_Dir anUpBest;
919       for (Standard_Integer anUpIter = 0; anUpIter < 4; ++anUpIter)
920       {
921         Standard_Real anAngle = anUpList[anUpIter].Angle (anOldUp);
922         if (aBestAngle > anAngle)
923         {
924           aBestAngle = anAngle;
925           anUpBest = anUpList[anUpIter];
926         }
927       }
928       myEndState->SetUp (anUpBest);
929     }
930 
931     viewFitAll (aView, myEndState);
932   }
933 
934   myViewAnimation->SetView (aView);
935   myViewAnimation->SetCameraStart (myStartState);
936   myViewAnimation->SetCameraEnd   (myEndState);
937   myViewAnimation->StartTimer (0.0, 1.0, true, false);
938 }
939 
940 //=======================================================================
941 //function : updateAnimation
942 //purpose  :
943 //=======================================================================
updateAnimation()944 Standard_Boolean AIS_ViewCube::updateAnimation()
945 {
946   const Standard_Real aPts = myViewAnimation->UpdateTimer();
947   if (aPts >= myViewAnimation->OwnDuration())
948   {
949     myViewAnimation->Stop();
950     onAnimationFinished();
951     myViewAnimation->SetView (Handle(V3d_View)());
952     return Standard_False;
953   }
954   return Standard_True;
955 }
956 
957 //=======================================================================
958 //function : UpdateAnimation
959 //purpose  :
960 //=======================================================================
UpdateAnimation(const Standard_Boolean theToUpdate)961 Standard_Boolean AIS_ViewCube::UpdateAnimation (const Standard_Boolean theToUpdate)
962 {
963   Handle(V3d_View) aView = myViewAnimation->View();
964   if (!HasAnimation()
965    || !updateAnimation())
966   {
967     return Standard_False;
968   }
969 
970   if (theToUpdate
971   && !aView.IsNull())
972   {
973     aView->IsInvalidated() ? aView->Redraw() : aView->RedrawImmediate();
974   }
975 
976   onAfterAnimation();
977   return Standard_True;
978 }
979 
980 //=======================================================================
981 //function : HandleClick
982 //purpose  :
983 //=======================================================================
HandleClick(const Handle (AIS_ViewCubeOwner)& theOwner)984 void AIS_ViewCube::HandleClick (const Handle(AIS_ViewCubeOwner)& theOwner)
985 {
986   if (!myToAutoStartAnim)
987   {
988     return;
989   }
990 
991   StartAnimation (theOwner);
992   if (!myIsFixedAnimation)
993   {
994     return;
995   }
996   for (; HasAnimation(); )
997   {
998     UpdateAnimation (true);
999   }
1000 }
1001 
1002 //=======================================================================
1003 //function : HilightOwnerWithColor
1004 //purpose  :
1005 //=======================================================================
HilightOwnerWithColor(const Handle (PrsMgr_PresentationManager)& thePrsMgr,const Handle (Prs3d_Drawer)& theStyle,const Handle (SelectMgr_EntityOwner)& theOwner)1006 void AIS_ViewCube::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
1007                                           const Handle(Prs3d_Drawer)& theStyle,
1008                                           const Handle(SelectMgr_EntityOwner)& theOwner)
1009 {
1010   if (theOwner.IsNull()
1011   || !thePrsMgr->IsImmediateModeOn())
1012   {
1013     return;
1014   }
1015 
1016   const Graphic3d_ZLayerId aLayer = theStyle->ZLayer() != Graphic3d_ZLayerId_UNKNOWN ? theStyle->ZLayer() : myDrawer->ZLayer();
1017   const AIS_ViewCubeOwner* aCubeOwner = dynamic_cast<AIS_ViewCubeOwner* >(theOwner.get());
1018 
1019   Handle(Prs3d_Presentation) aHiPrs = GetHilightPresentation (thePrsMgr);
1020   aHiPrs->Clear();
1021   aHiPrs->CStructure()->ViewAffinity = thePrsMgr->StructureManager()->ObjectAffinity (Handle(Standard_Transient)(this));
1022   aHiPrs->SetTransformPersistence (TransformPersistence());
1023   aHiPrs->SetZLayer (aLayer);
1024 
1025   {
1026     Handle(Graphic3d_Group) aGroup = aHiPrs->NewGroup();
1027     aGroup->SetGroupPrimitivesAspect (theStyle->ShadingAspect()->Aspect());
1028     Standard_Integer aNbNodes = 0, aNbTris = 0;
1029     createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, aCubeOwner->MainOrientation());
1030     if (aNbNodes > 0)
1031     {
1032       Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None);
1033       aNbNodes = aNbTris = 0;
1034       createBoxPartTriangles (aTris, aNbNodes, aNbTris, aCubeOwner->MainOrientation());
1035       aGroup->AddPrimitiveArray (aTris);
1036     }
1037   }
1038 
1039   if (thePrsMgr->IsImmediateModeOn())
1040   {
1041     thePrsMgr->AddToImmediateList (aHiPrs);
1042   }
1043 }
1044 
1045 //=======================================================================
1046 //function : HilightSelected
1047 //purpose  :
1048 //=======================================================================
HilightSelected(const Handle (PrsMgr_PresentationManager)&,const SelectMgr_SequenceOfOwner & theSeq)1049 void AIS_ViewCube::HilightSelected (const Handle(PrsMgr_PresentationManager)& ,
1050                                     const SelectMgr_SequenceOfOwner& theSeq)
1051 {
1052   // this method should never be called since AIS_InteractiveObject::HandleClick() has been overridden
1053   if (theSeq.Size() == 1)
1054   {
1055     //HandleClick (Handle(AIS_ViewCubeOwner)::DownCast (theSeq.First()));
1056   }
1057 }
1058