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