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