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