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