1 // Created on: 2015-12-23
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2015 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <AIS_Manipulator.hxx>
18 #include <AIS_InteractiveContext.hxx>
19 #include <AIS_ManipulatorOwner.hxx>
20 #include <Extrema_ExtElC.hxx>
21 #include <gce_MakeDir.hxx>
22 #include <Geom_Circle.hxx>
23 #include <Geom_Transformation.hxx>
24 #include <IntAna_IntConicQuad.hxx>
25 #include <Prs3d_Arrow.hxx>
26 #include <Prs3d_Root.hxx>
27 #include <Prs3d_ShadingAspect.hxx>
28 #include <Prs3d_ToolDisk.hxx>
29 #include <Prs3d_ToolSphere.hxx>
30 #include <Select3D_SensitiveCircle.hxx>
31 #include <Select3D_SensitivePoint.hxx>
32 #include <Select3D_SensitiveSegment.hxx>
33 #include <Select3D_SensitiveTriangulation.hxx>
34 #include <Select3D_SensitivePrimitiveArray.hxx>
35 #include <SelectMgr_SequenceOfOwner.hxx>
36 #include <TColgp_Array1OfPnt.hxx>
37 #include <V3d_View.hxx>
39 IMPLEMENT_STANDARD_HANDLE (AIS_Manipulator, AIS_InteractiveObject)
40 IMPLEMENT_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject)
42 IMPLEMENT_HSEQUENCE(AIS_ManipulatorObjectSequence)
46 //! Return Ax1 for specified direction of Ax2.
47 static gp_Ax1 getAx1FromAx2Dir (const gp_Ax2& theAx2,
52 case 0: return gp_Ax1 (theAx2.Location(), theAx2.XDirection());
53 case 1: return gp_Ax1 (theAx2.Location(), theAx2.YDirection());
54 case 2: return theAx2.Axis();
56 throw Standard_ProgramError ("AIS_Manipulator - Invalid axis index");
59 //! Auxiliary tool for filtering picking ray.
60 class ManipSensRotation
64 ManipSensRotation (const gp_Dir& thePlaneNormal) : myPlaneNormal (thePlaneNormal), myAngleTol (10.0 * M_PI / 180.0) {}
66 //! Checks if picking ray can be used for detection.
67 Standard_Boolean isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const
69 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
71 return Standard_False;
74 const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt());
75 return !aRay.IsNormal (myPlaneNormal, myAngleTol);
79 Standard_Real myAngleTol;
82 //! Sensitive circle with filtering picking ray.
83 class ManipSensCircle : public Select3D_SensitiveCircle, public ManipSensRotation
87 ManipSensCircle (const Handle(SelectBasics_EntityOwner)& theOwnerId,
88 const Handle(Geom_Circle)& theCircle,
89 const Standard_Integer theNbPnts)
90 : Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False, theNbPnts),
91 ManipSensRotation (theCircle->Position().Direction()) {}
93 //! Checks whether the circle overlaps current selecting volume
94 virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
95 SelectBasics_PickResult& thePickResult) Standard_OVERRIDE
97 return isValidRay (theMgr)
98 && Select3D_SensitiveCircle::Matches (theMgr, thePickResult);
102 //! Sensitive triangulation with filtering picking ray.
103 class ManipSensTriangulation : public Select3D_SensitiveTriangulation, public ManipSensRotation
106 ManipSensTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
107 const Handle(Poly_Triangulation)& theTrg,
108 const gp_Dir& thePlaneNormal)
109 : Select3D_SensitiveTriangulation (theOwnerId, theTrg, TopLoc_Location(), Standard_True),
110 ManipSensRotation (thePlaneNormal) {}
112 //! Checks whether the circle overlaps current selecting volume
113 virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
114 SelectBasics_PickResult& thePickResult) Standard_OVERRIDE
116 return isValidRay (theMgr)
117 && Select3D_SensitiveTriangulation::Matches (theMgr, thePickResult);
122 //=======================================================================
125 //=======================================================================
126 void AIS_Manipulator::init()
128 // Create axis in the default coordinate system. The custom position is applied in local transformation.
129 myAxes[0] = Axis (gp::OX(), Quantity_NOC_RED);
130 myAxes[1] = Axis (gp::OY(), Quantity_NOC_GREEN);
131 myAxes[2] = Axis (gp::OZ(), Quantity_NOC_BLUE1);
133 Graphic3d_MaterialAspect aShadingMaterial;
134 aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
135 aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
137 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
138 myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
139 myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE);
140 myDrawer->ShadingAspect()->SetMaterial (aShadingMaterial);
142 Graphic3d_MaterialAspect aHilightMaterial;
143 aHilightMaterial.SetColor (Quantity_NOC_AZURE);
144 aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
145 aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
146 aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
147 aHilightMaterial.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
148 aHilightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
150 myHighlightAspect = new Prs3d_ShadingAspect();
151 myHighlightAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
152 myHighlightAspect->SetMaterial (aHilightMaterial);
155 SetZLayer (Graphic3d_ZLayerId_Topmost);
158 //=======================================================================
159 //function : getHighlightPresentation
161 //=======================================================================
162 Handle(Prs3d_Presentation) AIS_Manipulator::getHighlightPresentation (const Handle(SelectMgr_EntityOwner)& theOwner) const
164 Handle(Prs3d_Presentation) aDummyPrs;
165 Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
166 if (anOwner.IsNull())
171 switch (anOwner->Mode())
173 case AIS_MM_Translation: return myAxes[anOwner->Index()].TranslatorHighlightPrs();
174 case AIS_MM_Rotation : return myAxes[anOwner->Index()].RotatorHighlightPrs();
175 case AIS_MM_Scaling : return myAxes[anOwner->Index()].ScalerHighlightPrs();
176 case AIS_MM_None : break;
182 //=======================================================================
183 //function : getGroup
185 //=======================================================================
186 Handle(Graphic3d_Group) AIS_Manipulator::getGroup (const Standard_Integer theIndex, const AIS_ManipulatorMode theMode) const
188 Handle(Graphic3d_Group) aDummyGroup;
190 if (theIndex < 0 || theIndex > 2)
197 case AIS_MM_Translation: return myAxes[theIndex].TranslatorGroup();
198 case AIS_MM_Rotation : return myAxes[theIndex].RotatorGroup();
199 case AIS_MM_Scaling : return myAxes[theIndex].ScalerGroup();
200 case AIS_MM_None : break;
206 //=======================================================================
207 //function : Constructor
209 //=======================================================================
210 AIS_Manipulator::AIS_Manipulator()
211 : myPosition (gp::XOY()),
213 myCurrentMode (AIS_MM_None),
214 myIsActivationOnDetection (Standard_False),
215 myIsZoomPersistentMode (Standard_True),
216 myHasStartedTransformation (Standard_False),
217 myStartPosition (gp::XOY()),
218 myStartPick (0.0, 0.0, 0.0),
222 SetMutable (Standard_True);
223 SetDisplayMode (AIS_Shaded);
227 //=======================================================================
228 //function : Constructor
230 //=======================================================================
231 AIS_Manipulator::AIS_Manipulator (const gp_Ax2& thePosition)
232 : myPosition (thePosition),
234 myCurrentMode (AIS_MM_None),
235 myIsActivationOnDetection (Standard_False),
236 myIsZoomPersistentMode (Standard_True),
237 myHasStartedTransformation (Standard_False),
238 myStartPosition (gp::XOY()),
239 myStartPick (0.0, 0.0, 0.0),
243 SetMutable (Standard_True);
244 SetDisplayMode (AIS_Shaded);
248 //=======================================================================
251 //=======================================================================
252 void AIS_Manipulator::SetPart (const Standard_Integer theAxisIndex, const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled)
254 Standard_ProgramError_Raise_if (theAxisIndex < 0 || theAxisIndex > 2, "AIS_Manipulator::SetMode(): axis index should be between 0 and 2");
257 case AIS_MM_Translation:
258 myAxes[theAxisIndex].SetTranslation (theIsEnabled);
261 case AIS_MM_Rotation:
262 myAxes[theAxisIndex].SetRotation (theIsEnabled);
266 myAxes[theAxisIndex].SetScaling (theIsEnabled);
274 //=======================================================================
275 //function : EnableMode
277 //=======================================================================
278 void AIS_Manipulator::EnableMode (const AIS_ManipulatorMode theMode)
285 const Handle(AIS_InteractiveContext)& aContext = GetContext();
286 if (aContext.IsNull())
291 aContext->Activate (this, theMode);
294 //=======================================================================
295 //function : attachToBox
297 //=======================================================================
298 void AIS_Manipulator::attachToBox (const Bnd_Box& theBox)
305 Standard_Real anXmin = 0.0, anYmin = 0.0, aZmin = 0.0, anXmax = 0.0, anYmax = 0.0, aZmax = 0.0;
306 theBox.Get (anXmin, anYmin, aZmin, anXmax, anYmax, aZmax);
308 gp_Ax2 aPosition = gp::XOY();
309 aPosition.SetLocation (gp_Pnt ((anXmin + anXmax) * 0.5, (anYmin + anYmax) * 0.5, (aZmin + aZmax) * 0.5));
310 SetPosition (aPosition);
313 //=======================================================================
314 //function : adjustSize
316 //=======================================================================
317 void AIS_Manipulator::adjustSize (const Bnd_Box& theBox)
319 Standard_Real aXmin = 0., aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.0;
320 theBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
321 Standard_Real aXSize = aXmax - aXmin;
322 Standard_Real aYSize = aYmax - aYmin;
323 Standard_Real aZSize = aZmax - aZmin;
325 SetSize ((Standard_ShortReal) (Max (aXSize, Max (aYSize, aZSize)) * 0.5));
328 //=======================================================================
331 //=======================================================================
332 void AIS_Manipulator::Attach (const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions)
334 if (theObject->IsKind (STANDARD_TYPE(AIS_Manipulator)))
339 Handle(AIS_ManipulatorObjectSequence) aSeq = new AIS_ManipulatorObjectSequence();
340 aSeq->Append (theObject);
341 Attach (aSeq, theOptions);
344 //=======================================================================
347 //=======================================================================
348 void AIS_Manipulator::Attach (const Handle(AIS_ManipulatorObjectSequence)& theObjects, const OptionsForAttach& theOptions)
350 if (theObjects->Size() < 1)
355 SetOwner (theObjects);
357 const Handle(AIS_InteractiveObject)& aCurObject = theObjects->Value (theObjects->Lower());
358 aCurObject->BoundingBox (aBox);
360 if (theOptions.AdjustPosition)
365 if (theOptions.AdjustSize)
370 const Handle(AIS_InteractiveContext)& aContext = Object()->GetContext();
371 if (!aContext.IsNull())
373 if (!aContext->IsDisplayed (this))
375 aContext->Display (this, Standard_False);
379 aContext->Update (this, Standard_False);
380 aContext->RecomputeSelectionOnly (this);
383 aContext->Load (this);
386 if (theOptions.EnableModes)
388 EnableMode (AIS_MM_Rotation);
389 EnableMode (AIS_MM_Translation);
390 EnableMode (AIS_MM_Scaling);
394 //=======================================================================
397 //=======================================================================
398 void AIS_Manipulator::Detach()
400 DeactivateCurrentMode();
407 Handle(AIS_InteractiveObject) anObject = Object();
408 const Handle(AIS_InteractiveContext)& aContext = anObject->GetContext();
409 if (!aContext.IsNull())
411 aContext->Remove (this, Standard_False);
417 //=======================================================================
420 //=======================================================================
421 Handle(AIS_ManipulatorObjectSequence) AIS_Manipulator::Objects() const
423 return Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
426 //=======================================================================
429 //=======================================================================
430 Handle(AIS_InteractiveObject) AIS_Manipulator::Object (const Standard_Integer theIndex) const
432 Handle(AIS_ManipulatorObjectSequence) anOwner = Handle(AIS_ManipulatorObjectSequence)::DownCast (GetOwner());
434 Standard_ProgramError_Raise_if (theIndex < anOwner->Lower() || theIndex > anOwner->Upper(), "AIS_Manipulator::Object(): wrong index value");
436 if (anOwner.IsNull() || anOwner->IsEmpty())
441 return anOwner->Value (theIndex);
444 //=======================================================================
447 //=======================================================================
448 Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const
453 //=======================================================================
454 //function : ObjectTransformation
456 //=======================================================================
457 Standard_Boolean AIS_Manipulator::ObjectTransformation (const Standard_Integer theMaxX, const Standard_Integer theMaxY,
458 const Handle(V3d_View)& theView, gp_Trsf& theTrsf)
460 // Initialize start reference data
461 if (!myHasStartedTransformation)
463 myStartTrsfs.Clear();
464 Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
465 for (AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects); anObjIter.More(); anObjIter.Next())
467 myStartTrsfs.Append (anObjIter.Value()->LocalTransformation());
469 myStartPosition = myPosition;
472 // Get 3d point with projection vector
473 Graphic3d_Vec3d anInputPoint, aProj;
474 theView->ConvertWithProj (theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z());
475 const gp_Lin anInputLine (gp_Pnt (anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir (aProj.x(), aProj.y(), aProj.z()));
476 switch (myCurrentMode)
478 case AIS_MM_Translation:
481 const gp_Lin aLine (myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction());
482 Extrema_ExtElC anExtrema (anInputLine, aLine, Precision::Angular());
483 if (!anExtrema.IsDone()
484 || anExtrema.NbExt() != 1)
486 // translation cannot be done co-directed with camera
487 return Standard_False;
490 Extrema_POnCurv anExPnts[2];
491 anExtrema.Points (1, anExPnts[0], anExPnts[1]);
492 const gp_Pnt aNewPosition = anExPnts[1].Value();
493 if (!myHasStartedTransformation)
495 myStartPick = aNewPosition;
496 myHasStartedTransformation = Standard_True;
497 return Standard_True;
499 else if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
501 return Standard_False;
505 if (myCurrentMode == AIS_MM_Translation)
507 aNewTrsf.SetTranslation (gp_Vec(myStartPick, aNewPosition));
510 else if (myCurrentMode == AIS_MM_Scaling)
512 if (aNewPosition.Distance (myStartPosition.Location()) < Precision::Confusion())
514 return Standard_False;
517 Standard_Real aCoeff = myStartPosition.Location().Distance (aNewPosition)
518 / myStartPosition.Location().Distance (myStartPick);
519 aNewTrsf.SetScale (myPosition.Location(), aCoeff);
522 return Standard_True;
524 case AIS_MM_Rotation:
526 const gp_Pnt aPosLoc = myStartPosition.Location();
527 const gp_Ax1 aCurrAxis = getAx1FromAx2Dir (myStartPosition, myCurrentIndex);
528 IntAna_IntConicQuad aIntersector (anInputLine, gp_Pln (aPosLoc, aCurrAxis.Direction()), Precision::Angular(), Precision::Intersection());
529 if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1)
531 return Standard_False;
534 const gp_Pnt aNewPosition = aIntersector.Point (1);
535 if (!myHasStartedTransformation)
537 myStartPick = aNewPosition;
538 myHasStartedTransformation = Standard_True;
539 gp_Dir aStartAxis = gce_MakeDir (aPosLoc, myStartPick);
540 myPrevState = aStartAxis.AngleWithRef (gce_MakeDir(aPosLoc, aNewPosition), aCurrAxis.Direction());
541 return Standard_True;
544 if (aNewPosition.Distance (myStartPick) < Precision::Confusion())
546 return Standard_False;
549 gp_Dir aStartAxis = aPosLoc.IsEqual (myStartPick, Precision::Confusion())
550 ? getAx1FromAx2Dir (myStartPosition, (myCurrentIndex + 1) % 3).Direction()
551 : gce_MakeDir (aPosLoc, myStartPick);
553 gp_Dir aCurrentAxis = gce_MakeDir (aPosLoc, aNewPosition);
554 Standard_Real anAngle = aStartAxis.AngleWithRef (aCurrentAxis, aCurrAxis.Direction());
556 // Change value of an angle if it should have different sign.
557 if (anAngle * myPrevState < 0 && Abs (anAngle) < M_PI_2)
559 Standard_Real aSign = myPrevState > 0 ? -1.0 : 1.0;
560 anAngle = aSign * (M_PI * 2 - anAngle);
563 if (Abs (anAngle) < Precision::Confusion())
565 return Standard_False;
569 aNewTrsf.SetRotation (aCurrAxis, anAngle);
571 myPrevState = anAngle;
572 return Standard_True;
576 return Standard_False;
579 return Standard_False;
582 //=======================================================================
583 //function : StartTransform
585 //=======================================================================
586 void AIS_Manipulator::StartTransform (const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView)
588 if (myHasStartedTransformation)
594 ObjectTransformation (theX, theY, theView, aTrsf);
597 //=======================================================================
598 //function : StopTransform
600 //=======================================================================
601 void AIS_Manipulator::StopTransform (const Standard_Boolean theToApply)
603 if (!IsAttached() || !myHasStartedTransformation)
608 myHasStartedTransformation = Standard_False;
614 Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
615 AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
616 NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
617 for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
619 anObjIter.ChangeValue()->SetLocalTransformation (aTrsfIter.Value());
621 SetPosition (myStartPosition);
624 //=======================================================================
625 //function : Transform
627 //=======================================================================
628 void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
630 if (!IsAttached() || !myHasStartedTransformation)
636 Handle(AIS_ManipulatorObjectSequence) anObjects = Objects();
637 AIS_ManipulatorObjectSequence::Iterator anObjIter (*anObjects);
638 NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter (myStartTrsfs);
639 for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next())
641 anObjIter.ChangeValue()->SetLocalTransformation (theTrsf * aTrsfIter.Value());
645 if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation)
646 || (myCurrentMode == AIS_MM_Rotation && myBehaviorOnTransform.FollowRotation))
648 gp_Pnt aPos = myStartPosition.Location().Transformed (theTrsf);
649 gp_Dir aVDir = myStartPosition.Direction().Transformed (theTrsf);
650 gp_Dir aXDir = myStartPosition.XDirection().Transformed (theTrsf);
651 SetPosition (gp_Ax2 (aPos, aVDir, aXDir));
655 //=======================================================================
656 //function : Transform
658 //=======================================================================
659 gp_Trsf AIS_Manipulator::Transform (const Standard_Integer thePX, const Standard_Integer thePY,
660 const Handle(V3d_View)& theView)
663 if (ObjectTransformation (thePX, thePY, theView, aTrsf))
671 //=======================================================================
672 //function : SetPosition
674 //=======================================================================
675 void AIS_Manipulator::SetPosition (const gp_Ax2& thePosition)
677 if (!myPosition.Location().IsEqual (thePosition.Location(), Precision::Confusion())
678 || !myPosition.Direction().IsEqual (thePosition.Direction(), Precision::Angular())
679 || !myPosition.XDirection().IsEqual (thePosition.XDirection(), Precision::Angular()))
681 myPosition = thePosition;
682 myAxes[0].SetPosition (getAx1FromAx2Dir (thePosition, 0));
683 myAxes[1].SetPosition (getAx1FromAx2Dir (thePosition, 1));
684 myAxes[2].SetPosition (getAx1FromAx2Dir (thePosition, 2));
685 updateTransformation();
689 //=======================================================================
690 //function : updateTransformation
691 //purpose : set local transformation to avoid graphics recomputation
692 //=======================================================================
693 void AIS_Manipulator::updateTransformation()
697 if (!myIsZoomPersistentMode)
699 aTrsf.SetTransformation (myPosition, gp::XOY());
703 const gp_Dir& aVDir = myPosition.Direction();
704 const gp_Dir& aXDir = myPosition.XDirection();
705 aTrsf.SetTransformation (gp_Ax2 (gp::Origin(), aVDir, aXDir), gp::XOY());
708 Handle(Geom_Transformation) aGeomTrsf = new Geom_Transformation (aTrsf);
709 // we explicitly call here setLocalTransformation() of the base class
710 // since AIS_Manipulator::setLocalTransformation() implementation throws exception
711 // as protection from external calls
712 AIS_InteractiveObject::setLocalTransformation (aGeomTrsf);
713 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
715 myAxes[anIt].Transform (aGeomTrsf);
718 if (myIsZoomPersistentMode)
720 if (TransformPersistence().IsNull()
721 || TransformPersistence()->Mode() != Graphic3d_TMF_ZoomPers
722 || !TransformPersistence()->AnchorPoint().IsEqual (myPosition.Location(), 0.0))
724 setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, myPosition.Location()));
729 //=======================================================================
732 //=======================================================================
733 void AIS_Manipulator::SetSize (const Standard_ShortReal theSideLength)
735 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
737 myAxes[anIt].SetSize (theSideLength);
743 //=======================================================================
746 //=======================================================================
747 void AIS_Manipulator::SetGap (const Standard_ShortReal theValue)
749 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
751 myAxes[anIt].SetIndent (theValue);
757 //=======================================================================
758 //function : DeactivateCurrentMode
760 //=======================================================================
761 void AIS_Manipulator::DeactivateCurrentMode()
763 if (!myIsActivationOnDetection)
765 Handle(Graphic3d_Group) aGroup = getGroup (myCurrentIndex, myCurrentMode);
771 Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
772 anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
773 anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
774 anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
775 anAspect->SetColor (myAxes[myCurrentIndex].Color());
777 aGroup->SetGroupPrimitivesAspect (anAspect->Aspect());
781 myCurrentMode = AIS_MM_None;
783 if (myHasStartedTransformation)
785 myHasStartedTransformation = Standard_False;
789 //=======================================================================
790 //function : SetZoomPersistence
792 //=======================================================================
793 void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable)
795 if (myIsZoomPersistentMode != theToEnable)
800 myIsZoomPersistentMode = theToEnable;
804 setTransformPersistence (Handle(Graphic3d_TransformPers)());
807 updateTransformation();
810 //=======================================================================
811 //function : SetTransformPersistence
813 //=======================================================================
814 void AIS_Manipulator::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
816 Standard_ASSERT_RETURN (!myIsZoomPersistentMode,
817 "AIS_Manipulator::SetTransformPersistence: "
818 "Custom settings are not allowed by this class in ZoomPersistence mode",);
820 setTransformPersistence (theTrsfPers);
823 //=======================================================================
824 //function : setTransformPersistence
826 //=======================================================================
827 void AIS_Manipulator::setTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
829 AIS_InteractiveObject::SetTransformPersistence (theTrsfPers);
831 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
833 myAxes[anIt].SetTransformPersistence (theTrsfPers);
837 //=======================================================================
838 //function : setLocalTransformation
840 //=======================================================================
841 void AIS_Manipulator::setLocalTransformation (const Handle(Geom_Transformation)& /*theTrsf*/)
843 Standard_ASSERT_INVOKE ("AIS_Manipulator::setLocalTransformation: "
844 "Custom transformation is not supported by this class");
847 //=======================================================================
850 //=======================================================================
851 void AIS_Manipulator::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
852 const Handle(Prs3d_Presentation)& thePrs,
853 const Standard_Integer theMode)
855 if (theMode != AIS_Shaded)
860 thePrs->SetInfiniteState (Standard_True);
861 thePrs->SetMutable (Standard_True);
862 Handle(Graphic3d_Group) aGroup;
863 Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect();
864 anAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
865 anAspect->SetMaterial (myDrawer->ShadingAspect()->Material());
866 anAspect->SetTransparency (myDrawer->ShadingAspect()->Transparency());
869 myCenter.Init (myAxes[0].AxisRadius() * 2.0f, gp::Origin());
870 aGroup = Prs3d_Root::NewGroup (thePrs);
871 aGroup->SetPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
872 aGroup->AddPrimitiveArray (myCenter.Array());
874 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
877 aGroup = Prs3d_Root::NewGroup (thePrs);
879 Handle(Prs3d_ShadingAspect) anAspectAx = new Prs3d_ShadingAspect (new Graphic3d_AspectFillArea3d(*anAspect->Aspect()));
880 anAspectAx->SetColor (myAxes[anIt].Color());
881 aGroup->SetGroupPrimitivesAspect (anAspectAx->Aspect());
882 myAxes[anIt].Compute (thePrsMgr, thePrs, anAspectAx);
883 myAxes[anIt].SetTransformPersistence (TransformPersistence());
886 updateTransformation();
889 //=======================================================================
890 //function : HilightSelected
892 //=======================================================================
893 void AIS_Manipulator::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePM,
894 const SelectMgr_SequenceOfOwner& theSeq)
896 if (theSeq.IsEmpty())
901 if (myIsActivationOnDetection)
906 if (!theSeq (1)->IsKind (STANDARD_TYPE (AIS_ManipulatorOwner)))
908 thePM->Color (this, GetContext()->HighlightStyle(), 0);
912 Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theSeq (1));
913 myHighlightAspect->Aspect()->SetInteriorColor (GetContext()->HighlightStyle()->Color());
914 Handle(Graphic3d_Group) aGroup = getGroup (anOwner->Index(), anOwner->Mode());
920 aGroup->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
922 myCurrentIndex = anOwner->Index();
923 myCurrentMode = anOwner->Mode();
926 //=======================================================================
927 //function : ClearSelected
929 //=======================================================================
930 void AIS_Manipulator::ClearSelected()
932 DeactivateCurrentMode();
935 //=======================================================================
936 //function : HilightOwnerWithColor
938 //=======================================================================
939 void AIS_Manipulator::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM,
940 const Handle(Prs3d_Drawer)& theStyle,
941 const Handle(SelectMgr_EntityOwner)& theOwner)
943 Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast (theOwner);
944 Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation (anOwner);
945 if (aPresentation.IsNull())
949 aPresentation->Highlight (theStyle);
950 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPresentation->Groups());
951 aGroupIter.More(); aGroupIter.Next())
953 Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue();
955 && aGrp->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
957 aGrp->SetGroupPrimitivesAspect (myHighlightAspect->Aspect());
960 aPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
961 thePM->AddToImmediateList (aPresentation);
963 if (myIsActivationOnDetection)
967 DeactivateCurrentMode();
970 myCurrentIndex = anOwner->Index();
971 myCurrentMode = anOwner->Mode();
975 //=======================================================================
976 //function : ComputeSelection
978 //=======================================================================
979 void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
980 const Standard_Integer theMode)
983 AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
984 if (aMode == AIS_MM_None)
988 Handle(SelectMgr_EntityOwner) anOwner;
989 if (aMode == AIS_MM_None)
991 anOwner = new SelectMgr_EntityOwner (this, 5);
994 if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
996 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
998 const Axis& anAxis = myAxes[anIt];
999 if (aMode != AIS_MM_None)
1001 anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
1003 // define sensitivity by line
1004 Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
1005 aLine->SetSensitivityFactor (15);
1006 theSelection->Add (aLine);
1008 // enlarge sensitivity by triangulation
1009 Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
1010 aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location());
1011 theSelection->Add (aTri);
1015 if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
1017 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
1019 const Axis& anAxis = myAxes[anIt];
1020 if (aMode != AIS_MM_None)
1022 anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
1024 // define sensitivity by circle
1025 Handle(Geom_Circle) aGeomCircle = new Geom_Circle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
1026 Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
1027 aCircle->SetSensitivityFactor (15);
1028 theSelection->Add (aCircle);
1029 // enlarge sensitivity by triangulation
1030 Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
1031 theSelection->Add (aTri);
1035 if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
1037 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
1039 if (aMode != AIS_MM_None)
1041 anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
1043 // define sensitivity by point
1044 Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
1045 aPnt->SetSensitivityFactor (15);
1046 theSelection->Add (aPnt);
1047 // enlarge sensitivity by triangulation
1048 Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
1049 theSelection->Add (aTri);
1054 //=======================================================================
1058 //=======================================================================
1059 void AIS_Manipulator::Disk::Init (const Standard_ShortReal theInnerRadius,
1060 const Standard_ShortReal theOuterRadius,
1061 const gp_Ax1& thePosition,
1062 const Standard_Integer theSlicesNb,
1063 const Standard_Integer theStacksNb)
1065 myPosition = thePosition;
1066 myInnerRad = theInnerRadius;
1067 myOuterRad = theOuterRadius;
1069 Prs3d_ToolDisk aTool (theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb);
1070 gp_Ax3 aSystem (myPosition.Location(), myPosition.Direction());
1072 aTrsf.SetTransformation (aSystem, gp_Ax3());
1073 aTool.FillArray (myArray, myTriangulation, aTrsf);
1076 //=======================================================================
1080 //=======================================================================
1081 void AIS_Manipulator::Sphere::Init (const Standard_ShortReal theRadius,
1082 const gp_Pnt& thePosition,
1083 const Standard_Integer theSlicesNb,
1084 const Standard_Integer theStacksNb)
1086 myPosition = thePosition;
1087 myRadius = theRadius;
1089 Prs3d_ToolSphere aTool (theRadius, theSlicesNb, theStacksNb);
1091 aTrsf.SetTranslation (gp_Vec(gp::Origin(), thePosition));
1092 aTool.FillArray (myArray, myTriangulation, aTrsf);
1095 //=======================================================================
1099 //=======================================================================
1100 void AIS_Manipulator::Cube::Init (const gp_Ax1& thePosition, const Standard_ShortReal theSize)
1102 myArray = new Graphic3d_ArrayOfTriangles (12 * 3, 0, Standard_True);
1104 Poly_Array1OfTriangle aPolyTriangles (1, 12);
1105 TColgp_Array1OfPnt aPoints (1, 36);
1106 NCollection_Array1<gp_Dir> aNormals (1, 12);
1107 myTriangulation = new Poly_Triangulation (aPoints, aPolyTriangles);
1109 gp_Ax2 aPln (thePosition.Location(), thePosition.Direction());
1110 gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5;
1111 gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize;
1112 gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize;
1113 gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize;
1114 gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize
1115 + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5;
1116 gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize;
1117 gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize;
1118 gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize;
1120 gp_Dir aRight ((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ());
1121 gp_Dir aFront ((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ());
1124 addTriangle (0, aBottomLeft, aV2, aV3, -thePosition.Direction());
1125 addTriangle (1, aBottomLeft, aV3, aV4, -thePosition.Direction());
1128 addTriangle (2, aV3, aV4, aV5, aFront);
1129 addTriangle (3, aV3, aV5, aTopRight, aFront);
1132 addTriangle (4, aBottomLeft, aV2, aV7, -aFront);
1133 addTriangle (5, aBottomLeft, aV7, aV6, -aFront);
1136 addTriangle (6, aV7, aV6, aV5, thePosition.Direction());
1137 addTriangle (7, aTopRight, aV7, aV5, thePosition.Direction());
1140 addTriangle (8, aV6, aV5, aV4, -aRight);
1141 addTriangle (9, aBottomLeft, aV6, aV4, -aRight);
1144 addTriangle (10, aV3, aTopRight, aV7, aRight);
1145 addTriangle (11, aV3, aV7, aV2, aRight);
1148 //=======================================================================
1150 //function : addTriangle
1152 //=======================================================================
1153 void AIS_Manipulator::Cube::addTriangle (const Standard_Integer theIndex,
1154 const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3,
1155 const gp_Dir& theNormal)
1157 myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 1, theP1);
1158 myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 2, theP2);
1159 myTriangulation->ChangeNodes().SetValue (theIndex * 3 + 3, theP3);
1161 myTriangulation->ChangeTriangles().SetValue (theIndex + 1, Poly_Triangle (theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3));
1162 myArray->AddVertex (theP1, theNormal);
1163 myArray->AddVertex (theP2, theNormal);
1164 myArray->AddVertex (theP3, theNormal);
1167 //=======================================================================
1169 //function : Constructor
1171 //=======================================================================
1172 AIS_Manipulator::Axis::Axis (const gp_Ax1& theAxis,
1173 const Quantity_Color& theColor,
1174 const Standard_ShortReal theLength)
1175 : myReferenceAxis (theAxis),
1176 myPosition (theAxis),
1178 myHasTranslation (Standard_True),
1179 myLength (theLength),
1180 myAxisRadius (0.5f),
1181 myHasScaling (Standard_True),
1183 myHasRotation (Standard_True),
1184 myInnerRadius (myLength + myBoxSize),
1185 myDiskThickness (myBoxSize * 0.5f),
1187 myFacettesNumber (20),
1188 myCircleRadius (myLength + myBoxSize + myBoxSize * 0.5f * 0.5f)
1193 //=======================================================================
1195 //function : Compute
1197 //=======================================================================
1199 void AIS_Manipulator::Axis::Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
1200 const Handle(Prs3d_Presentation)& thePrs,
1201 const Handle(Prs3d_ShadingAspect)& theAspect)
1203 if (myHasTranslation)
1205 const Standard_Real anArrowLength = 0.25 * myLength;
1206 const Standard_Real aCylinderLength = myLength - anArrowLength;
1207 myArrowTipPos = gp_Pnt (0.0, 0.0, 0.0).Translated (myReferenceAxis.Direction().XYZ() * aCylinderLength);
1209 myTriangleArray = Prs3d_Arrow::DrawShaded (gp_Ax1(gp::Origin(), myReferenceAxis.Direction()),
1215 myTranslatorGroup = Prs3d_Root::NewGroup (thePrs);
1216 myTranslatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1217 myTranslatorGroup->AddPrimitiveArray (myTriangleArray);
1219 if (myHighlightTranslator.IsNull())
1221 myHighlightTranslator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1225 myHighlightTranslator->Clear();
1228 Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightTranslator);
1229 aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1230 aGroup->AddPrimitiveArray (myTriangleArray);
1236 myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent);
1237 myCube.Init (gp_Ax1 (myCubePos, myReferenceAxis.Direction()), myBoxSize);
1239 myScalerGroup = Prs3d_Root::NewGroup (thePrs);
1240 myScalerGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1241 myScalerGroup->AddPrimitiveArray (myCube.Array());
1243 if (myHighlightScaler.IsNull())
1245 myHighlightScaler = new Prs3d_Presentation (thePrsMgr->StructureManager());
1249 myHighlightScaler->Clear();
1252 Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightScaler);
1253 aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1254 aGroup->AddPrimitiveArray (myCube.Array());
1260 myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f;
1261 myCircle.Init (myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2);
1262 myRotatorGroup = Prs3d_Root::NewGroup (thePrs);
1263 myRotatorGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1264 myRotatorGroup->AddPrimitiveArray (myCircle.Array());
1266 if (myHighlightRotator.IsNull())
1268 myHighlightRotator = new Prs3d_Presentation (thePrsMgr->StructureManager());
1272 myHighlightRotator->Clear();
1275 Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (myHighlightRotator);
1276 aGroup->SetGroupPrimitivesAspect (theAspect->Aspect());
1277 aGroup->AddPrimitiveArray (myCircle.Array());