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