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