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