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