0027038: Visualization - add new presentation for object manipulation
[occt.git] / src / AIS / AIS_Manipulator.cxx
1 // Created on: 2015-12-23
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2015 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_Manipulator.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <AIS_ManipulatorOwner.hxx>
20 #include <gce_MakeDir.hxx>
21 #include <GeomAPI_ExtremaCurveCurve.hxx>
22 #include <GeomAPI_IntCS.hxx>
23 #include <Geom_Circle.hxx>
24 #include <Geom_Line.hxx>
25 #include <Geom_Plane.hxx>
26 #include <Geom_Transformation.hxx>
27 #include <Prs3d_Root.hxx>
28 #include <Prs3d_ShadingAspect.hxx>
29 #include <Select3D_SensitiveCircle.hxx>
30 #include <Select3D_SensitivePoint.hxx>
31 #include <Select3D_SensitiveSegment.hxx>
32 #include <Select3D_SensitiveTriangulation.hxx>
33 #include <SelectMgr_SequenceOfOwner.hxx>
34 #include <StdPrs_ToolDisk.hxx>
35 #include <StdPrs_ToolCylinder.hxx>
36 #include <StdPrs_ToolSphere.hxx>
37 #include <TColgp_Array1OfPnt.hxx>
38 #include <V3d_View.hxx>
39
40 IMPLEMENT_STANDARD_HANDLE (AIS_Manipulator, AIS_InteractiveObject)
41 IMPLEMENT_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject)
42
43 IMPLEMENT_HSEQUENCE(AIS_ManipulatorObjectSequence)
44
45 //=======================================================================
46 //function : init
47 //purpose  : 
48 //=======================================================================
49 void AIS_Manipulator::init()
50 {
51   // Create axis in the default coordinate system. The custom position is applied in local transformation.
52   myAxes[0] = Axis (gp::OX(), Quantity_NOC_RED);
53   myAxes[1] = Axis (gp::OY(), Quantity_NOC_GREEN);
54   myAxes[2] = Axis (gp::OZ(), Quantity_NOC_BLUE1);
55
56   Graphic3d_MaterialAspect aShadingMaterial;
57   aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
58   aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
59
60   myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
61   myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
62   myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE);
63   myDrawer->ShadingAspect()->SetMaterial (aShadingMaterial);
64
65   Graphic3d_MaterialAspect aHilightMaterial;
66   aHilightMaterial.SetColor (Quantity_NOC_AZURE);
67   aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
68   aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
69   aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
70   aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
71   aHilightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
72
73   myHighlightAspect = new Prs3d_ShadingAspect();
74   myHighlightAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
75   myHighlightAspect->SetMaterial (aHilightMaterial);
76
77   SetSize (100);
78   SetZLayer (Graphic3d_ZLayerId_Topmost);
79 }
80
81 //=======================================================================
82 //function : getHighlightPresentation
83 //purpose  : 
84 //=======================================================================
85 Handle(Prs3d_Presentation) AIS_Manipulator::getHighlightPresentation (const Handle(SelectMgr_EntityOwner)& theOwner) const
86 {
87   Handle(Prs3d_Presentation) aDummyPrs;
88   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
89   if (anOwner.IsNull())
90   {
91     return aDummyPrs;
92   }
93
94   switch (anOwner->Mode())
95   {
96     case AIS_MM_Translation: return myAxes[anOwner->Index()].TranslatorHighlightPrs();
97     case AIS_MM_Rotation   : return myAxes[anOwner->Index()].RotatorHighlightPrs();
98     case AIS_MM_Scaling    : return myAxes[anOwner->Index()].ScalerHighlightPrs();
99     case AIS_MM_None       : break;
100   }
101
102   return aDummyPrs;
103 }
104
105 //=======================================================================
106 //function : getGroup
107 //purpose  : 
108 //=======================================================================
109 Handle(Graphic3d_Group) AIS_Manipulator::getGroup (const Standard_Integer theIndex, const AIS_ManipulatorMode theMode) const
110 {
111   Handle(Graphic3d_Group) aDummyGroup;
112
113   if (theIndex < 0 || theIndex > 2)
114   {
115     return aDummyGroup;
116   }
117
118   switch (theMode)
119   {
120     case AIS_MM_Translation: return myAxes[theIndex].TranslatorGroup();
121     case AIS_MM_Rotation   : return myAxes[theIndex].RotatorGroup();
122     case AIS_MM_Scaling    : return myAxes[theIndex].ScalerGroup();
123     case AIS_MM_None       : break;
124   }
125
126   return aDummyGroup;
127 }
128
129 //=======================================================================
130 //function : Constructor
131 //purpose  : 
132 //=======================================================================
133 AIS_Manipulator::AIS_Manipulator()
134 : myPosition (gp::XOY()),
135   myCurrentIndex (-1),
136   myCurrentMode (AIS_MM_None),
137   myIsActivationOnDetection (Standard_False),
138   myIsZoomPersistentMode (Standard_True),
139   myHasStartedTransformation (Standard_False),
140   myStartPosition (gp::XOY()),
141   myStartPick (0.0, 0.0, 0.0),
142   myPrevState (0.0)
143 {
144   SetInfiniteState();
145   SetMutable (Standard_True);
146   SetDisplayMode (AIS_Shaded);
147   init();
148 }
149
150 //=======================================================================
151 //function : Constructor
152 //purpose  : 
153 //=======================================================================
154 AIS_Manipulator::AIS_Manipulator (const gp_Ax2& thePosition)
155 : myPosition (thePosition),
156   myCurrentIndex (-1),
157   myCurrentMode (AIS_MM_None),
158   myIsActivationOnDetection (Standard_False),
159   myIsZoomPersistentMode (Standard_True),
160   myHasStartedTransformation (Standard_False),
161   myStartPosition (gp::XOY()),
162   myStartPick (0.0, 0.0, 0.0),
163   myPrevState (0.0)
164 {
165   SetInfiniteState();
166   SetMutable (Standard_True);
167   SetDisplayMode (AIS_Shaded);
168   init();
169 }
170
171 //=======================================================================
172 //function : SetPart
173 //purpose  : 
174 //=======================================================================
175 void AIS_Manipulator::SetPart (const Standard_Integer theAxisIndex, const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled)
176 {
177   Standard_ProgramError_Raise_if (theAxisIndex < 0 || theAxisIndex > 2, "AIS_Manipulator::SetMode(): axis index should be between 0 and 2");
178   switch (theMode)
179   {
180     case AIS_MM_Translation:
181       myAxes[theAxisIndex].SetTranslation (theIsEnabled);
182       break;
183
184     case AIS_MM_Rotation:
185       myAxes[theAxisIndex].SetRotation (theIsEnabled);
186       break;
187
188     case AIS_MM_Scaling:
189       myAxes[theAxisIndex].SetScaling (theIsEnabled);
190       break;
191
192     case AIS_MM_None:
193       break;
194   }
195 }
196
197 //=======================================================================
198 //function : EnableMode
199 //purpose  : 
200 //=======================================================================
201 void AIS_Manipulator::EnableMode (const AIS_ManipulatorMode theMode)
202 {
203   if (!IsAttached())
204   {
205     return;
206   }
207
208   const Handle(AIS_InteractiveContext)& aContext = GetContext();
209   if (aContext.IsNull())
210   {
211     return;
212   }
213
214   aContext->Activate (this, theMode);
215 }
216
217 //=======================================================================
218 //function : attachToBox
219 //purpose  : 
220 //=======================================================================
221 void AIS_Manipulator::attachToBox (const Bnd_Box& theBox)
222 {
223   if (theBox.IsVoid())
224   {
225     return;
226   }
227
228   Standard_Real anXmin = 0.0, anYmin = 0.0, aZmin = 0.0, anXmax = 0.0, anYmax = 0.0, aZmax = 0.0;
229   theBox.Get (anXmin, anYmin, aZmin, anXmax, anYmax, aZmax);
230
231   gp_Ax2 aPosition = gp::XOY();
232   aPosition.SetLocation (gp_Pnt ((anXmin + anXmax) * 0.5, (anYmin + anYmax) * 0.5, (aZmin + aZmax) * 0.5));
233   SetPosition (aPosition);
234 }
235
236 //=======================================================================
237 //function : adjustSize
238 //purpose  : 
239 //=======================================================================
240 void AIS_Manipulator::adjustSize (const Bnd_Box& theBox)
241 {
242   Standard_Real aXmin = 0., aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.0;
243   theBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
244   Standard_Real aXSize = aXmax - aXmin;
245   Standard_Real aYSize = aYmax - aYmin;
246   Standard_Real aZSize  = aZmax  - aZmin;
247
248   SetSize ((Standard_ShortReal) (Max (aXSize, Max (aYSize, aZSize)) * 0.5));
249 }
250
251 //=======================================================================
252 //function : Attach
253 //purpose  : 
254 //=======================================================================
255 void AIS_Manipulator::Attach (const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions)
256 {
257   if (theObject->IsKind (STANDARD_TYPE(AIS_Manipulator)))
258   {
259     return;
260   }
261
262   Handle(AIS_ManipulatorObjectSequence) aSeq = new AIS_ManipulatorObjectSequence();
263   aSeq->Append (theObject);
264   Attach (aSeq, theOptions);
265 }
266
267 //=======================================================================
268 //function : Attach
269 //purpose  : 
270 //=======================================================================
271 void AIS_Manipulator::Attach (const Handle(AIS_ManipulatorObjectSequence)& theObjects, const OptionsForAttach& theOptions)
272 {
273   if (theObjects->Size() < 1)
274   {
275     return;
276   }
277
278   SetOwner (theObjects);
279   Bnd_Box aBox;
280   const Handle(AIS_InteractiveObject)& aCurObject = theObjects->Value (theObjects->Lower());
281   aCurObject->BoundingBox (aBox);
282
283   if (theOptions.AdjustPosition)
284   {
285     attachToBox (aBox);
286   }
287
288   if (theOptions.AdjustSize)
289   {
290     adjustSize (aBox);
291   }
292
293   const Handle(AIS_InteractiveContext)& aContext = Object()->GetContext();
294   if (!aContext.IsNull())
295   {
296     if (!aContext->IsDisplayed (this))
297     {
298       aContext->Display (this, Standard_False);
299     }
300     else
301     {
302       aContext->Update (this, Standard_False);
303       aContext->RecomputeSelectionOnly (this);
304     }
305
306     aContext->Load (this);
307     aContext->CurrentViewer()->RedrawImmediate();
308   }
309
310   if (theOptions.EnableModes)
311   {
312     EnableMode (AIS_MM_Rotation);
313     EnableMode (AIS_MM_Translation);
314     EnableMode (AIS_MM_Scaling);
315   }
316 }
317
318 //=======================================================================
319 //function : Detach
320 //purpose  : 
321 //=======================================================================
322 void AIS_Manipulator::Detach()
323 {
324   DeactivateCurrentMode();
325
326   if (!IsAttached())
327   {
328     return;
329   }
330
331   Handle(AIS_InteractiveObject) anObject = Object();
332   const Handle(AIS_InteractiveContext)& aContext = anObject->GetContext();
333   if (!aContext.IsNull())
334   {
335     aContext->Remove (this, Standard_False);
336   }
337
338   SetOwner (NULL);
339 }
340
341 //=======================================================================
342 //function : Objects
343 //purpose  : 
344 //=======================================================================
345 Handle(AIS_ManipulatorObjectSequence) AIS_Manipulator::Objects() const
346 {
347   return Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
348 }
349
350 //=======================================================================
351 //function : Object
352 //purpose  : 
353 //=======================================================================
354 Handle(AIS_InteractiveObject) AIS_Manipulator::Object (const Standard_Integer theIndex) const
355 {
356   Handle(AIS_ManipulatorObjectSequence) anOwner = Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
357
358   Standard_ProgramError_Raise_if (theIndex < anOwner->Lower() || theIndex > anOwner->Upper(), "AIS_Manipulator::Object(): wrong index value");
359
360   if (anOwner.IsNull() || anOwner->IsEmpty())
361   {
362     return NULL;
363   }
364
365   return anOwner->Value (theIndex);
366 }
367
368 //=======================================================================
369 //function : Object
370 //purpose  : 
371 //=======================================================================
372 Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const
373 {
374   return Object (1);
375 }
376
377 //=======================================================================
378 //function : ObjectTransformation
379 //purpose  : 
380 //=======================================================================
381 Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer theMaxX, const Standard_Integer theMaxY,
382                                                         const Handle(V3d_View)& theView, gp_Trsf& theTrsf)
383 {
384   // Initialize start reference data
385   if (!myHasStartedTransformation)
386   {
387     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
388     myStartTrsfs.Clear();
389     for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
390     {
391       myStartTrsfs.Append (anObjects->Value (anIt)->LocalTransformation());
392     }
393     myStartPosition = myPosition;
394   }
395
396   // Get 3d point with projection vector
397   Graphic3d_Vec3d anInputPoint;
398   Graphic3d_Vec3d aProj;
399   theView->ConvertWithProj (theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z());
400   gp_Lin anInputLine (gp_Pnt (anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir (aProj.x(), aProj.y(), aProj.z()));
401   gp_Pnt aNewPosition = gp::Origin();
402
403   switch (myCurrentMode)
404   {
405     case AIS_MM_Translation:
406     {
407       gp_Lin aLine (myStartPick, myAxes[myCurrentIndex].Position().Direction());
408       Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
409       Handle(Geom_Curve) aCurve = new Geom_Line (aLine);
410       GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
411       gp_Pnt aP1, aP2;
412       anExtrema.NearestPoints (aP1, aP2);
413       aNewPosition = aP2;
414
415       if (!myHasStartedTransformation)
416       {
417         myStartPick = aNewPosition;
418         myHasStartedTransformation = Standard_True;
419         return Standard_True;
420       }
421
422       if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
423       {
424         return Standard_False;
425       }
426
427       gp_Trsf aNewTrsf;
428       aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
429       theTrsf *= aNewTrsf;
430       break;
431     }
432     case AIS_MM_Rotation:
433     {
434       Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
435       Handle(Geom_Surface) aSurface = new Geom_Plane (myPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
436       GeomAPI_IntCS aIntersector (anInputCurve, aSurface);
437       if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1)
438       {
439         return Standard_False;
440       }
441
442       aNewPosition = aIntersector.Point (1);
443
444       if (!myHasStartedTransformation)
445       {
446         myStartPick = aNewPosition;
447         myHasStartedTransformation = Standard_True;
448         gp_Dir aStartAxis = gce_MakeDir (myPosition.Location(), myStartPick);
449         myPrevState = aStartAxis.AngleWithRef (gce_MakeDir(myPosition.Location(), aNewPosition), myAxes[myCurrentIndex].Position().Direction());
450         return Standard_True;
451       }
452
453       if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
454       {
455         return Standard_False;
456       }
457
458       gp_Dir aStartAxis = myPosition.Location().IsEqual (myStartPick, Precision::Confusion())
459         ? myAxes[(myCurrentIndex + 1) % 3].Position().Direction()
460         : gce_MakeDir (myPosition.Location(), myStartPick);
461
462       gp_Dir aCurrentAxis = gce_MakeDir (myPosition.Location(), aNewPosition);
463       Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, myAxes[myCurrentIndex].Position().Direction());
464
465       // Change value of an angle if it should have different sign.
466       if (anAngle * myPrevState < 0 && Abs (anAngle) < M_PI_2)
467       {
468         Standard_ShortReal aSign = myPrevState > 0 ? -1.0f : 1.0f;
469         anAngle = aSign * (M_PI * 2 - anAngle);
470       }
471
472       if (Abs (anAngle) < Precision::Confusion())
473       {
474         return Standard_False;
475       }
476
477       gp_Trsf aNewTrsf;
478       aNewTrsf.SetRotation (myAxes[myCurrentIndex].Position(), anAngle);
479       theTrsf *= aNewTrsf;
480       myPrevState = anAngle;
481       break;
482     }
483     case AIS_MM_Scaling:
484     {
485       gp_Lin aLine (myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
486       Handle(Geom_Curve) anInputCurve = new Geom_Line (anInputLine);
487       Handle(Geom_Curve) aCurve = new Geom_Line (aLine);
488       GeomAPI_ExtremaCurveCurve anExtrema (anInputCurve, aCurve);
489       gp_Pnt aTmp;
490       anExtrema.NearestPoints (aTmp, aNewPosition);
491
492       if (!myHasStartedTransformation)
493       {
494         myStartPick = aNewPosition;
495         myHasStartedTransformation = Standard_True;
496         return Standard_True;
497       }
498
499       if (aNewPosition.Distance (myStartPick) < Precision::Confusion() 
500        || aNewPosition.Distance (myStartPosition.Location()) < Precision::Confusion())
501       {
502         return Standard_False;
503       }
504
505       Standard_Real aCoeff = myStartPosition.Location().Distance (aNewPosition)
506                            / myStartPosition.Location().Distance (myStartPick);
507       gp_Trsf aNewTrsf;
508       aNewTrsf.SetScale (myPosition.Location(), aCoeff);
509
510       theTrsf = aNewTrsf;
511       break;
512     }
513     case AIS_MM_None:
514       return Standard_False;
515   }
516
517   return Standard_True;
518 }
519
520 //=======================================================================
521 //function : StartTransform
522 //purpose  : 
523 //=======================================================================
524 void AIS_Manipulator::StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView)
525 {
526   if (myHasStartedTransformation)
527   {
528     return;
529   }
530
531   gp_Trsf aTrsf;
532   ObjectTransformation (theX, theY, theView, aTrsf);
533 }
534
535 //=======================================================================
536 //function : StopTransform
537 //purpose  : 
538 //=======================================================================
539 void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
540 {
541   if (!IsAttached() || !myHasStartedTransformation)
542   {
543     return;
544   }
545
546   myHasStartedTransformation = Standard_False;
547
548   if (!theToApply)
549   {
550     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
551
552     for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
553     {
554       anObjects->Value (anIt)->SetLocalTransformation (myStartTrsfs(anIt));
555     }
556
557     SetPosition (myStartPosition);
558   }
559 }
560
561 //=======================================================================
562 //function : Transform
563 //purpose  : 
564 //=======================================================================
565 void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
566 {
567   if (!IsAttached() || !myHasStartedTransformation)
568   {
569     return;
570   }
571
572   Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
573
574   for (Standard_Integer anIt = anObjects->Lower(); anIt <= anObjects->Upper(); ++anIt)
575   {
576     anObjects->Value (anIt)->SetLocalTransformation (theTrsf * myStartTrsfs(anIt));
577   }
578
579   if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation)
580    || (myCurrentMode == AIS_MM_Rotation    && myBehaviorOnTransform.FollowRotation))
581   {
582     gp_Pnt aPos  = myStartPosition.Location().Transformed (theTrsf);
583     gp_Dir aVDir = myStartPosition.Direction().Transformed (theTrsf);
584     gp_Dir aXDir = myStartPosition.XDirection().Transformed (theTrsf);
585     SetPosition (gp_Ax2 (aPos, aVDir, aXDir));
586   }
587 }
588
589 //=======================================================================
590 //function : Transform
591 //purpose  : 
592 //=======================================================================
593 gp_Trsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
594                                     const Handle(V3d_View)& theView)
595 {
596   gp_Trsf aTrsf;
597   if (ObjectTransformation (thePX, thePY, theView, aTrsf))
598   {
599     Transform (aTrsf);
600   }
601
602   return aTrsf;
603 }
604
605 //=======================================================================
606 //function : SetPosition
607 //purpose  : 
608 //=======================================================================
609 void AIS_Manipulator::SetPosition (const gp_Ax2& thePosition)
610 {
611   if (!myPosition.Location().IsEqual (thePosition.Location(), Precision::Confusion())
612    || !myPosition.Direction().IsEqual (thePosition.Direction(), Precision::Angular())
613    || !myPosition.XDirection().IsEqual (thePosition.XDirection(), Precision::Angular()))
614   {
615     myPosition = thePosition;
616     myAxes[0].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.XDirection()));
617     myAxes[1].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.YDirection()));
618     myAxes[2].SetPosition (gp_Ax1 (myPosition.Location(), myPosition.Direction()));
619
620     updateTransformation();
621   }
622 }
623
624 //=======================================================================
625 //function : updateTransformation
626 //purpose  : set local transformation to avoid graphics recomputation
627 //=======================================================================
628 void AIS_Manipulator::updateTransformation()
629 {
630   gp_Trsf aTrsf;
631
632   if (!myIsZoomPersistentMode)
633   {
634     aTrsf.SetTransformation (myPosition, gp::XOY());
635   }
636   else
637   {
638     const gp_Dir& aVDir = myPosition.Direction();
639     const gp_Dir& aXDir = myPosition.XDirection();
640     aTrsf.SetTransformation (gp_Ax2 (gp::Origin(), aVDir, aXDir), gp::XOY());
641   }
642
643   AIS_InteractiveObject::SetLocalTransformation (aTrsf);
644
645   Handle(Geom_Transformation) aGeomTrsf = new Geom_Transformation (this->Transformation());
646
647   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
648   {
649     myAxes[anIt].Transform (aGeomTrsf);
650   }
651
652   if (myIsZoomPersistentMode)
653   {
654     if (!(GetTransformPersistenceMode () == Graphic3d_TMF_ZoomPers
655        && GetTransformPersistencePoint().IsEqual (myPosition.Location(), 0.)))
656     {
657       setTransformPersistence (Graphic3d_TMF_ZoomPers, myPosition.Location());
658     }
659   }
660 }
661
662 //=======================================================================
663 //function : SetSize
664 //purpose  : 
665 //=======================================================================
666 void AIS_Manipulator::SetSize (const Standard_ShortReal theSideLength)
667 {
668   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
669   {
670     myAxes[anIt].SetSize (theSideLength);
671   }
672
673   SetToUpdate();
674 }
675
676 //=======================================================================
677 //function : SetGap
678 //purpose  : 
679 //=======================================================================
680 void AIS_Manipulator::SetGap (const Standard_ShortReal theValue)
681 {
682   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
683   {
684     myAxes[anIt].SetIndent (theValue);
685   }
686
687   SetToUpdate();
688 }
689
690 //=======================================================================
691 //function : DeactivateCurrentMode
692 //purpose  : 
693 //=======================================================================
694 void AIS_Manipulator::DeactivateCurrentMode()
695 {
696   if (!myIsActivationOnDetection)
697   {
698     Handle(Graphic3d_Group) aGroup = getGroup (myCurrentIndex, myCurrentMode);
699     if (aGroup.IsNull())
700     {
701       return;
702     }
703
704     Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
705     anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
706     anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
707     anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
708     anAspect->SetColor (myAxes[myCurrentIndex].Color());
709
710     aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
711   }
712
713   myCurrentIndex = -1;
714   myCurrentMode = AIS_MM_None;
715
716   if (myHasStartedTransformation)
717   {
718     myHasStartedTransformation = Standard_False;
719   }
720 }
721
722 //=======================================================================
723 //function : SetZoomPersistence
724 //purpose  : 
725 //=======================================================================
726 void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
727 {
728   if (myIsZoomPersistentMode != theToEnable)
729   {
730     SetToUpdate();
731   }
732
733   myIsZoomPersistentMode = theToEnable;
734
735   if (!theToEnable)
736   {
737     setTransformPersistence (Graphic3d_TMF_None, gp::Origin());
738   }
739
740   updateTransformation();
741 }
742
743 //=======================================================================
744 //function : SetTransformPersistence
745 //purpose  : 
746 //=======================================================================
747 void AIS_Manipulator::SetTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint)
748 {
749   Standard_ASSERT_RETURN (!myIsZoomPersistentMode,
750     "AIS_Manipulator::SetTransformPersistence: "
751     "Custom settings are not supported by this class in ZoomPersistence mode",);
752
753   setTransformPersistence (theFlag, thePoint);
754 }
755
756 //=======================================================================
757 //function : setTransformPersistence
758 //purpose  : 
759 //=======================================================================
760 void AIS_Manipulator::setTransformPersistence (const Graphic3d_TransModeFlags& theFlag, const gp_Pnt& thePoint)
761 {
762   AIS_InteractiveObject::SetTransformPersistence (theFlag, thePoint);
763
764   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
765   {
766     myAxes[anIt].SetTransformPersistence (theFlag, thePoint);
767   }
768 }
769
770 //=======================================================================
771 //function : SetLocalTransformation
772 //purpose  : 
773 //=======================================================================
774 void AIS_Manipulator::SetLocalTransformation (const gp_Trsf& /*theTransformation*/)
775 {
776   Standard_ASSERT_INVOKE (
777     "AIS_Manipulator::SetLocalTransformation: "
778     "Custom transformation is not supported by this class");
779 }
780
781 //=======================================================================
782 //function : Compute
783 //purpose  : 
784 //=======================================================================
785 void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
786                                const Handle(Prs3d_Presentation)& thePrs,
787                                const Standard_Integer theMode)
788 {
789   if (theMode != AIS_Shaded)
790   {
791     return;
792   }
793
794   thePrs->SetInfiniteState (Standard_True);
795   thePrs->SetMutable (Standard_True);
796   Handle(Graphic3d_Group) aGroup;
797   Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
798   anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
799   anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
800   anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
801
802   // Display center
803   myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
804   aGroup = Prs3d_Root::NewGroup (thePrs);
805   aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
806   aGroup->AddPrimitiveArray (myCenter.Array());
807
808   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
809   {
810     // Display axes
811     aGroup = Prs3d_Root::NewGroup (thePrs);
812     anAspect->SetColor (myAxes[anIt].Color());
813     aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
814     myAxes[anIt].Compute (thePrsMgr, thePrs, anAspect);
815     myAxes[anIt].SetTransformPersistence (GetTransformPersistenceMode(),
816                                           GetTransformPersistencePoint());
817   }
818
819   updateTransformation();
820 }
821
822 //=======================================================================
823 //function : HilightSelected
824 //purpose  : 
825 //=======================================================================
826 void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
827                                        const SelectMgr_SequenceOfOwner& theSeq)
828 {
829   if (theSeq.IsEmpty())
830   {
831     return;
832   }
833
834   if (myIsActivationOnDetection)
835   {
836     return;
837   }
838
839   if (!theSeq (1)->IsKind (STANDARD_TYPE (AIS_ManipulatorOwner)))
840   {
841     thePM->Color (this, GetContext()->HilightColor(), 0);
842     return;
843   }
844
845   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theSeq (1));
846   myHighlightAspect->Aspect()->SetInteriorColor (GetContext()->HilightColor());
847   Handle(Graphic3d_Group) aGroup = getGroup (anOwner->Index(), anOwner->Mode());
848   if (aGroup.IsNull())
849   {
850     return;
851   }
852
853   aGroup->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
854
855   myCurrentIndex = anOwner->Index();
856   myCurrentMode = anOwner->Mode();
857 }
858
859 //=======================================================================
860 //function : ClearSelected
861 //purpose  :
862 //=======================================================================
863 void AIS_Manipulator::ClearSelected()
864 {
865   DeactivateCurrentMode();
866 }
867
868 //=======================================================================
869 //function : HilightOwnerWithColor
870 //purpose  : 
871 //=======================================================================
872 void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, const Quantity_NameOfColor theColor, const Handle(SelectMgr_EntityOwner)& theOwner)
873 {
874   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
875   Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation (anOwner);
876   if (aPresentation.IsNull())
877   {
878     return;
879   }
880   aPresentation->Highlight (Aspect_TOHM_COLOR, theColor);
881   aPresentation->SetShadingAspect (myHighlightAspect);
882   aPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
883   thePM->AddToImmediateList (aPresentation);
884
885   if (myIsActivationOnDetection)
886   {
887     if (HasActiveMode())
888     {
889       DeactivateCurrentMode();
890     }
891
892     myCurrentIndex = anOwner->Index();
893     myCurrentMode = anOwner->Mode();
894   }
895 }
896
897 //=======================================================================
898 //function : ComputeSelection
899 //purpose  : 
900 //=======================================================================
901 void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
902                                         const Standard_Integer theMode)
903 {
904   //Check mode
905   AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
906   if (aMode == AIS_MM_None)
907   {
908     return;
909   }
910   Handle(SelectMgr_EntityOwner) anOwner;
911   if (aMode == AIS_MM_None)
912   {
913     anOwner = new SelectMgr_EntityOwner (this, 5);
914   }
915   Handle(Select3D_SensitiveTriangulation) aTri;
916   if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
917   {
918     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
919     {
920       const Axis& anAxis = myAxes[anIt];
921       if (aMode != AIS_MM_None)
922       {
923         anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
924       }
925       // define sensitivity by line
926       Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
927       aLine->SetSensitivityFactor (15);
928       theSelection->Add (aLine);
929       // enlarge sensitivity by triangulation
930       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorCylinder().Triangulation(), TopLoc_Location(), Standard_True);
931       theSelection->Add (aTri);
932       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrow().Triangulation(), TopLoc_Location(), Standard_True);
933       theSelection->Add (aTri);
934       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrowBottom().Triangulation(), TopLoc_Location(), Standard_True);
935       theSelection->Add (aTri);
936     }
937   }
938
939   if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
940   {
941     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
942     {
943       const Axis& anAxis = myAxes[anIt];
944       if (aMode != AIS_MM_None)
945       {
946         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
947       }
948       // define sensitivity by circle
949       Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
950       Handle(Select3D_SensitiveCircle) aCircle = new Select3D_SensitiveCircle (anOwner, aGeomCircle, Standard_False, anAxis.FacettesNumber());
951       aCircle->SetSensitivityFactor (15);
952       theSelection->Add (aCircle);
953       // enlarge sensitivity by triangulation
954       aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), TopLoc_Location(), Standard_True);
955       theSelection->Add (aTri);
956     }
957   }
958
959   if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
960   {
961     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
962     {
963       if (aMode != AIS_MM_None)
964       {
965         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
966       }
967       // define sensitivity by point
968       Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
969       aPnt->SetSensitivityFactor (15);
970       theSelection->Add (aPnt);
971       // enlarge sensitivity by triangulation
972       aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
973       theSelection->Add (aTri);
974     }
975   }
976 }
977
978 //=======================================================================
979 //class    : Cylinder
980 //function : Init
981 //purpose  : 
982 //=======================================================================
983 void AIS_Manipulator::Cylinder::Init (const Standard_ShortReal theBotRad, const Standard_ShortReal theTopRad,
984                                       const Standard_ShortReal theHeight,
985                                       const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb,
986                                       const gp_Ax1& thePosition)
987 {
988   myPosition = thePosition;
989   myBottomRad = theBotRad;
990   myTopRad = theTopRad;
991   myHeight = theHeight;
992
993   StdPrs_ToolCylinder aTool (myBottomRad, myTopRad, myHeight, theSlicesNb, theStacksNb);
994   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
995   gp_Trsf aTrsf;
996   aTrsf.SetTransformation (aSystem, gp_Ax3());
997
998   aTool.FillArray (myArray, myTriangulation, aTrsf);
999 }
1000
1001 //=======================================================================
1002 //class    : Disk
1003 //function : Init
1004 //purpose  : 
1005 //=======================================================================
1006 void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
1007                                   const Standard_ShortReal theOuterRadius,
1008                                   const gp_Ax1& thePosition,
1009                                   const Standard_Integer theSlicesNb,
1010                                   const Standard_Integer theStacksNb)
1011 {
1012   myPosition = thePosition;
1013   myInnerRad = theInnerRadius;
1014   myOuterRad = theOuterRadius;
1015
1016   StdPrs_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
1017   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
1018   gp_Trsf aTrsf;
1019   aTrsf.SetTransformation (aSystem, gp_Ax3());
1020   aTool.FillArray (myArray, myTriangulation, aTrsf);
1021 }
1022
1023 //=======================================================================
1024 //class    : Sphere
1025 //function : Init
1026 //purpose  : 
1027 //=======================================================================
1028 void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
1029                                     const gp_Pnt& thePosition,
1030                                     const Standard_Integer theSlicesNb,
1031                                     const Standard_Integer theStacksNb)
1032 {
1033   myPosition = thePosition;
1034   myRadius = theRadius;
1035
1036   StdPrs_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
1037   gp_Trsf aTrsf;
1038   aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
1039   aTool.FillArray (myArray, myTriangulation, aTrsf);
1040 }
1041
1042 //=======================================================================
1043 //class    : Cube
1044 //function : Init
1045 //purpose  : 
1046 //=======================================================================
1047 void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
1048 {
1049   myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
1050
1051   Poly_Array1OfTriangle aPolyTriangles (1, 12);
1052   TColgp_Array1OfPnt aPoints (1, 36);
1053   NCollection_Array1<gp_Dir> aNormals (1, 12);
1054   myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
1055
1056   gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
1057   gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
1058   gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
1059   gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
1060   gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
1061   gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
1062     + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
1063   gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
1064   gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
1065   gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
1066
1067   gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
1068   gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
1069
1070   // Bottom
1071   addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
1072   addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
1073
1074   // Front
1075   addTriangle (2, aV3, aV4, aV5, aFront);
1076   addTriangle (3, aV3, aV5, aTopRight, aFront);
1077
1078   // Back
1079   addTriangle (4, aBottomLeft, aV2, aV7, -aFront);
1080   addTriangle (5, aBottomLeft, aV7, aV6, -aFront);
1081
1082   // aTop
1083   addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
1084   addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
1085
1086   //Left
1087   addTriangle (8, aV6, aV5, aV4, -aRight);
1088   addTriangle (9, aBottomLeft, aV6, aV4, -aRight);
1089
1090   // Right
1091   addTriangle (10, aV3, aTopRight, aV7, aRight);
1092   addTriangle (11, aV3, aV7, aV2, aRight);
1093 }
1094
1095 //=======================================================================
1096 //class    : Cube
1097 //function : addTriangle
1098 //purpose  : 
1099 //=======================================================================
1100 void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
1101                                          const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
1102                                          const gp_Dir& theNormal)
1103 {
1104   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 1, theP1);
1105   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 2, theP2);
1106   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 3, theP3);
1107
1108   myTriangulation->ChangeTriangles().SetValue (theIndex + 1, Poly_Triangle (theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3));
1109   myArray->AddVertex (theP1, theNormal);
1110   myArray->AddVertex (theP2, theNormal);
1111   myArray->AddVertex (theP3, theNormal);
1112 }
1113
1114 //=======================================================================
1115 //class    : Axis
1116 //function : Constructor
1117 //purpose  : 
1118 //=======================================================================
1119 AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
1120                              const Quantity_Color& theColor,
1121                              const Standard_ShortReal theLength)
1122 : myReferenceAxis (theAxis),
1123   myPosition (theAxis),
1124   myColor (theColor),
1125   myHasTranslation (Standard_True),
1126   myLength (theLength),
1127   myAxisRadius (0.5f),
1128   myHasScaling (Standard_True),
1129   myBoxSize (2.0f),
1130   myHasRotation (Standard_True),
1131   myInnerRadius (myLength + myBoxSize),
1132   myDiskThickness (myBoxSize * 0.5f),
1133   myIndent (0.2f),
1134   myFacettesNumber (20),
1135   myCircleRadius (myLength + myBoxSize + myBoxSize * 0.5f * 0.5f)
1136 {
1137   //
1138 }
1139
1140 //=======================================================================
1141 //class    : Axis
1142 //function : Compute
1143 //purpose  : 
1144 //=======================================================================
1145 void AIS_Manipulator::Axis::Compute (const Handle_PrsMgr_PresentationManager3d& thePrsMgr,
1146                                      const Handle(Prs3d_Presentation)& thePrs,
1147                                      const Handle(Prs3d_ShadingAspect)& theAspect)
1148 {
1149   Handle(Graphic3d_Group) aGroup;
1150
1151   if (myHasTranslation)
1152   {
1153     const Standard_ShortReal anArrowLength = 0.25f * myLength;
1154     const Standard_ShortReal aCylinderLength = myLength - anArrowLength;
1155
1156     myCylinder.Init (myAxisRadius, myAxisRadius, aCylinderLength, myFacettesNumber, 2, gp_Ax1 (gp::Origin(), myReferenceAxis.Direction()));
1157
1158     gp_Pnt anArrowBottom (0.0, 0.0, 0.0);
1159     anArrowBottom.Translate (myReferenceAxis.Direction().XYZ() * aCylinderLength);
1160
1161     myArrow.Init (myAxisRadius * 1.5f, 0.0f, anArrowLength, myFacettesNumber, 2, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()));
1162     myArrowBottom.Init (myAxisRadius, myAxisRadius * 1.5f, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()), myFacettesNumber);
1163     myArrowTipPos = anArrowBottom;
1164
1165     myTranslatorGroup = Prs3d_Root::NewGroup (thePrs);
1166     myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1167     myTranslatorGroup->AddPrimitiveArray (myCylinder.Array());
1168     myTranslatorGroup->AddPrimitiveArray (myArrow.Array());
1169     myTranslatorGroup->AddPrimitiveArray (myArrowBottom.Array());
1170
1171     if (myHighlightTranslator.IsNull())
1172     {
1173       myHighlightTranslator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1174     }
1175
1176     myHighlightTranslator->Clear();
1177     aGroup = Prs3d_Root::CurrentGroup (myHighlightTranslator);
1178     aGroup->AddPrimitiveArray (myCylinder.Array());
1179     aGroup->AddPrimitiveArray (myArrow.Array());
1180     aGroup->AddPrimitiveArray (myArrowBottom.Array());
1181   }
1182
1183   if (myHasScaling)
1184   {
1185     myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
1186     myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
1187
1188     myScalerGroup = Prs3d_Root::NewGroup (thePrs);
1189     myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1190     myScalerGroup->AddPrimitiveArray (myCube.Array());
1191
1192     if (myHighlightScaler.IsNull())
1193     {
1194       myHighlightScaler = new Prs3d_Presentation (thePrsMgr->StructureManager());
1195     }
1196
1197     myHighlightScaler->Clear();
1198     aGroup = Prs3d_Root::CurrentGroup (myHighlightScaler);
1199     aGroup->AddPrimitiveArray (myCube.Array());
1200   }
1201
1202   if (myHasRotation)
1203   {
1204     myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
1205     myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
1206     myRotatorGroup = Prs3d_Root::NewGroup (thePrs);
1207     myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1208     myRotatorGroup->AddPrimitiveArray (myCircle.Array());
1209
1210     if (myHighlightRotator.IsNull())
1211     {
1212       myHighlightRotator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1213     }
1214
1215     myHighlightRotator->Clear();
1216     aGroup = Prs3d_Root::CurrentGroup (myHighlightRotator);
1217     Prs3d_Root::CurrentGroup (myHighlightRotator)->AddPrimitiveArray (myCircle.Array());
1218   }
1219 }