0030477: Visualization - crash in AIS_Manipulator::ObjectTransformation after using...
[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 : SetPart
276 //purpose  : 
277 //=======================================================================
278 void AIS_Manipulator::SetPart (const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled)
279 {
280   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
281   {
282     SetPart (anIt, theMode, theIsEnabled);
283   }
284 }
285
286 //=======================================================================
287 //function : EnableMode
288 //purpose  : 
289 //=======================================================================
290 void AIS_Manipulator::EnableMode (const AIS_ManipulatorMode theMode)
291 {
292   if (!IsAttached())
293   {
294     return;
295   }
296
297   const Handle(AIS_InteractiveContext)& aContext = GetContext();
298   if (aContext.IsNull())
299   {
300     return;
301   }
302
303   aContext->Activate (this, theMode);
304 }
305
306 //=======================================================================
307 //function : attachToBox
308 //purpose  : 
309 //=======================================================================
310 void AIS_Manipulator::attachToBox (const Bnd_Box& theBox)
311 {
312   if (theBox.IsVoid())
313   {
314     return;
315   }
316
317   Standard_Real anXmin = 0.0, anYmin = 0.0, aZmin = 0.0, anXmax = 0.0, anYmax = 0.0, aZmax = 0.0;
318   theBox.Get (anXmin, anYmin, aZmin, anXmax, anYmax, aZmax);
319
320   gp_Ax2 aPosition = gp::XOY();
321   aPosition.SetLocation (gp_Pnt ((anXmin + anXmax) * 0.5, (anYmin + anYmax) * 0.5, (aZmin + aZmax) * 0.5));
322   SetPosition (aPosition);
323 }
324
325 //=======================================================================
326 //function : adjustSize
327 //purpose  : 
328 //=======================================================================
329 void AIS_Manipulator::adjustSize (const Bnd_Box& theBox)
330 {
331   Standard_Real aXmin = 0., aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.0;
332   theBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
333   Standard_Real aXSize = aXmax - aXmin;
334   Standard_Real aYSize = aYmax - aYmin;
335   Standard_Real aZSize  = aZmax  - aZmin;
336
337   SetSize ((Standard_ShortReal) (Max (aXSize, Max (aYSize, aZSize)) * 0.5));
338 }
339
340 //=======================================================================
341 //function : Attach
342 //purpose  : 
343 //=======================================================================
344 void AIS_Manipulator::Attach (const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions)
345 {
346   if (theObject->IsKind (STANDARD_TYPE(AIS_Manipulator)))
347   {
348     return;
349   }
350
351   Handle(AIS_ManipulatorObjectSequence) aSeq = new AIS_ManipulatorObjectSequence();
352   aSeq->Append (theObject);
353   Attach (aSeq, theOptions);
354 }
355
356 //=======================================================================
357 //function : Attach
358 //purpose  : 
359 //=======================================================================
360 void AIS_Manipulator::Attach (const Handle(AIS_ManipulatorObjectSequence)& theObjects, const OptionsForAttach& theOptions)
361 {
362   if (theObjects->Size() < 1)
363   {
364     return;
365   }
366
367   SetOwner (theObjects);
368   Bnd_Box aBox;
369   const Handle(AIS_InteractiveObject)& aCurObject = theObjects->Value (theObjects->Lower());
370   aCurObject->BoundingBox (aBox);
371
372   if (theOptions.AdjustPosition)
373   {
374     attachToBox (aBox);
375   }
376
377   if (theOptions.AdjustSize)
378   {
379     adjustSize (aBox);
380   }
381
382   const Handle(AIS_InteractiveContext)& aContext = Object()->GetContext();
383   if (!aContext.IsNull())
384   {
385     if (!aContext->IsDisplayed (this))
386     {
387       aContext->Display (this, Standard_False);
388     }
389     else
390     {
391       aContext->Update (this, Standard_False);
392       aContext->RecomputeSelectionOnly (this);
393     }
394
395     aContext->Load (this);
396   }
397
398   if (theOptions.EnableModes)
399   {
400     EnableMode (AIS_MM_Rotation);
401     EnableMode (AIS_MM_Translation);
402     EnableMode (AIS_MM_Scaling);
403   }
404 }
405
406 //=======================================================================
407 //function : Detach
408 //purpose  : 
409 //=======================================================================
410 void AIS_Manipulator::Detach()
411 {
412   DeactivateCurrentMode();
413
414   if (!IsAttached())
415   {
416     return;
417   }
418
419   Handle(AIS_InteractiveObject) anObject = Object();
420   const Handle(AIS_InteractiveContext)& aContext = anObject->GetContext();
421   if (!aContext.IsNull())
422   {
423     aContext->Remove (this, Standard_False);
424   }
425
426   SetOwner (NULL);
427 }
428
429 //=======================================================================
430 //function : Objects
431 //purpose  : 
432 //=======================================================================
433 Handle(AIS_ManipulatorObjectSequence) AIS_Manipulator::Objects() const
434 {
435   return Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
436 }
437
438 //=======================================================================
439 //function : Object
440 //purpose  : 
441 //=======================================================================
442 Handle(AIS_InteractiveObject) AIS_Manipulator::Object (const Standard_Integer theIndex) const
443 {
444   Handle(AIS_ManipulatorObjectSequence) anOwner = Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
445
446   Standard_ProgramError_Raise_if (theIndex < anOwner->Lower() || theIndex > anOwner->Upper(), "AIS_Manipulator::Object(): wrong index value");
447
448   if (anOwner.IsNull() || anOwner->IsEmpty())
449   {
450     return NULL;
451   }
452
453   return anOwner->Value (theIndex);
454 }
455
456 //=======================================================================
457 //function : Object
458 //purpose  : 
459 //=======================================================================
460 Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const
461 {
462   return Object (1);
463 }
464
465 //=======================================================================
466 //function : ObjectTransformation
467 //purpose  : 
468 //=======================================================================
469 Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer theMaxX, const Standard_Integer theMaxY,
470                                                         const Handle(V3d_View)& theView, gp_Trsf& theTrsf)
471 {
472   // Initialize start reference data
473   if (!myHasStartedTransformation)
474   {
475     myStartTrsfs.Clear();
476     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
477     for (AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects); anObjIter.More(); anObjIter.Next())
478     {
479       myStartTrsfs.Append (anObjIter.Value()->LocalTransformation());
480     }
481     myStartPosition = myPosition;
482   }
483
484   // Get 3d point with projection vector
485   Graphic3d_Vec3d anInputPoint, aProj;
486   theView->ConvertWithProj (theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z());
487   const gp_Lin anInputLine (gp_Pnt (anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir (aProj.x(), aProj.y(), aProj.z()));
488   switch (myCurrentMode)
489   {
490     case AIS_MM_Translation:
491     case AIS_MM_Scaling:
492     {
493       const gp_Lin aLine (myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
494       Extrema_ExtElC anExtrema (anInputLine, aLine, Precision::Angular());
495       if (!anExtrema.IsDone()
496         || anExtrema.IsParallel()
497         || anExtrema.NbExt() != 1)
498       {
499         // translation cannot be done co-directed with camera
500         return Standard_False;
501       }
502
503       Extrema_POnCurv anExPnts[2];
504       anExtrema.Points (1, anExPnts[0], anExPnts[1]);
505       const gp_Pnt aNewPosition = anExPnts[1].Value();
506       if (!myHasStartedTransformation)
507       {
508         myStartPick = aNewPosition;
509         myHasStartedTransformation = Standard_True;
510         return Standard_True;
511       }
512       else if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
513       {
514         return Standard_False;
515       }
516
517       gp_Trsf aNewTrsf;
518       if (myCurrentMode == AIS_MM_Translation)
519       {
520         aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
521         theTrsf *= aNewTrsf;
522       }
523       else if (myCurrentMode == AIS_MM_Scaling)
524       {
525         if (aNewPosition.Distance (myStartPosition.Location()) < Precision::Confusion())
526         {
527           return Standard_False;
528         }
529
530         Standard_Real aCoeff = myStartPosition.Location().Distance (aNewPosition)
531                              / myStartPosition.Location().Distance (myStartPick);
532         aNewTrsf.SetScale (myPosition.Location(), aCoeff);
533         theTrsf = aNewTrsf;
534       }
535       return Standard_True;
536     }
537     case AIS_MM_Rotation:
538     {
539       const gp_Pnt aPosLoc   = myStartPosition.Location();
540       const gp_Ax1 aCurrAxis = getAx1FromAx2Dir (myStartPosition, myCurrentIndex);
541       IntAna_IntConicQuad aIntersector (anInputLine, gp_Pln (aPosLoc, aCurrAxis.Direction()), Precision::Angular(), Precision::Intersection());
542       if (!aIntersector.IsDone()
543         || aIntersector.IsParallel()
544         || aIntersector.NbPoints() < 1)
545       {
546         return Standard_False;
547       }
548
549       const gp_Pnt aNewPosition = aIntersector.Point (1);
550       if (!myHasStartedTransformation)
551       {
552         myStartPick = aNewPosition;
553         myHasStartedTransformation = Standard_True;
554         gp_Dir aStartAxis = gce_MakeDir (aPosLoc, myStartPick);
555         myPrevState = aStartAxis.AngleWithRef (gce_MakeDir(aPosLoc, aNewPosition), aCurrAxis.Direction());
556         return Standard_True;
557       }
558
559       if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
560       {
561         return Standard_False;
562       }
563
564       gp_Dir aStartAxis = aPosLoc.IsEqual (myStartPick, Precision::Confusion())
565         ? getAx1FromAx2Dir (myStartPosition, (myCurrentIndex + 1) % 3).Direction()
566         : gce_MakeDir (aPosLoc, myStartPick);
567
568       gp_Dir aCurrentAxis = gce_MakeDir (aPosLoc, aNewPosition);
569       Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, aCurrAxis.Direction());
570
571       // Change value of an angle if it should have different sign.
572       if (anAngle * myPrevState < 0 && Abs (anAngle) < M_PI_2)
573       {
574         Standard_Real aSign = myPrevState > 0 ? -1.0 : 1.0;
575         anAngle = aSign * (M_PI * 2 - anAngle);
576       }
577
578       if (Abs (anAngle) < Precision::Confusion())
579       {
580         return Standard_False;
581       }
582
583       gp_Trsf aNewTrsf;
584       aNewTrsf.SetRotation (aCurrAxis, anAngle);
585       theTrsf *= aNewTrsf;
586       myPrevState = anAngle;
587       return Standard_True;
588     }
589     case AIS_MM_None:
590     {
591       return Standard_False;
592     }
593   }
594   return Standard_False;
595 }
596
597 //=======================================================================
598 //function : StartTransform
599 //purpose  : 
600 //=======================================================================
601 void AIS_Manipulator::StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView)
602 {
603   if (myHasStartedTransformation)
604   {
605     return;
606   }
607
608   gp_Trsf aTrsf;
609   ObjectTransformation (theX, theY, theView, aTrsf);
610 }
611
612 //=======================================================================
613 //function : StopTransform
614 //purpose  : 
615 //=======================================================================
616 void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
617 {
618   if (!IsAttached() || !myHasStartedTransformation)
619   {
620     return;
621   }
622
623   myHasStartedTransformation = Standard_False;
624   if (theToApply)
625   {
626     return;
627   }
628
629   Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
630   AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
631   NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
632   for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
633   {
634     anObjIter.ChangeValue()->SetLocalTransformation (aTrsfIter.Value());
635   }
636   SetPosition (myStartPosition);
637 }
638
639 //=======================================================================
640 //function : Transform
641 //purpose  : 
642 //=======================================================================
643 void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
644 {
645   if (!IsAttached() || !myHasStartedTransformation)
646   {
647     return;
648   }
649
650   {
651     Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
652     AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
653     NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
654     for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
655     {
656       anObjIter.ChangeValue()->SetLocalTransformation (theTrsf * aTrsfIter.Value());
657     }
658   }
659
660   if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation)
661    || (myCurrentMode == AIS_MM_Rotation    && myBehaviorOnTransform.FollowRotation))
662   {
663     gp_Pnt aPos  = myStartPosition.Location().Transformed (theTrsf);
664     gp_Dir aVDir = myStartPosition.Direction().Transformed (theTrsf);
665     gp_Dir aXDir = myStartPosition.XDirection().Transformed (theTrsf);
666     SetPosition (gp_Ax2 (aPos, aVDir, aXDir));
667   }
668 }
669
670 //=======================================================================
671 //function : Transform
672 //purpose  : 
673 //=======================================================================
674 gp_Trsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
675                                     const Handle(V3d_View)& theView)
676 {
677   gp_Trsf aTrsf;
678   if (ObjectTransformation (thePX, thePY, theView, aTrsf))
679   {
680     Transform (aTrsf);
681   }
682
683   return aTrsf;
684 }
685
686 //=======================================================================
687 //function : SetPosition
688 //purpose  : 
689 //=======================================================================
690 void AIS_Manipulator::SetPosition (const gp_Ax2& thePosition)
691 {
692   if (!myPosition.Location().IsEqual (thePosition.Location(), Precision::Confusion())
693    || !myPosition.Direction().IsEqual (thePosition.Direction(), Precision::Angular())
694    || !myPosition.XDirection().IsEqual (thePosition.XDirection(), Precision::Angular()))
695   {
696     myPosition = thePosition;
697     myAxes[0].SetPosition (getAx1FromAx2Dir (thePosition, 0));
698     myAxes[1].SetPosition (getAx1FromAx2Dir (thePosition, 1));
699     myAxes[2].SetPosition (getAx1FromAx2Dir (thePosition, 2));
700     updateTransformation();
701   }
702 }
703
704 //=======================================================================
705 //function : updateTransformation
706 //purpose  : set local transformation to avoid graphics recomputation
707 //=======================================================================
708 void AIS_Manipulator::updateTransformation()
709 {
710   gp_Trsf aTrsf;
711
712   if (!myIsZoomPersistentMode)
713   {
714     aTrsf.SetTransformation (myPosition, gp::XOY());
715   }
716   else
717   {
718     const gp_Dir& aVDir = myPosition.Direction();
719     const gp_Dir& aXDir = myPosition.XDirection();
720     aTrsf.SetTransformation (gp_Ax2 (gp::Origin(), aVDir, aXDir), gp::XOY());
721   }
722
723   Handle(Geom_Transformation) aGeomTrsf = new Geom_Transformation (aTrsf);
724   // we explicitly call here setLocalTransformation() of the base class
725   // since AIS_Manipulator::setLocalTransformation() implementation throws exception
726   // as protection from external calls
727   AIS_InteractiveObject::setLocalTransformation (aGeomTrsf);
728   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
729   {
730     myAxes[anIt].Transform (aGeomTrsf);
731   }
732
733   if (myIsZoomPersistentMode)
734   {
735     if (TransformPersistence().IsNull()
736     ||  TransformPersistence()->Mode() != Graphic3d_TMF_ZoomPers
737     || !TransformPersistence()->AnchorPoint().IsEqual (myPosition.Location(), 0.0))
738     {
739       setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, myPosition.Location()));
740     }
741   }
742 }
743
744 //=======================================================================
745 //function : SetSize
746 //purpose  : 
747 //=======================================================================
748 void AIS_Manipulator::SetSize (const Standard_ShortReal theSideLength)
749 {
750   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
751   {
752     myAxes[anIt].SetSize (theSideLength);
753   }
754
755   SetToUpdate();
756 }
757
758 //=======================================================================
759 //function : SetGap
760 //purpose  : 
761 //=======================================================================
762 void AIS_Manipulator::SetGap (const Standard_ShortReal theValue)
763 {
764   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
765   {
766     myAxes[anIt].SetIndent (theValue);
767   }
768
769   SetToUpdate();
770 }
771
772 //=======================================================================
773 //function : DeactivateCurrentMode
774 //purpose  : 
775 //=======================================================================
776 void AIS_Manipulator::DeactivateCurrentMode()
777 {
778   if (!myIsActivationOnDetection)
779   {
780     Handle(Graphic3d_Group) aGroup = getGroup (myCurrentIndex, myCurrentMode);
781     if (aGroup.IsNull())
782     {
783       return;
784     }
785
786     Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
787     anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
788     anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
789     anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
790     anAspect->SetColor (myAxes[myCurrentIndex].Color());
791
792     aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
793   }
794
795   myCurrentIndex = -1;
796   myCurrentMode = AIS_MM_None;
797
798   if (myHasStartedTransformation)
799   {
800     myHasStartedTransformation = Standard_False;
801   }
802 }
803
804 //=======================================================================
805 //function : SetZoomPersistence
806 //purpose  : 
807 //=======================================================================
808 void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
809 {
810   if (myIsZoomPersistentMode != theToEnable)
811   {
812     SetToUpdate();
813   }
814
815   myIsZoomPersistentMode = theToEnable;
816
817   if (!theToEnable)
818   {
819     setTransformPersistence (Handle(Graphic3d_TransformPers)());
820   }
821
822   updateTransformation();
823 }
824
825 //=======================================================================
826 //function : SetTransformPersistence
827 //purpose  :
828 //=======================================================================
829 void AIS_Manipulator::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
830 {
831   Standard_ASSERT_RETURN (!myIsZoomPersistentMode,
832     "AIS_Manipulator::SetTransformPersistence: "
833     "Custom settings are not allowed by this class in ZoomPersistence mode",);
834
835   setTransformPersistence (theTrsfPers);
836 }
837
838 //=======================================================================
839 //function : setTransformPersistence
840 //purpose  : 
841 //=======================================================================
842 void AIS_Manipulator::setTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
843 {
844   AIS_InteractiveObject::SetTransformPersistence (theTrsfPers);
845
846   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
847   {
848     myAxes[anIt].SetTransformPersistence (theTrsfPers);
849   }
850 }
851
852 //=======================================================================
853 //function : setLocalTransformation
854 //purpose  :
855 //=======================================================================
856 void AIS_Manipulator::setLocalTransformation (const Handle(Geom_Transformation)& /*theTrsf*/)
857 {
858   Standard_ASSERT_INVOKE ("AIS_Manipulator::setLocalTransformation: "
859                           "Custom transformation is not supported by this class");
860 }
861
862 //=======================================================================
863 //function : Compute
864 //purpose  : 
865 //=======================================================================
866 void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
867                                const Handle(Prs3d_Presentation)& thePrs,
868                                const Standard_Integer theMode)
869 {
870   if (theMode != AIS_Shaded)
871   {
872     return;
873   }
874
875   thePrs->SetInfiniteState (Standard_True);
876   thePrs->SetMutable (Standard_True);
877   Handle(Graphic3d_Group) aGroup;
878   Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
879   anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
880   anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
881   anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
882
883   // Display center
884   myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
885   aGroup = Prs3d_Root::NewGroup (thePrs);
886   aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
887   aGroup->AddPrimitiveArray (myCenter.Array());
888
889   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
890   {
891     // Display axes
892     aGroup = Prs3d_Root::NewGroup (thePrs);
893
894     Handle(Prs3d_ShadingAspect) anAspectAx = new Prs3d_ShadingAspect (new Graphic3d_AspectFillArea3d(*anAspect->Aspect()));
895     anAspectAx->SetColor (myAxes[anIt].Color());
896     aGroup->SetGroupPrimitivesAspect (anAspectAx->Aspect());
897     myAxes[anIt].Compute (thePrsMgr, thePrs, anAspectAx);
898     myAxes[anIt].SetTransformPersistence (TransformPersistence());
899   }
900
901   updateTransformation();
902 }
903
904 //=======================================================================
905 //function : HilightSelected
906 //purpose  : 
907 //=======================================================================
908 void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
909                                        const SelectMgr_SequenceOfOwner& theSeq)
910 {
911   if (theSeq.IsEmpty())
912   {
913     return;
914   }
915
916   if (myIsActivationOnDetection)
917   {
918     return;
919   }
920
921   if (!theSeq (1)->IsKind (STANDARD_TYPE (AIS_ManipulatorOwner)))
922   {
923     thePM->Color (this, GetContext()->HighlightStyle(), 0);
924     return;
925   }
926
927   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theSeq (1));
928   myHighlightAspect->Aspect()->SetInteriorColor (GetContext()->HighlightStyle()->Color());
929   Handle(Graphic3d_Group) aGroup = getGroup (anOwner->Index(), anOwner->Mode());
930   if (aGroup.IsNull())
931   {
932     return;
933   }
934
935   aGroup->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
936
937   myCurrentIndex = anOwner->Index();
938   myCurrentMode = anOwner->Mode();
939 }
940
941 //=======================================================================
942 //function : ClearSelected
943 //purpose  :
944 //=======================================================================
945 void AIS_Manipulator::ClearSelected()
946 {
947   DeactivateCurrentMode();
948 }
949
950 //=======================================================================
951 //function : HilightOwnerWithColor
952 //purpose  : 
953 //=======================================================================
954 void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
955                                              const Handle(Prs3d_Drawer)& theStyle,
956                                              const Handle(SelectMgr_EntityOwner)& theOwner)
957 {
958   Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
959   Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation (anOwner);
960   if (aPresentation.IsNull())
961   {
962     return;
963   }
964   aPresentation->Highlight (theStyle);
965   for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPresentation->Groups());
966        aGroupIter.More(); aGroupIter.Next())
967   {
968     Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue();
969     if (!aGrp.IsNull()
970      && aGrp->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
971     {
972       aGrp->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
973     }
974   }
975   aPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
976   thePM->AddToImmediateList (aPresentation);
977
978   if (myIsActivationOnDetection)
979   {
980     if (HasActiveMode())
981     {
982       DeactivateCurrentMode();
983     }
984
985     myCurrentIndex = anOwner->Index();
986     myCurrentMode = anOwner->Mode();
987   }
988 }
989
990 //=======================================================================
991 //function : ComputeSelection
992 //purpose  : 
993 //=======================================================================
994 void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
995                                         const Standard_Integer theMode)
996 {
997   //Check mode
998   AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
999   if (aMode == AIS_MM_None)
1000   {
1001     return;
1002   }
1003   Handle(SelectMgr_EntityOwner) anOwner;
1004   if (aMode == AIS_MM_None)
1005   {
1006     anOwner = new SelectMgr_EntityOwner (this, 5);
1007   }
1008
1009   if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
1010   {
1011     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
1012     {
1013       if (!myAxes[anIt].HasTranslation())
1014       {
1015         continue;
1016       }
1017       const Axis& anAxis = myAxes[anIt];
1018       if (aMode != AIS_MM_None)
1019       {
1020         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
1021       }
1022       // define sensitivity by line
1023       Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
1024       aLine->SetSensitivityFactor (15);
1025       theSelection->Add (aLine);
1026
1027       // enlarge sensitivity by triangulation
1028       Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
1029       aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location());
1030       theSelection->Add (aTri);
1031     }
1032   }
1033
1034   if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
1035   {
1036     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
1037     {
1038       if (!myAxes[anIt].HasRotation())
1039       {
1040         continue;
1041       }
1042       const Axis& anAxis = myAxes[anIt];
1043       if (aMode != AIS_MM_None)
1044       {
1045         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
1046       }
1047       // define sensitivity by circle
1048       Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
1049       Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
1050       aCircle->SetSensitivityFactor (15);
1051       theSelection->Add (aCircle);
1052       // enlarge sensitivity by triangulation
1053       Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
1054       theSelection->Add (aTri);
1055     }
1056   }
1057
1058   if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
1059   {
1060     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
1061     {
1062       if (!myAxes[anIt].HasScaling())
1063       {
1064         continue;
1065       }
1066       if (aMode != AIS_MM_None)
1067       {
1068         anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
1069       }
1070       // define sensitivity by point
1071       Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
1072       aPnt->SetSensitivityFactor (15);
1073       theSelection->Add (aPnt);
1074       // enlarge sensitivity by triangulation
1075       Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
1076       theSelection->Add (aTri);
1077     }
1078   }
1079 }
1080
1081 //=======================================================================
1082 //class    : Disk
1083 //function : Init
1084 //purpose  : 
1085 //=======================================================================
1086 void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
1087                                   const Standard_ShortReal theOuterRadius,
1088                                   const gp_Ax1& thePosition,
1089                                   const Standard_Integer theSlicesNb,
1090                                   const Standard_Integer theStacksNb)
1091 {
1092   myPosition = thePosition;
1093   myInnerRad = theInnerRadius;
1094   myOuterRad = theOuterRadius;
1095
1096   Prs3d_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
1097   gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
1098   gp_Trsf aTrsf;
1099   aTrsf.SetTransformation (aSystem, gp_Ax3());
1100   aTool.FillArray (myArray, myTriangulation, aTrsf);
1101 }
1102
1103 //=======================================================================
1104 //class    : Sphere
1105 //function : Init
1106 //purpose  : 
1107 //=======================================================================
1108 void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
1109                                     const gp_Pnt& thePosition,
1110                                     const Standard_Integer theSlicesNb,
1111                                     const Standard_Integer theStacksNb)
1112 {
1113   myPosition = thePosition;
1114   myRadius = theRadius;
1115
1116   Prs3d_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
1117   gp_Trsf aTrsf;
1118   aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
1119   aTool.FillArray (myArray, myTriangulation, aTrsf);
1120 }
1121
1122 //=======================================================================
1123 //class    : Cube
1124 //function : Init
1125 //purpose  : 
1126 //=======================================================================
1127 void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
1128 {
1129   myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
1130
1131   Poly_Array1OfTriangle aPolyTriangles (1, 12);
1132   TColgp_Array1OfPnt aPoints (1, 36);
1133   NCollection_Array1<gp_Dir> aNormals (1, 12);
1134   myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
1135
1136   gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
1137   gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
1138   gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
1139   gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
1140   gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
1141   gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
1142     + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
1143   gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
1144   gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
1145   gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
1146
1147   gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
1148   gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
1149
1150   // Bottom
1151   addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
1152   addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
1153
1154   // Front
1155   addTriangle (2, aV3, aV4, aV5, aFront);
1156   addTriangle (3, aV3, aV5, aTopRight, aFront);
1157
1158   // Back
1159   addTriangle (4, aBottomLeft, aV2, aV7, -aFront);
1160   addTriangle (5, aBottomLeft, aV7, aV6, -aFront);
1161
1162   // aTop
1163   addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
1164   addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
1165
1166   //Left
1167   addTriangle (8, aV6, aV5, aV4, -aRight);
1168   addTriangle (9, aBottomLeft, aV6, aV4, -aRight);
1169
1170   // Right
1171   addTriangle (10, aV3, aTopRight, aV7, aRight);
1172   addTriangle (11, aV3, aV7, aV2, aRight);
1173 }
1174
1175 //=======================================================================
1176 //class    : Cube
1177 //function : addTriangle
1178 //purpose  : 
1179 //=======================================================================
1180 void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
1181                                          const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
1182                                          const gp_Dir& theNormal)
1183 {
1184   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 1, theP1);
1185   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 2, theP2);
1186   myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 3, theP3);
1187
1188   myTriangulation->ChangeTriangles().SetValue (theIndex + 1, Poly_Triangle (theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3));
1189   myArray->AddVertex (theP1, theNormal);
1190   myArray->AddVertex (theP2, theNormal);
1191   myArray->AddVertex (theP3, theNormal);
1192 }
1193
1194 //=======================================================================
1195 //class    : Axis
1196 //function : Constructor
1197 //purpose  : 
1198 //=======================================================================
1199 AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
1200                              const Quantity_Color& theColor,
1201                              const Standard_ShortReal theLength)
1202 : myReferenceAxis (theAxis),
1203   myPosition (theAxis),
1204   myColor (theColor),
1205   myHasTranslation (Standard_True),
1206   myLength (theLength),
1207   myAxisRadius (0.5f),
1208   myHasScaling (Standard_True),
1209   myBoxSize (2.0f),
1210   myHasRotation (Standard_True),
1211   myInnerRadius (myLength + myBoxSize),
1212   myDiskThickness (myBoxSize * 0.5f),
1213   myIndent (0.2f),
1214   myFacettesNumber (20),
1215   myCircleRadius (myLength + myBoxSize + myBoxSize * 0.5f * 0.5f)
1216 {
1217   //
1218 }
1219
1220 //=======================================================================
1221 //class    : Axis
1222 //function : Compute
1223 //purpose  :
1224 //=======================================================================
1225
1226 void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
1227                                      const Handle(Prs3d_Presentation)& thePrs,
1228                                      const Handle(Prs3d_ShadingAspect)& theAspect)
1229 {
1230   if (myHasTranslation)
1231   {
1232     const Standard_Real anArrowLength   = 0.25 * myLength;
1233     const Standard_Real aCylinderLength = myLength - anArrowLength;
1234     myArrowTipPos = gp_Pnt (0.0, 0.0, 0.0).Translated (myReferenceAxis.Direction().XYZ() * aCylinderLength);
1235
1236     myTriangleArray = Prs3d_Arrow::DrawShaded (gp_Ax1(gp::Origin(), myReferenceAxis.Direction()),
1237                                                myAxisRadius,
1238                                                myLength,
1239                                                myAxisRadius * 1.5,
1240                                                anArrowLength,
1241                                                myFacettesNumber);
1242     myTranslatorGroup = Prs3d_Root::NewGroup (thePrs);
1243     myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1244     myTranslatorGroup->AddPrimitiveArray (myTriangleArray);
1245
1246     if (myHighlightTranslator.IsNull())
1247     {
1248       myHighlightTranslator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1249     }
1250     else
1251     {
1252       myHighlightTranslator->Clear();
1253     }
1254     {
1255       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightTranslator);
1256       aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1257       aGroup->AddPrimitiveArray (myTriangleArray);
1258     }
1259   }
1260
1261   if (myHasScaling)
1262   {
1263     myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
1264     myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
1265
1266     myScalerGroup = Prs3d_Root::NewGroup (thePrs);
1267     myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1268     myScalerGroup->AddPrimitiveArray (myCube.Array());
1269
1270     if (myHighlightScaler.IsNull())
1271     {
1272       myHighlightScaler = new Prs3d_Presentation (thePrsMgr->StructureManager());
1273     }
1274     else
1275     {
1276       myHighlightScaler->Clear();
1277     }
1278     {
1279       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightScaler);
1280       aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1281       aGroup->AddPrimitiveArray (myCube.Array());
1282     }
1283   }
1284
1285   if (myHasRotation)
1286   {
1287     myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
1288     myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
1289     myRotatorGroup = Prs3d_Root::NewGroup (thePrs);
1290     myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1291     myRotatorGroup->AddPrimitiveArray (myCircle.Array());
1292
1293     if (myHighlightRotator.IsNull())
1294     {
1295       myHighlightRotator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1296     }
1297     else
1298     {
1299       myHighlightRotator->Clear();
1300     }
1301     {
1302       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightRotator);
1303       aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1304       aGroup->AddPrimitiveArray (myCircle.Array());
1305     }
1306   }
1307 }