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