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