0027818: Visualization - provide an interface to define highlight presentation properties
[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   Handle(Geom_Transformation) aGeomTrsf = new Geom_Transformation (aTrsf);
644   // we explicitly call here setLocalTransformation() of the base class
645   // since AIS_Manipulator::setLocalTransformation() implementation throws exception
646   // as protection from external calls
647   AIS_InteractiveObject::setLocalTransformation (aGeomTrsf);
648   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
649   {
650     myAxes[anIt].Transform (aGeomTrsf);
651   }
652
653   if (myIsZoomPersistentMode)
654   {
655     if (TransformPersistence().IsNull()
656     ||  TransformPersistence()->Mode() != Graphic3d_TMF_ZoomPers
657     || !TransformPersistence()->AnchorPoint().IsEqual (myPosition.Location(), 0.0))
658     {
659       setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, myPosition.Location()));
660     }
661   }
662 }
663
664 //=======================================================================
665 //function : SetSize
666 //purpose  : 
667 //=======================================================================
668 void AIS_Manipulator::SetSize (const Standard_ShortReal theSideLength)
669 {
670   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
671   {
672     myAxes[anIt].SetSize (theSideLength);
673   }
674
675   SetToUpdate();
676 }
677
678 //=======================================================================
679 //function : SetGap
680 //purpose  : 
681 //=======================================================================
682 void AIS_Manipulator::SetGap (const Standard_ShortReal theValue)
683 {
684   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
685   {
686     myAxes[anIt].SetIndent (theValue);
687   }
688
689   SetToUpdate();
690 }
691
692 //=======================================================================
693 //function : DeactivateCurrentMode
694 //purpose  : 
695 //=======================================================================
696 void AIS_Manipulator::DeactivateCurrentMode()
697 {
698   if (!myIsActivationOnDetection)
699   {
700     Handle(Graphic3d_Group) aGroup = getGroup (myCurrentIndex, myCurrentMode);
701     if (aGroup.IsNull())
702     {
703       return;
704     }
705
706     Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
707     anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
708     anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
709     anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
710     anAspect->SetColor (myAxes[myCurrentIndex].Color());
711
712     aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
713   }
714
715   myCurrentIndex = -1;
716   myCurrentMode = AIS_MM_None;
717
718   if (myHasStartedTransformation)
719   {
720     myHasStartedTransformation = Standard_False;
721   }
722 }
723
724 //=======================================================================
725 //function : SetZoomPersistence
726 //purpose  : 
727 //=======================================================================
728 void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
729 {
730   if (myIsZoomPersistentMode != theToEnable)
731   {
732     SetToUpdate();
733   }
734
735   myIsZoomPersistentMode = theToEnable;
736
737   if (!theToEnable)
738   {
739     setTransformPersistence (Handle(Graphic3d_TransformPers)());
740   }
741
742   updateTransformation();
743 }
744
745 //=======================================================================
746 //function : SetTransformPersistence
747 //purpose  :
748 //=======================================================================
749 void AIS_Manipulator::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
750 {
751   Standard_ASSERT_RETURN (!myIsZoomPersistentMode,
752     "AIS_Manipulator::SetTransformPersistence: "
753     "Custom settings are not allowed by this class in ZoomPersistence mode",);
754
755   setTransformPersistence (theTrsfPers);
756 }
757
758 //=======================================================================
759 //function : setTransformPersistence
760 //purpose  : 
761 //=======================================================================
762 void AIS_Manipulator::setTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
763 {
764   AIS_InteractiveObject::SetTransformPersistence (theTrsfPers);
765
766   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
767   {
768     myAxes[anIt].SetTransformPersistence (theTrsfPers);
769   }
770 }
771
772 //=======================================================================
773 //function : setLocalTransformation
774 //purpose  :
775 //=======================================================================
776 void AIS_Manipulator::setLocalTransformation (const Handle(Geom_Transformation)& /*theTrsf*/)
777 {
778   Standard_ASSERT_INVOKE ("AIS_Manipulator::setLocalTransformation: "
779                           "Custom transformation is not supported by this class");
780 }
781
782 //=======================================================================
783 //function : Compute
784 //purpose  : 
785 //=======================================================================
786 void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
787                                const Handle(Prs3d_Presentation)& thePrs,
788                                const Standard_Integer theMode)
789 {
790   if (theMode != AIS_Shaded)
791   {
792     return;
793   }
794
795   thePrs->SetInfiniteState (Standard_True);
796   thePrs->SetMutable (Standard_True);
797   Handle(Graphic3d_Group) aGroup;
798   Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
799   anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
800   anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
801   anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
802
803   // Display center
804   myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
805   aGroup = Prs3d_Root::NewGroup (thePrs);
806   aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
807   aGroup->AddPrimitiveArray (myCenter.Array());
808
809   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
810   {
811     // Display axes
812     aGroup = Prs3d_Root::NewGroup (thePrs);
813
814     Handle(Prs3d_ShadingAspect) anAspectAx = new Prs3d_ShadingAspect (new Graphic3d_AspectFillArea3d(*anAspect->Aspect()));
815     anAspectAx->SetColor (myAxes[anIt].Color());
816     aGroup->SetGroupPrimitivesAspect (anAspectAx->Aspect());
817     myAxes[anIt].Compute (thePrsMgr, thePrs, anAspectAx);
818     myAxes[anIt].SetTransformPersistence (TransformPersistence());
819   }
820
821   updateTransformation();
822 }
823
824 //=======================================================================
825 //function : HilightSelected
826 //purpose  : 
827 //=======================================================================
828 void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
829                                        const SelectMgr_SequenceOfOwner& theSeq)
830 {
831   if (theSeq.IsEmpty())
832   {
833     return;
834   }
835
836   if (myIsActivationOnDetection)
837   {
838     return;
839   }
840
841   if (!theSeq (1)->IsKind (STANDARD_TYPE (AIS_ManipulatorOwner)))
842   {
843     thePM->Color (this, GetContext()->HighlightStyle(), 0);
844     return;
845   }
846
847   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theSeq (1));
848   myHighlightAspect->Aspect()->SetInteriorColor (GetContext()->HighlightStyle()->Color());
849   Handle(Graphic3d_Group) aGroup = getGroup (anOwner->Index(), anOwner->Mode());
850   if (aGroup.IsNull())
851   {
852     return;
853   }
854
855   aGroup->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
856
857   myCurrentIndex = anOwner->Index();
858   myCurrentMode = anOwner->Mode();
859 }
860
861 //=======================================================================
862 //function : ClearSelected
863 //purpose  :
864 //=======================================================================
865 void AIS_Manipulator::ClearSelected()
866 {
867   DeactivateCurrentMode();
868 }
869
870 //=======================================================================
871 //function : HilightOwnerWithColor
872 //purpose  : 
873 //=======================================================================
874 void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
875                                              const Handle(Graphic3d_HighlightStyle)& theStyle,
876                                              const Handle(SelectMgr_EntityOwner)& theOwner)
877 {
878   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
879   Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation (anOwner);
880   if (aPresentation.IsNull())
881   {
882     return;
883   }
884   aPresentation->Highlight (theStyle);
885   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPresentation->Groups());
886        aGroupIter.More(); aGroupIter.Next())
887   {
888     Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue();
889     if (!aGrp.IsNull()
890      && aGrp->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
891     {
892       aGrp->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
893     }
894   }
895   aPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
896   thePM->AddToImmediateList (aPresentation);
897
898   if (myIsActivationOnDetection)
899   {
900     if (HasActiveMode())
901     {
902       DeactivateCurrentMode();
903     }
904
905     myCurrentIndex = anOwner->Index();
906     myCurrentMode = anOwner->Mode();
907   }
908 }
909
910 //=======================================================================
911 //function : ComputeSelection
912 //purpose  : 
913 //=======================================================================
914 void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
915                                         const Standard_Integer theMode)
916 {
917   //Check mode
918   AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
919   if (aMode == AIS_MM_None)
920   {
921     return;
922   }
923   Handle(SelectMgr_EntityOwner) anOwner;
924   if (aMode == AIS_MM_None)
925   {
926     anOwner = new SelectMgr_EntityOwner (this, 5);
927   }
928   Handle(Select3D_SensitiveTriangulation) aTri;
929   if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
930   {
931     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
932     {
933       const Axis& anAxis = myAxes[anIt];
934       if (aMode != AIS_MM_None)
935       {
936         anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
937       }
938       // define sensitivity by line
939       Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
940       aLine->SetSensitivityFactor (15);
941       theSelection->Add (aLine);
942       // enlarge sensitivity by triangulation
943       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorCylinder().Triangulation(), TopLoc_Location(), Standard_True);
944       theSelection->Add (aTri);
945       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrow().Triangulation(), TopLoc_Location(), Standard_True);
946       theSelection->Add (aTri);
947       aTri = new Select3D_SensitiveTriangulation (anOwner, anAxis.TranslatorArrowBottom().Triangulation(), TopLoc_Location(), Standard_True);
948       theSelection->Add (aTri);
949     }
950   }
951
952   if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
953   {
954     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
955     {
956       const Axis& anAxis = myAxes[anIt];
957       if (aMode != AIS_MM_None)
958       {
959         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
960       }
961       // define sensitivity by circle
962       Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
963       Handle(Select3D_SensitiveCircle) aCircle = new Select3D_SensitiveCircle (anOwner, aGeomCircle, Standard_False, anAxis.FacettesNumber());
964       aCircle->SetSensitivityFactor (15);
965       theSelection->Add (aCircle);
966       // enlarge sensitivity by triangulation
967       aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), TopLoc_Location(), Standard_True);
968       theSelection->Add (aTri);
969     }
970   }
971
972   if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
973   {
974     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
975     {
976       if (aMode != AIS_MM_None)
977       {
978         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
979       }
980       // define sensitivity by point
981       Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
982       aPnt->SetSensitivityFactor (15);
983       theSelection->Add (aPnt);
984       // enlarge sensitivity by triangulation
985       aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
986       theSelection->Add (aTri);
987     }
988   }
989 }
990
991 //=======================================================================
992 //class    : Cylinder
993 //function : Init
994 //purpose  : 
995 //=======================================================================
996 void AIS_Manipulator::Cylinder::Init (const Standard_ShortReal theBotRad, const Standard_ShortReal theTopRad,
997                                       const Standard_ShortReal theHeight,
998                                       const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb,
999                                       const gp_Ax1& thePosition)
1000 {
1001   myPosition = thePosition;
1002   myBottomRad = theBotRad;
1003   myTopRad = theTopRad;
1004   myHeight = theHeight;
1005
1006   StdPrs_ToolCylinder aTool (myBottomRad, myTopRad, myHeight, theSlicesNb, theStacksNb);
1007   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
1008   gp_Trsf aTrsf;
1009   aTrsf.SetTransformation (aSystem, gp_Ax3());
1010
1011   aTool.FillArray (myArray, myTriangulation, aTrsf);
1012 }
1013
1014 //=======================================================================
1015 //class    : Disk
1016 //function : Init
1017 //purpose  : 
1018 //=======================================================================
1019 void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
1020                                   const Standard_ShortReal theOuterRadius,
1021                                   const gp_Ax1& thePosition,
1022                                   const Standard_Integer theSlicesNb,
1023                                   const Standard_Integer theStacksNb)
1024 {
1025   myPosition = thePosition;
1026   myInnerRad = theInnerRadius;
1027   myOuterRad = theOuterRadius;
1028
1029   StdPrs_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
1030   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
1031   gp_Trsf aTrsf;
1032   aTrsf.SetTransformation (aSystem, gp_Ax3());
1033   aTool.FillArray (myArray, myTriangulation, aTrsf);
1034 }
1035
1036 //=======================================================================
1037 //class    : Sphere
1038 //function : Init
1039 //purpose  : 
1040 //=======================================================================
1041 void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
1042                                     const gp_Pnt& thePosition,
1043                                     const Standard_Integer theSlicesNb,
1044                                     const Standard_Integer theStacksNb)
1045 {
1046   myPosition = thePosition;
1047   myRadius = theRadius;
1048
1049   StdPrs_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
1050   gp_Trsf aTrsf;
1051   aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
1052   aTool.FillArray (myArray, myTriangulation, aTrsf);
1053 }
1054
1055 //=======================================================================
1056 //class    : Cube
1057 //function : Init
1058 //purpose  : 
1059 //=======================================================================
1060 void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
1061 {
1062   myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
1063
1064   Poly_Array1OfTriangle aPolyTriangles (1, 12);
1065   TColgp_Array1OfPnt aPoints (1, 36);
1066   NCollection_Array1<gp_Dir> aNormals (1, 12);
1067   myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
1068
1069   gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
1070   gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
1071   gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
1072   gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
1073   gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
1074   gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
1075     + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
1076   gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
1077   gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
1078   gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
1079
1080   gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
1081   gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
1082
1083   // Bottom
1084   addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
1085   addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
1086
1087   // Front
1088   addTriangle (2, aV3, aV4, aV5, aFront);
1089   addTriangle (3, aV3, aV5, aTopRight, aFront);
1090
1091   // Back
1092   addTriangle (4, aBottomLeft, aV2, aV7, -aFront);
1093   addTriangle (5, aBottomLeft, aV7, aV6, -aFront);
1094
1095   // aTop
1096   addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
1097   addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
1098
1099   //Left
1100   addTriangle (8, aV6, aV5, aV4, -aRight);
1101   addTriangle (9, aBottomLeft, aV6, aV4, -aRight);
1102
1103   // Right
1104   addTriangle (10, aV3, aTopRight, aV7, aRight);
1105   addTriangle (11, aV3, aV7, aV2, aRight);
1106 }
1107
1108 //=======================================================================
1109 //class    : Cube
1110 //function : addTriangle
1111 //purpose  : 
1112 //=======================================================================
1113 void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
1114                                          const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
1115                                          const gp_Dir& theNormal)
1116 {
1117   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 1, theP1);
1118   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 2, theP2);
1119   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 3, theP3);
1120
1121   myTriangulation->ChangeTriangles().SetValue (theIndex + 1, Poly_Triangle (theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3));
1122   myArray->AddVertex (theP1, theNormal);
1123   myArray->AddVertex (theP2, theNormal);
1124   myArray->AddVertex (theP3, theNormal);
1125 }
1126
1127 //=======================================================================
1128 //class    : Axis
1129 //function : Constructor
1130 //purpose  : 
1131 //=======================================================================
1132 AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
1133                              const Quantity_Color& theColor,
1134                              const Standard_ShortReal theLength)
1135 : myReferenceAxis (theAxis),
1136   myPosition (theAxis),
1137   myColor (theColor),
1138   myHasTranslation (Standard_True),
1139   myLength (theLength),
1140   myAxisRadius (0.5f),
1141   myHasScaling (Standard_True),
1142   myBoxSize (2.0f),
1143   myHasRotation (Standard_True),
1144   myInnerRadius (myLength + myBoxSize),
1145   myDiskThickness (myBoxSize * 0.5f),
1146   myIndent (0.2f),
1147   myFacettesNumber (20),
1148   myCircleRadius (myLength + myBoxSize + myBoxSize * 0.5f * 0.5f)
1149 {
1150   //
1151 }
1152
1153 //=======================================================================
1154 //class    : Axis
1155 //function : Compute
1156 //purpose  : 
1157 //=======================================================================
1158 void AIS_Manipulator::Axis::Compute (const Handle_PrsMgr_PresentationManager3d& thePrsMgr,
1159                                      const Handle(Prs3d_Presentation)& thePrs,
1160                                      const Handle(Prs3d_ShadingAspect)& theAspect)
1161 {
1162   Handle(Graphic3d_Group) aGroup;
1163
1164   if (myHasTranslation)
1165   {
1166     const Standard_ShortReal anArrowLength = 0.25f * myLength;
1167     const Standard_ShortReal aCylinderLength = myLength - anArrowLength;
1168
1169     myCylinder.Init (myAxisRadius, myAxisRadius, aCylinderLength, myFacettesNumber, 2, gp_Ax1 (gp::Origin(), myReferenceAxis.Direction()));
1170
1171     gp_Pnt anArrowBottom (0.0, 0.0, 0.0);
1172     anArrowBottom.Translate (myReferenceAxis.Direction().XYZ() * aCylinderLength);
1173
1174     myArrow.Init (myAxisRadius * 1.5f, 0.0f, anArrowLength, myFacettesNumber, 2, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()));
1175     myArrowBottom.Init (myAxisRadius, myAxisRadius * 1.5f, gp_Ax1 (anArrowBottom, myReferenceAxis.Direction()), myFacettesNumber);
1176     myArrowTipPos = anArrowBottom;
1177
1178     myTranslatorGroup = Prs3d_Root::NewGroup (thePrs);
1179     myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1180     myTranslatorGroup->AddPrimitiveArray (myCylinder.Array());
1181     myTranslatorGroup->AddPrimitiveArray (myArrow.Array());
1182     myTranslatorGroup->AddPrimitiveArray (myArrowBottom.Array());
1183
1184     if (myHighlightTranslator.IsNull())
1185     {
1186       myHighlightTranslator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1187     }
1188
1189     myHighlightTranslator->Clear();
1190     aGroup = Prs3d_Root::CurrentGroup (myHighlightTranslator);
1191     aGroup->AddPrimitiveArray (myCylinder.Array());
1192     aGroup->AddPrimitiveArray (myArrow.Array());
1193     aGroup->AddPrimitiveArray (myArrowBottom.Array());
1194   }
1195
1196   if (myHasScaling)
1197   {
1198     myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
1199     myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
1200
1201     myScalerGroup = Prs3d_Root::NewGroup (thePrs);
1202     myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1203     myScalerGroup->AddPrimitiveArray (myCube.Array());
1204
1205     if (myHighlightScaler.IsNull())
1206     {
1207       myHighlightScaler = new Prs3d_Presentation (thePrsMgr->StructureManager());
1208     }
1209
1210     myHighlightScaler->Clear();
1211     aGroup = Prs3d_Root::CurrentGroup (myHighlightScaler);
1212     aGroup->AddPrimitiveArray (myCube.Array());
1213   }
1214
1215   if (myHasRotation)
1216   {
1217     myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
1218     myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
1219     myRotatorGroup = Prs3d_Root::NewGroup (thePrs);
1220     myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1221     myRotatorGroup->AddPrimitiveArray (myCircle.Array());
1222
1223     if (myHighlightRotator.IsNull())
1224     {
1225       myHighlightRotator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1226     }
1227
1228     myHighlightRotator->Clear();
1229     aGroup = Prs3d_Root::CurrentGroup (myHighlightRotator);
1230     Prs3d_Root::CurrentGroup (myHighlightRotator)->AddPrimitiveArray (myCircle.Array());
1231   }
1232 }