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