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