// Created on: 2015-12-23 // Created by: Anastasia BORISOVA // Copyright (c) 2015 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include <AIS_Manipulator.hxx> #include <AIS_DisplayMode.hxx> #include <AIS_InteractiveContext.hxx> #include <AIS_ManipulatorOwner.hxx> #include <Extrema_ExtElC.hxx> #include <gce_MakeDir.hxx> #include <IntAna_IntConicQuad.hxx> #include <Prs3d_Arrow.hxx> #include <Prs3d_ShadingAspect.hxx> #include <Prs3d_ToolDisk.hxx> #include <Prs3d_ToolSector.hxx> #include <Prs3d_ToolSphere.hxx> #include <Select3D_SensitiveCircle.hxx> #include <Select3D_SensitivePoint.hxx> #include <Select3D_SensitiveSegment.hxx> #include <Select3D_SensitiveTriangulation.hxx> #include <Select3D_SensitivePrimitiveArray.hxx> #include <SelectMgr_SequenceOfOwner.hxx> #include <TColgp_Array1OfPnt.hxx> #include <V3d_View.hxx> IMPLEMENT_STANDARD_HANDLE(AIS_Manipulator, AIS_InteractiveObject) IMPLEMENT_STANDARD_RTTIEXT(AIS_Manipulator, AIS_InteractiveObject) IMPLEMENT_HSEQUENCE(AIS_ManipulatorObjectSequence) namespace { //! Return Ax1 for specified direction of Ax2. static gp_Ax1 getAx1FromAx2Dir(const gp_Ax2& theAx2, int theIndex) { switch (theIndex) { case 0: return gp_Ax1(theAx2.Location(), theAx2.XDirection()); case 1: return gp_Ax1(theAx2.Location(), theAx2.YDirection()); case 2: return theAx2.Axis(); } throw Standard_ProgramError("AIS_Manipulator - Invalid axis index"); } //! Auxiliary tool for filtering picking ray. class ManipSensRotation { public: //! Main constructor. ManipSensRotation(const gp_Dir& thePlaneNormal) : myPlaneNormal(thePlaneNormal), myAngleTol(10.0 * M_PI / 180.0) { } //! Checks if picking ray can be used for detection. Standard_Boolean isValidRay(const SelectBasics_SelectingVolumeManager& theMgr) const { if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point) { return Standard_False; } const gp_Dir aRay = theMgr.GetViewRayDirection(); return !aRay.IsNormal(myPlaneNormal, myAngleTol); } private: gp_Dir myPlaneNormal; Standard_Real myAngleTol; }; //! Sensitive circle with filtering picking ray. class ManipSensCircle : public Select3D_SensitiveCircle, public ManipSensRotation { public: //! Main constructor. ManipSensCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId, const gp_Circ& theCircle) : Select3D_SensitiveCircle(theOwnerId, theCircle, Standard_False), ManipSensRotation(theCircle.Position().Direction()) { } //! Checks whether the circle overlaps current selecting volume virtual Standard_Boolean Matches(SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) Standard_OVERRIDE { return isValidRay(theMgr) && Select3D_SensitiveCircle::Matches(theMgr, thePickResult); } }; //! Sensitive triangulation with filtering picking ray. class ManipSensTriangulation : public Select3D_SensitiveTriangulation, public ManipSensRotation { public: ManipSensTriangulation(const Handle(SelectMgr_EntityOwner)& theOwnerId, const Handle(Poly_Triangulation)& theTrg, const gp_Dir& thePlaneNormal) : Select3D_SensitiveTriangulation(theOwnerId, theTrg, TopLoc_Location(), Standard_True), ManipSensRotation(thePlaneNormal) { } //! Checks whether the circle overlaps current selecting volume virtual Standard_Boolean Matches(SelectBasics_SelectingVolumeManager& theMgr, SelectBasics_PickResult& thePickResult) Standard_OVERRIDE { return isValidRay(theMgr) && Select3D_SensitiveTriangulation::Matches(theMgr, thePickResult); } }; } // namespace //================================================================================================= void AIS_Manipulator::init() { // Create axis in the default coordinate system. The custom position is applied in local // transformation. myAxes[0] = Axis(gp::OX(), Quantity_NOC_RED); myAxes[1] = Axis(gp::OY(), Quantity_NOC_GREEN); myAxes[2] = Axis(gp::OZ(), Quantity_NOC_BLUE1); Graphic3d_MaterialAspect aShadingMaterial; aShadingMaterial.SetSpecularColor(Quantity_NOC_BLACK); aShadingMaterial.SetMaterialType(Graphic3d_MATERIAL_ASPECT); myDrawer->SetShadingAspect(new Prs3d_ShadingAspect()); myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle(Aspect_IS_SOLID); myDrawer->ShadingAspect()->SetColor(Quantity_NOC_WHITE); myDrawer->ShadingAspect()->SetMaterial(aShadingMaterial); Graphic3d_MaterialAspect aHilightMaterial; aHilightMaterial.SetColor(Quantity_NOC_AZURE); aHilightMaterial.SetAmbientColor(Quantity_NOC_BLACK); aHilightMaterial.SetDiffuseColor(Quantity_NOC_BLACK); aHilightMaterial.SetSpecularColor(Quantity_NOC_BLACK); aHilightMaterial.SetEmissiveColor(Quantity_NOC_BLACK); aHilightMaterial.SetMaterialType(Graphic3d_MATERIAL_ASPECT); myHighlightAspect = new Prs3d_ShadingAspect(); myHighlightAspect->Aspect()->SetInteriorStyle(Aspect_IS_SOLID); myHighlightAspect->SetMaterial(aHilightMaterial); Graphic3d_MaterialAspect aDraggerMaterial; aDraggerMaterial.SetAmbientColor(Quantity_NOC_BLACK); aDraggerMaterial.SetDiffuseColor(Quantity_NOC_BLACK); aDraggerMaterial.SetSpecularColor(Quantity_NOC_BLACK); aDraggerMaterial.SetMaterialType(Graphic3d_MATERIAL_ASPECT); myDraggerHighlight = new Prs3d_ShadingAspect(); myDraggerHighlight->Aspect()->SetInteriorStyle(Aspect_IS_SOLID); myDraggerHighlight->SetMaterial(aDraggerMaterial); myDraggerHighlight->SetTransparency(0.5); SetSize(100); SetZLayer(Graphic3d_ZLayerId_Topmost); } //================================================================================================= Handle(Prs3d_Presentation) AIS_Manipulator::getHighlightPresentation( const Handle(SelectMgr_EntityOwner)& theOwner) const { Handle(Prs3d_Presentation) aDummyPrs; Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast(theOwner); if (anOwner.IsNull()) { return aDummyPrs; } switch (anOwner->Mode()) { case AIS_MM_Translation: return myAxes[anOwner->Index()].TranslatorHighlightPrs(); case AIS_MM_Rotation: return myAxes[anOwner->Index()].RotatorHighlightPrs(); case AIS_MM_Scaling: return myAxes[anOwner->Index()].ScalerHighlightPrs(); case AIS_MM_TranslationPlane: return myAxes[anOwner->Index()].DraggerHighlightPrs(); case AIS_MM_None: break; } return aDummyPrs; } //================================================================================================= Handle(Graphic3d_Group) AIS_Manipulator::getGroup(const Standard_Integer theIndex, const AIS_ManipulatorMode theMode) const { Handle(Graphic3d_Group) aDummyGroup; if (theIndex < 0 || theIndex > 2) { return aDummyGroup; } switch (theMode) { case AIS_MM_Translation: return myAxes[theIndex].TranslatorGroup(); case AIS_MM_Rotation: return myAxes[theIndex].RotatorGroup(); case AIS_MM_Scaling: return myAxes[theIndex].ScalerGroup(); case AIS_MM_TranslationPlane: return myAxes[theIndex].DraggerGroup(); case AIS_MM_None: break; } return aDummyGroup; } //================================================================================================= AIS_Manipulator::AIS_Manipulator() : myPosition(gp::XOY()), myCurrentIndex(-1), myCurrentMode(AIS_MM_None), myIsActivationOnDetection(Standard_False), myIsZoomPersistentMode(Standard_True), myHasStartedTransformation(Standard_False), myStartPosition(gp::XOY()), myStartPick(0.0, 0.0, 0.0), myPrevState(0.0) { SetInfiniteState(); SetMutable(Standard_True); SetDisplayMode(AIS_Shaded); init(); } //================================================================================================= AIS_Manipulator::AIS_Manipulator(const gp_Ax2& thePosition) : myPosition(thePosition), myCurrentIndex(-1), myCurrentMode(AIS_MM_None), myIsActivationOnDetection(Standard_False), myIsZoomPersistentMode(Standard_True), myHasStartedTransformation(Standard_False), myStartPosition(gp::XOY()), myStartPick(0.0, 0.0, 0.0), myPrevState(0.0) { SetInfiniteState(); SetMutable(Standard_True); SetDisplayMode(AIS_Shaded); init(); } //================================================================================================= void AIS_Manipulator::SetPart(const Standard_Integer theAxisIndex, const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled) { Standard_ProgramError_Raise_if( theAxisIndex < 0 || theAxisIndex > 2, "AIS_Manipulator::SetMode(): axis index should be between 0 and 2"); switch (theMode) { case AIS_MM_Translation: myAxes[theAxisIndex].SetTranslation(theIsEnabled); break; case AIS_MM_Rotation: myAxes[theAxisIndex].SetRotation(theIsEnabled); break; case AIS_MM_Scaling: myAxes[theAxisIndex].SetScaling(theIsEnabled); break; case AIS_MM_TranslationPlane: myAxes[theAxisIndex].SetDragging(theIsEnabled); break; case AIS_MM_None: break; } } //================================================================================================= void AIS_Manipulator::SetPart(const AIS_ManipulatorMode theMode, const Standard_Boolean theIsEnabled) { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { SetPart(anIt, theMode, theIsEnabled); } } //================================================================================================= void AIS_Manipulator::EnableMode(const AIS_ManipulatorMode theMode) { if (!IsAttached()) { return; } const Handle(AIS_InteractiveContext)& aContext = GetContext(); if (aContext.IsNull()) { return; } aContext->Activate(this, theMode); } //================================================================================================= void AIS_Manipulator::attachToPoint(const gp_Pnt& thePoint) { gp_Ax2 aPosition = gp::XOY(); aPosition.SetLocation(thePoint); SetPosition(aPosition); } //================================================================================================= void AIS_Manipulator::attachToBox(const Bnd_Box& theBox) { if (theBox.IsVoid()) { return; } Standard_Real anXmin = 0.0, anYmin = 0.0, aZmin = 0.0, anXmax = 0.0, anYmax = 0.0, aZmax = 0.0; theBox.Get(anXmin, anYmin, aZmin, anXmax, anYmax, aZmax); gp_Ax2 aPosition = gp::XOY(); aPosition.SetLocation( gp_Pnt((anXmin + anXmax) * 0.5, (anYmin + anYmax) * 0.5, (aZmin + aZmax) * 0.5)); SetPosition(aPosition); } //================================================================================================= void AIS_Manipulator::adjustSize(const Bnd_Box& theBox) { Standard_Real aXmin = 0., aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.0; theBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); Standard_Real aXSize = aXmax - aXmin; Standard_Real aYSize = aYmax - aYmin; Standard_Real aZSize = aZmax - aZmin; SetSize((Standard_ShortReal)(Max(aXSize, Max(aYSize, aZSize)) * 0.5)); } //================================================================================================= void AIS_Manipulator::Attach(const Handle(AIS_InteractiveObject)& theObject, const OptionsForAttach& theOptions) { if (theObject->IsKind(STANDARD_TYPE(AIS_Manipulator))) { return; } Handle(AIS_ManipulatorObjectSequence) aSeq = new AIS_ManipulatorObjectSequence(); aSeq->Append(theObject); Attach(aSeq, theOptions); } //================================================================================================= void AIS_Manipulator::Attach(const Handle(AIS_ManipulatorObjectSequence)& theObjects, const OptionsForAttach& theOptions) { if (theObjects->Size() < 1) { return; } SetOwner(theObjects); Bnd_Box aBox; const Handle(AIS_InteractiveObject)& aCurObject = theObjects->Value(theObjects->Lower()); aCurObject->BoundingBox(aBox); if (theOptions.AdjustPosition) { const Handle(Graphic3d_TransformPers)& aTransPers = aCurObject->TransformPersistence(); if (!aTransPers.IsNull() && (aTransPers->IsZoomOrRotate() || aTransPers->IsAxial())) { attachToPoint(aTransPers->AnchorPoint()); } else { attachToBox(aBox); } } if (theOptions.AdjustSize) { adjustSize(aBox); } const Handle(AIS_InteractiveContext)& aContext = Object()->GetContext(); if (!aContext.IsNull()) { if (!aContext->IsDisplayed(this)) { aContext->Display(this, Standard_False); } else { aContext->Update(this, Standard_False); aContext->RecomputeSelectionOnly(this); } aContext->Load(this); } if (theOptions.EnableModes) { EnableMode(AIS_MM_Rotation); EnableMode(AIS_MM_Translation); EnableMode(AIS_MM_Scaling); EnableMode(AIS_MM_TranslationPlane); } } //================================================================================================= void AIS_Manipulator::Detach() { DeactivateCurrentMode(); if (!IsAttached()) { return; } Handle(AIS_InteractiveObject) anObject = Object(); const Handle(AIS_InteractiveContext)& aContext = anObject->GetContext(); if (!aContext.IsNull()) { aContext->Remove(this, Standard_False); } SetOwner(NULL); } //================================================================================================= Handle(AIS_ManipulatorObjectSequence) AIS_Manipulator::Objects() const { return Handle(AIS_ManipulatorObjectSequence)::DownCast(GetOwner()); } //================================================================================================= Handle(AIS_InteractiveObject) AIS_Manipulator::Object(const Standard_Integer theIndex) const { Handle(AIS_ManipulatorObjectSequence) anOwner = Handle(AIS_ManipulatorObjectSequence)::DownCast(GetOwner()); Standard_ProgramError_Raise_if(theIndex < anOwner->Lower() || theIndex > anOwner->Upper(), "AIS_Manipulator::Object(): wrong index value"); if (anOwner.IsNull() || anOwner->IsEmpty()) { return NULL; } return anOwner->Value(theIndex); } //================================================================================================= Handle(AIS_InteractiveObject) AIS_Manipulator::Object() const { return Object(1); } //================================================================================================= Standard_Boolean AIS_Manipulator::ObjectTransformation(const Standard_Integer theMaxX, const Standard_Integer theMaxY, const Handle(V3d_View)& theView, gp_Trsf& theTrsf) { // Initialize start reference data if (!myHasStartedTransformation) { myStartTrsfs.Clear(); Handle(AIS_ManipulatorObjectSequence) anObjects = Objects(); for (AIS_ManipulatorObjectSequence::Iterator anObjIter(*anObjects); anObjIter.More(); anObjIter.Next()) { myStartTrsfs.Append(anObjIter.Value()->LocalTransformation()); } myStartPosition = myPosition; } // Get 3d point with projection vector Graphic3d_Vec3d anInputPoint, aProj; theView->ConvertWithProj(theMaxX, theMaxY, anInputPoint.x(), anInputPoint.y(), anInputPoint.z(), aProj.x(), aProj.y(), aProj.z()); const gp_Lin anInputLine(gp_Pnt(anInputPoint.x(), anInputPoint.y(), anInputPoint.z()), gp_Dir(aProj.x(), aProj.y(), aProj.z())); switch (myCurrentMode) { case AIS_MM_Translation: case AIS_MM_Scaling: { const gp_Lin aLine(myStartPosition.Location(), myAxes[myCurrentIndex].Position().Direction()); Extrema_ExtElC anExtrema(anInputLine, aLine, Precision::Angular()); if (!anExtrema.IsDone() || anExtrema.IsParallel() || anExtrema.NbExt() != 1) { // translation cannot be done co-directed with camera return Standard_False; } Extrema_POnCurv anExPnts[2]; anExtrema.Points(1, anExPnts[0], anExPnts[1]); const gp_Pnt aNewPosition = anExPnts[1].Value(); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; return Standard_True; } else if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } gp_Trsf aNewTrsf; if (myCurrentMode == AIS_MM_Translation) { aNewTrsf.SetTranslation(gp_Vec(myStartPick, aNewPosition)); theTrsf *= aNewTrsf; } else if (myCurrentMode == AIS_MM_Scaling) { if (aNewPosition.Distance(myStartPosition.Location()) < Precision::Confusion()) { return Standard_False; } Standard_Real aCoeff = myStartPosition.Location().Distance(aNewPosition) / myStartPosition.Location().Distance(myStartPick); aNewTrsf.SetScale(myPosition.Location(), aCoeff); theTrsf = aNewTrsf; } return Standard_True; } case AIS_MM_Rotation: { const gp_Pnt aPosLoc = myStartPosition.Location(); const gp_Ax1 aCurrAxis = getAx1FromAx2Dir(myStartPosition, myCurrentIndex); IntAna_IntConicQuad aIntersector(anInputLine, gp_Pln(aPosLoc, aCurrAxis.Direction()), Precision::Angular(), Precision::Intersection()); if (!aIntersector.IsDone() || aIntersector.IsParallel() || aIntersector.NbPoints() < 1) { return Standard_False; } const gp_Pnt aNewPosition = aIntersector.Point(1); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; gp_Dir aStartAxis = gce_MakeDir(aPosLoc, myStartPick); myPrevState = aStartAxis.AngleWithRef(gce_MakeDir(aPosLoc, aNewPosition), aCurrAxis.Direction()); return Standard_True; } if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } gp_Dir aStartAxis = aPosLoc.IsEqual(myStartPick, Precision::Confusion()) ? getAx1FromAx2Dir(myStartPosition, (myCurrentIndex + 1) % 3).Direction() : gce_MakeDir(aPosLoc, myStartPick); gp_Dir aCurrentAxis = gce_MakeDir(aPosLoc, aNewPosition); Standard_Real anAngle = aStartAxis.AngleWithRef(aCurrentAxis, aCurrAxis.Direction()); // Change value of an angle if it should have different sign. if (anAngle * myPrevState < 0 && Abs(anAngle) < M_PI_2) { Standard_Real aSign = myPrevState > 0 ? -1.0 : 1.0; anAngle = aSign * (M_PI * 2 - anAngle); } if (Abs(anAngle) < Precision::Confusion()) { return Standard_False; } gp_Trsf aNewTrsf; aNewTrsf.SetRotation(aCurrAxis, anAngle); theTrsf *= aNewTrsf; myPrevState = anAngle; return Standard_True; } case AIS_MM_TranslationPlane: { const gp_Pnt aPosLoc = myStartPosition.Location(); const gp_Ax1 aCurrAxis = getAx1FromAx2Dir(myStartPosition, myCurrentIndex); IntAna_IntConicQuad aIntersector(anInputLine, gp_Pln(aPosLoc, aCurrAxis.Direction()), Precision::Angular(), Precision::Intersection()); if (!aIntersector.IsDone() || aIntersector.NbPoints() < 1) { return Standard_False; } const gp_Pnt aNewPosition = aIntersector.Point(1); if (!myHasStartedTransformation) { myStartPick = aNewPosition; myHasStartedTransformation = Standard_True; return Standard_True; } if (aNewPosition.Distance(myStartPick) < Precision::Confusion()) { return Standard_False; } gp_Trsf aNewTrsf; aNewTrsf.SetTranslation(gp_Vec(myStartPick, aNewPosition)); theTrsf *= aNewTrsf; return Standard_True; } case AIS_MM_None: { return Standard_False; } } return Standard_False; } //================================================================================================= Standard_Boolean AIS_Manipulator::ProcessDragging(const Handle(AIS_InteractiveContext)& aCtx, const Handle(V3d_View)& theView, const Handle(SelectMgr_EntityOwner)&, const Graphic3d_Vec2i& theDragFrom, const Graphic3d_Vec2i& theDragTo, const AIS_DragAction theAction) { switch (theAction) { case AIS_DragAction_Start: { if (HasActiveMode()) { StartTransform(theDragFrom.x(), theDragFrom.y(), theView); return Standard_True; } break; } case AIS_DragAction_Confirmed: { return Standard_True; } case AIS_DragAction_Update: { Transform(theDragTo.x(), theDragTo.y(), theView); return Standard_True; } case AIS_DragAction_Abort: { StopTransform(false); return Standard_True; } case AIS_DragAction_Stop: { // at the end of transformation redisplay for updating sensitive areas StopTransform(true); if (aCtx->IsDisplayed(this)) { aCtx->Redisplay(this, true); } return Standard_True; } break; } return Standard_False; } //================================================================================================= void AIS_Manipulator::StartTransform(const Standard_Integer theX, const Standard_Integer theY, const Handle(V3d_View)& theView) { if (myHasStartedTransformation) { return; } gp_Trsf aTrsf; ObjectTransformation(theX, theY, theView, aTrsf); } //================================================================================================= void AIS_Manipulator::StopTransform(const Standard_Boolean theToApply) { if (!IsAttached() || !myHasStartedTransformation) { return; } myHasStartedTransformation = Standard_False; if (theToApply) { return; } Handle(AIS_ManipulatorObjectSequence) anObjects = Objects(); AIS_ManipulatorObjectSequence::Iterator anObjIter(*anObjects); NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter(myStartTrsfs); for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next()) { anObjIter.ChangeValue()->SetLocalTransformation(aTrsfIter.Value()); } SetPosition(myStartPosition); } //================================================================================================= void AIS_Manipulator::Transform(const gp_Trsf& theTrsf) { if (!IsAttached() || !myHasStartedTransformation) { return; } { Handle(AIS_ManipulatorObjectSequence) anObjects = Objects(); AIS_ManipulatorObjectSequence::Iterator anObjIter(*anObjects); NCollection_Sequence<gp_Trsf>::Iterator aTrsfIter(myStartTrsfs); for (; anObjIter.More(); anObjIter.Next(), aTrsfIter.Next()) { const Handle(AIS_InteractiveObject)& anObj = anObjIter.ChangeValue(); const Handle(Graphic3d_TransformPers)& aTransPers = anObj->TransformPersistence(); if (!aTransPers.IsNull() && (aTransPers->IsZoomOrRotate() || aTransPers->IsAxial())) { gp_XYZ aNewAnchorPoint = aTransPers->AnchorPoint().XYZ() - myPosition.Location().XYZ(); aNewAnchorPoint += myStartPosition.Location().Transformed(theTrsf).XYZ(); aTransPers->SetAnchorPoint(aNewAnchorPoint); continue; } const gp_Trsf& anOldTrsf = aTrsfIter.Value(); const Handle(TopLoc_Datum3D)& aParentTrsf = anObj->CombinedParentTransformation(); if (!aParentTrsf.IsNull() && aParentTrsf->Form() != gp_Identity) { // recompute local transformation relative to parent transformation const gp_Trsf aNewLocalTrsf = aParentTrsf->Trsf().Inverted() * theTrsf * aParentTrsf->Trsf() * anOldTrsf; anObj->SetLocalTransformation(aNewLocalTrsf); } else { anObj->SetLocalTransformation(theTrsf * anOldTrsf); } } } if ((myCurrentMode == AIS_MM_Translation && myBehaviorOnTransform.FollowTranslation) || (myCurrentMode == AIS_MM_Rotation && myBehaviorOnTransform.FollowRotation) || (myCurrentMode == AIS_MM_TranslationPlane && myBehaviorOnTransform.FollowDragging)) { gp_Pnt aPos = myStartPosition.Location().Transformed(theTrsf); gp_Dir aVDir = myStartPosition.Direction().Transformed(theTrsf); gp_Dir aXDir = myStartPosition.XDirection().Transformed(theTrsf); SetPosition(gp_Ax2(aPos, aVDir, aXDir)); } } //================================================================================================= gp_Trsf AIS_Manipulator::Transform(const Standard_Integer thePX, const Standard_Integer thePY, const Handle(V3d_View)& theView) { gp_Trsf aTrsf; if (ObjectTransformation(thePX, thePY, theView, aTrsf)) { Transform(aTrsf); } return aTrsf; } //================================================================================================= void AIS_Manipulator::SetPosition(const gp_Ax2& thePosition) { if (!myPosition.Location().IsEqual(thePosition.Location(), Precision::Confusion()) || !myPosition.Direction().IsEqual(thePosition.Direction(), Precision::Angular()) || !myPosition.XDirection().IsEqual(thePosition.XDirection(), Precision::Angular())) { myPosition = thePosition; myAxes[0].SetPosition(getAx1FromAx2Dir(thePosition, 0)); myAxes[1].SetPosition(getAx1FromAx2Dir(thePosition, 1)); myAxes[2].SetPosition(getAx1FromAx2Dir(thePosition, 2)); updateTransformation(); } } //======================================================================= // function : updateTransformation // purpose : set local transformation to avoid graphics recomputation //======================================================================= void AIS_Manipulator::updateTransformation() { gp_Trsf aTrsf; if (!myIsZoomPersistentMode) { aTrsf.SetTransformation(myPosition, gp::XOY()); } else { const gp_Dir& aVDir = myPosition.Direction(); const gp_Dir& aXDir = myPosition.XDirection(); aTrsf.SetTransformation(gp_Ax2(gp::Origin(), aVDir, aXDir), gp::XOY()); } Handle(TopLoc_Datum3D) aGeomTrsf = new TopLoc_Datum3D(aTrsf); // we explicitly call here setLocalTransformation() of the base class // since AIS_Manipulator::setLocalTransformation() implementation throws exception // as protection from external calls AIS_InteractiveObject::setLocalTransformation(aGeomTrsf); for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { myAxes[anIt].Transform(aGeomTrsf); } if (myIsZoomPersistentMode) { if (TransformPersistence().IsNull() || TransformPersistence()->Mode() != Graphic3d_TMF_AxialZoomPers || !TransformPersistence()->AnchorPoint().IsEqual(myPosition.Location(), 0.0)) { setTransformPersistence( new Graphic3d_TransformPers(Graphic3d_TMF_AxialZoomPers, myPosition.Location())); } } else { if (TransformPersistence().IsNull() || TransformPersistence()->Mode() != Graphic3d_TMF_AxialScalePers) { setTransformPersistence( new Graphic3d_TransformPers(Graphic3d_TMF_AxialScalePers, myPosition.Location())); } } } //================================================================================================= void AIS_Manipulator::SetSize(const Standard_ShortReal theSideLength) { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { myAxes[anIt].SetSize(theSideLength); } SetToUpdate(); } //================================================================================================= void AIS_Manipulator::SetGap(const Standard_ShortReal theValue) { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { myAxes[anIt].SetIndent(theValue); } SetToUpdate(); } //================================================================================================= void AIS_Manipulator::DeactivateCurrentMode() { if (!myIsActivationOnDetection) { Handle(Graphic3d_Group) aGroup = getGroup(myCurrentIndex, myCurrentMode); if (aGroup.IsNull()) { return; } Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect(); anAspect->Aspect()->SetInteriorStyle(Aspect_IS_SOLID); anAspect->SetMaterial(myDrawer->ShadingAspect()->Material()); if (myCurrentMode == AIS_MM_TranslationPlane) anAspect->SetTransparency(1.0); else { anAspect->SetTransparency(myDrawer->ShadingAspect()->Transparency()); anAspect->SetColor(myAxes[myCurrentIndex].Color()); } aGroup->SetGroupPrimitivesAspect(anAspect->Aspect()); } myCurrentIndex = -1; myCurrentMode = AIS_MM_None; if (myHasStartedTransformation) { myHasStartedTransformation = Standard_False; } } //================================================================================================= void AIS_Manipulator::SetZoomPersistence(const Standard_Boolean theToEnable) { if (myIsZoomPersistentMode != theToEnable) { SetToUpdate(); } myIsZoomPersistentMode = theToEnable; if (!theToEnable) { setTransformPersistence(new (Graphic3d_TransformPers)(Graphic3d_TMF_AxialScalePers)); } updateTransformation(); } //================================================================================================= void AIS_Manipulator::SetTransformPersistence(const Handle(Graphic3d_TransformPers)& theTrsfPers) { Standard_ASSERT_RETURN(!myIsZoomPersistentMode, "AIS_Manipulator::SetTransformPersistence: " "Custom settings are not allowed by this class in ZoomPersistence mode", ); setTransformPersistence(theTrsfPers); } //================================================================================================= void AIS_Manipulator::setTransformPersistence(const Handle(Graphic3d_TransformPers)& theTrsfPers) { AIS_InteractiveObject::SetTransformPersistence(theTrsfPers); for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { myAxes[anIt].SetTransformPersistence(theTrsfPers); } } //================================================================================================= void AIS_Manipulator::setLocalTransformation(const Handle(TopLoc_Datum3D)& /*theTrsf*/) { Standard_ASSERT_INVOKE("AIS_Manipulator::setLocalTransformation: " "Custom transformation is not supported by this class"); } //================================================================================================= void AIS_Manipulator::Compute(const Handle(PrsMgr_PresentationManager)& thePrsMgr, const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) { if (theMode != AIS_Shaded) { return; } thePrs->SetInfiniteState(Standard_True); thePrs->SetMutable(Standard_True); Handle(Graphic3d_Group) aGroup; Handle(Prs3d_ShadingAspect) anAspect = new Prs3d_ShadingAspect(); anAspect->Aspect()->SetInteriorStyle(Aspect_IS_SOLID); anAspect->SetMaterial(myDrawer->ShadingAspect()->Material()); anAspect->SetTransparency(myDrawer->ShadingAspect()->Transparency()); // Display center myCenter.Init(myAxes[0].AxisRadius() * 2.0f, gp::Origin()); aGroup = thePrs->NewGroup(); aGroup->SetPrimitivesAspect(myDrawer->ShadingAspect()->Aspect()); aGroup->AddPrimitiveArray(myCenter.Array()); for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { // Display axes aGroup = thePrs->NewGroup(); Handle(Prs3d_ShadingAspect) anAspectAx = new Prs3d_ShadingAspect(new Graphic3d_AspectFillArea3d(*anAspect->Aspect())); anAspectAx->SetColor(myAxes[anIt].Color()); aGroup->SetGroupPrimitivesAspect(anAspectAx->Aspect()); myAxes[anIt].Compute(thePrsMgr, thePrs, anAspectAx); myAxes[anIt].SetTransformPersistence(TransformPersistence()); } updateTransformation(); } //================================================================================================= void AIS_Manipulator::HilightSelected(const Handle(PrsMgr_PresentationManager)& thePM, const SelectMgr_SequenceOfOwner& theSeq) { if (theSeq.IsEmpty()) { return; } if (myIsActivationOnDetection) { return; } if (!theSeq(1)->IsKind(STANDARD_TYPE(AIS_ManipulatorOwner))) { thePM->Color(this, GetContext()->HighlightStyle(), 0); return; } Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast(theSeq(1)); myHighlightAspect->Aspect()->SetInteriorColor(GetContext()->HighlightStyle()->Color()); Handle(Graphic3d_Group) aGroup = getGroup(anOwner->Index(), anOwner->Mode()); if (aGroup.IsNull()) { return; } if (anOwner->Mode() == AIS_MM_TranslationPlane) { myDraggerHighlight->SetColor(myAxes[anOwner->Index()].Color()); aGroup->SetGroupPrimitivesAspect(myDraggerHighlight->Aspect()); } else aGroup->SetGroupPrimitivesAspect(myHighlightAspect->Aspect()); myCurrentIndex = anOwner->Index(); myCurrentMode = anOwner->Mode(); } //================================================================================================= void AIS_Manipulator::ClearSelected() { DeactivateCurrentMode(); } //================================================================================================= void AIS_Manipulator::HilightOwnerWithColor(const Handle(PrsMgr_PresentationManager)& thePM, const Handle(Prs3d_Drawer)& theStyle, const Handle(SelectMgr_EntityOwner)& theOwner) { Handle(AIS_ManipulatorOwner) anOwner = Handle(AIS_ManipulatorOwner)::DownCast(theOwner); Handle(Prs3d_Presentation) aPresentation = getHighlightPresentation(anOwner); if (aPresentation.IsNull()) { return; } aPresentation->CStructure()->ViewAffinity = myViewAffinity; if (anOwner->Mode() == AIS_MM_TranslationPlane) { Handle(Prs3d_Drawer) aStyle = new Prs3d_Drawer(); aStyle->SetColor(myAxes[anOwner->Index()].Color()); aStyle->SetTransparency(0.5); aPresentation->Highlight(aStyle); } else { aPresentation->Highlight(theStyle); } for (Graphic3d_SequenceOfGroup::Iterator aGroupIter(aPresentation->Groups()); aGroupIter.More(); aGroupIter.Next()) { Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue(); if (!aGrp.IsNull()) { aGrp->SetGroupPrimitivesAspect(myHighlightAspect->Aspect()); } } aPresentation->SetZLayer(Graphic3d_ZLayerId_Topmost); thePM->AddToImmediateList(aPresentation); if (myIsActivationOnDetection) { if (HasActiveMode()) { DeactivateCurrentMode(); } myCurrentIndex = anOwner->Index(); myCurrentMode = anOwner->Mode(); } } //================================================================================================= void AIS_Manipulator::ComputeSelection(const Handle(SelectMgr_Selection)& theSelection, const Standard_Integer theMode) { // Check mode const AIS_ManipulatorMode aMode = (AIS_ManipulatorMode)theMode; if (aMode == AIS_MM_None) { return; } Handle(SelectMgr_EntityOwner) anOwner; // Sensitivity calculation for manipulator parts allows to avoid // overlapping of sensitive areas when size of manipulator is small. // Sensitivity is calculated relative to the default size of the manipulator (100.0f). const Standard_ShortReal aSensitivityCoef = myAxes[0].Size() / 100.0f; // clang-format off const Standard_Integer aHighSensitivity = Max (Min (RealToInt (aSensitivityCoef * 15), 15), 3); // clamp sensitivity within range [3, 15] const Standard_Integer aLowSensitivity = Max (Min (RealToInt (aSensitivityCoef * 10), 10), 2); // clamp sensitivity within range [2, 10] // clang-format on switch (aMode) { case AIS_MM_Translation: { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { if (!myAxes[anIt].HasTranslation()) { continue; } const Axis& anAxis = myAxes[anIt]; anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9); // define sensitivity by line Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment(anOwner, gp::Origin(), anAxis.TranslatorTipPosition()); aLine->SetSensitivityFactor(aHighSensitivity); theSelection->Add(aLine); // enlarge sensitivity by triangulation Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray(anOwner); aTri->InitTriangulation(anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location()); theSelection->Add(aTri); } break; } case AIS_MM_Rotation: { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { if (!myAxes[anIt].HasRotation()) { continue; } const Axis& anAxis = myAxes[anIt]; anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Rotation, 9); // define sensitivity by circle const gp_Circ aGeomCircle(gp_Ax2(gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius()); Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle(anOwner, aGeomCircle); aCircle->SetSensitivityFactor(aLowSensitivity); theSelection->Add(aCircle); // enlarge sensitivity by triangulation Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation(anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction()); theSelection->Add(aTri); } break; } case AIS_MM_Scaling: { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { if (!myAxes[anIt].HasScaling()) { continue; } anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Scaling, 9); // define sensitivity by point Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint(anOwner, myAxes[anIt].ScalerCubePosition()); aPnt->SetSensitivityFactor(aHighSensitivity); theSelection->Add(aPnt); // enlarge sensitivity by triangulation Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True); theSelection->Add(aTri); } break; } case AIS_MM_TranslationPlane: { for (Standard_Integer anIt = 0; anIt < 3; ++anIt) { if (!myAxes[anIt].HasDragging()) { continue; } anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9); // define sensitivity by two crossed lines Standard_Real aSensitivityOffset = ZoomPersistence() ? aHighSensitivity * (0.5 + M_SQRT2) : 0.0; gp_Pnt aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition().Translated( myAxes[((anIt + 2) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset); gp_Pnt aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition().Translated( myAxes[((anIt + 1) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset); gp_XYZ aMidP = (aP1.XYZ() + aP2.XYZ()) / 2.0; gp_XYZ anOrig = aMidP.Normalized().Multiplied(aSensitivityOffset); Handle(Select3D_SensitiveSegment) aLine1 = new Select3D_SensitiveSegment(anOwner, aP1, aP2); aLine1->SetSensitivityFactor(aLowSensitivity); theSelection->Add(aLine1); Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, anOrig, aMidP); aLine2->SetSensitivityFactor(aLowSensitivity); theSelection->Add(aLine2); // enlarge sensitivity by triangulation Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True); theSelection->Add(aTri); } break; } default: { anOwner = new SelectMgr_EntityOwner(this, 5); break; } } } //======================================================================= // class : Disk // function : Init // purpose : //======================================================================= void AIS_Manipulator::Disk::Init(const Standard_ShortReal theInnerRadius, const Standard_ShortReal theOuterRadius, const gp_Ax1& thePosition, const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb) { myPosition = thePosition; myInnerRad = theInnerRadius; myOuterRad = theOuterRadius; Prs3d_ToolDisk aTool(theInnerRadius, theOuterRadius, theSlicesNb, theStacksNb); gp_Ax3 aSystem(myPosition.Location(), myPosition.Direction()); gp_Trsf aTrsf; aTrsf.SetTransformation(aSystem, gp_Ax3()); myArray = aTool.CreateTriangulation(aTrsf); myTriangulation = aTool.CreatePolyTriangulation(aTrsf); } //======================================================================= // class : Sphere // function : Init // purpose : //======================================================================= void AIS_Manipulator::Sphere::Init(const Standard_ShortReal theRadius, const gp_Pnt& thePosition, const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb) { myPosition = thePosition; myRadius = theRadius; Prs3d_ToolSphere aTool(theRadius, theSlicesNb, theStacksNb); gp_Trsf aTrsf; aTrsf.SetTranslation(gp_Vec(gp::Origin(), thePosition)); myArray = aTool.CreateTriangulation(aTrsf); myTriangulation = aTool.CreatePolyTriangulation(aTrsf); } //======================================================================= // class : Cube // function : Init // purpose : //======================================================================= void AIS_Manipulator::Cube::Init(const gp_Ax1& thePosition, const Standard_ShortReal theSize) { myArray = new Graphic3d_ArrayOfTriangles(12 * 3, 0, Standard_True); Poly_Array1OfTriangle aPolyTriangles(1, 12); TColgp_Array1OfPnt aPoints(1, 36); NCollection_Array1<gp_Dir> aNormals(1, 12); myTriangulation = new Poly_Triangulation(aPoints, aPolyTriangles); gp_Ax2 aPln(thePosition.Location(), thePosition.Direction()); gp_Pnt aBottomLeft = thePosition.Location().XYZ() - aPln.XDirection().XYZ() * theSize * 0.5 - aPln.YDirection().XYZ() * theSize * 0.5; gp_Pnt aV2 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize; gp_Pnt aV3 = aBottomLeft.XYZ() + aPln.YDirection().XYZ() * theSize + aPln.XDirection().XYZ() * theSize; gp_Pnt aV4 = aBottomLeft.XYZ() + aPln.XDirection().XYZ() * theSize; gp_Pnt aTopRight = thePosition.Location().XYZ() + thePosition.Direction().XYZ() * theSize + aPln.XDirection().XYZ() * theSize * 0.5 + aPln.YDirection().XYZ() * theSize * 0.5; gp_Pnt aV5 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize; gp_Pnt aV6 = aTopRight.XYZ() - aPln.YDirection().XYZ() * theSize - aPln.XDirection().XYZ() * theSize; gp_Pnt aV7 = aTopRight.XYZ() - aPln.XDirection().XYZ() * theSize; gp_Dir aRight((gp_Vec(aTopRight, aV7) ^ gp_Vec(aTopRight, aV2)).XYZ()); gp_Dir aFront((gp_Vec(aV3, aV4) ^ gp_Vec(aV3, aV5)).XYZ()); // Bottom addTriangle(0, aBottomLeft, aV2, aV3, -thePosition.Direction()); addTriangle(1, aBottomLeft, aV3, aV4, -thePosition.Direction()); // Front addTriangle(2, aV3, aV5, aV4, -aFront); addTriangle(3, aV3, aTopRight, aV5, -aFront); // Back addTriangle(4, aBottomLeft, aV7, aV2, aFront); addTriangle(5, aBottomLeft, aV6, aV7, aFront); // aTop addTriangle(6, aV7, aV6, aV5, thePosition.Direction()); addTriangle(7, aTopRight, aV7, aV5, thePosition.Direction()); // Left addTriangle(8, aV6, aV4, aV5, aRight); addTriangle(9, aBottomLeft, aV4, aV6, aRight); // Right addTriangle(10, aV3, aV7, aTopRight, -aRight); addTriangle(11, aV3, aV2, aV7, -aRight); } //======================================================================= // class : Cube // function : addTriangle // purpose : //======================================================================= void AIS_Manipulator::Cube::addTriangle(const Standard_Integer theIndex, const gp_Pnt& theP1, const gp_Pnt& theP2, const gp_Pnt& theP3, const gp_Dir& theNormal) { myTriangulation->SetNode(theIndex * 3 + 1, theP1); myTriangulation->SetNode(theIndex * 3 + 2, theP2); myTriangulation->SetNode(theIndex * 3 + 3, theP3); myTriangulation->SetTriangle(theIndex + 1, Poly_Triangle(theIndex * 3 + 1, theIndex * 3 + 2, theIndex * 3 + 3)); myArray->AddVertex(theP1, theNormal); myArray->AddVertex(theP2, theNormal); myArray->AddVertex(theP3, theNormal); } //======================================================================= // class : Sector // function : Init // purpose : //======================================================================= void AIS_Manipulator::Sector::Init(const Standard_ShortReal theRadius, const gp_Ax1& thePosition, const gp_Dir& theXDirection, const Standard_Integer theSlicesNb, const Standard_Integer theStacksNb) { Prs3d_ToolSector aTool(theRadius, theSlicesNb, theStacksNb); gp_Ax3 aSystem(thePosition.Location(), thePosition.Direction(), theXDirection); gp_Trsf aTrsf; aTrsf.SetTransformation(aSystem, gp_Ax3()); myArray = aTool.CreateTriangulation(aTrsf); myTriangulation = aTool.CreatePolyTriangulation(aTrsf); } //======================================================================= // class : Axis // function : Constructor // purpose : //======================================================================= AIS_Manipulator::Axis::Axis(const gp_Ax1& theAxis, const Quantity_Color& theColor, const Standard_ShortReal theLength) : myReferenceAxis(theAxis), myPosition(theAxis), myColor(theColor), myHasTranslation(Standard_True), myLength(theLength), myAxisRadius(0.5f), myHasScaling(Standard_True), myBoxSize(2.0f), myHasRotation(Standard_True), myInnerRadius(myLength + myBoxSize), myDiskThickness(myBoxSize * 0.5f), myIndent(0.2f), myHasDragging(Standard_True), myFacettesNumber(20), myCircleRadius(myLength + myBoxSize + myBoxSize * 0.5f * 0.5f) { // } //======================================================================= // class : Axis // function : Compute // purpose : //======================================================================= void AIS_Manipulator::Axis::Compute(const Handle(PrsMgr_PresentationManager)& thePrsMgr, const Handle(Prs3d_Presentation)& thePrs, const Handle(Prs3d_ShadingAspect)& theAspect) { if (myHasTranslation) { const Standard_Real anArrowLength = 0.25 * myLength; const Standard_Real aCylinderLength = myLength - anArrowLength; myArrowTipPos = gp_Pnt(0.0, 0.0, 0.0).Translated(myReferenceAxis.Direction().XYZ() * aCylinderLength); myTriangleArray = Prs3d_Arrow::DrawShaded(gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myAxisRadius, myLength, myAxisRadius * 1.5, anArrowLength, myFacettesNumber); myTranslatorGroup = thePrs->NewGroup(); myTranslatorGroup->SetClosed(true); myTranslatorGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); myTranslatorGroup->AddPrimitiveArray(myTriangleArray); if (myHighlightTranslator.IsNull()) { myHighlightTranslator = new Prs3d_Presentation(thePrsMgr->StructureManager()); } else { myHighlightTranslator->Clear(); } { Handle(Graphic3d_Group) aGroup = myHighlightTranslator->CurrentGroup(); aGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); aGroup->AddPrimitiveArray(myTriangleArray); } } if (myHasScaling) { myCubePos = myReferenceAxis.Direction().XYZ() * (myLength + myIndent); myCube.Init(gp_Ax1(myCubePos, myReferenceAxis.Direction()), myBoxSize); myScalerGroup = thePrs->NewGroup(); myScalerGroup->SetClosed(true); myScalerGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); myScalerGroup->AddPrimitiveArray(myCube.Array()); if (myHighlightScaler.IsNull()) { myHighlightScaler = new Prs3d_Presentation(thePrsMgr->StructureManager()); } else { myHighlightScaler->Clear(); } { Handle(Graphic3d_Group) aGroup = myHighlightScaler->CurrentGroup(); aGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); aGroup->AddPrimitiveArray(myCube.Array()); } } if (myHasRotation) { myCircleRadius = myInnerRadius + myIndent * 2 + myDiskThickness * 0.5f; myCircle.Init(myInnerRadius + myIndent * 2, myInnerRadius + myDiskThickness + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), myFacettesNumber * 2); myRotatorGroup = thePrs->NewGroup(); myRotatorGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); myRotatorGroup->AddPrimitiveArray(myCircle.Array()); if (myHighlightRotator.IsNull()) { myHighlightRotator = new Prs3d_Presentation(thePrsMgr->StructureManager()); } else { myHighlightRotator->Clear(); } { Handle(Graphic3d_Group) aGroup = myHighlightRotator->CurrentGroup(); aGroup->SetGroupPrimitivesAspect(theAspect->Aspect()); aGroup->AddPrimitiveArray(myCircle.Array()); } } if (myHasDragging) { gp_Dir aXDirection; if (myReferenceAxis.Direction().X() > 0) aXDirection = gp::DY(); else if (myReferenceAxis.Direction().Y() > 0) aXDirection = gp::DZ(); else aXDirection = gp::DX(); mySector.Init(myInnerRadius + myIndent * 2, gp_Ax1(gp::Origin(), myReferenceAxis.Direction()), aXDirection, myFacettesNumber * 2); myDraggerGroup = thePrs->NewGroup(); Handle(Graphic3d_AspectFillArea3d) aFillArea = new Graphic3d_AspectFillArea3d(); myDraggerGroup->SetGroupPrimitivesAspect(aFillArea); myDraggerGroup->AddPrimitiveArray(mySector.Array()); if (myHighlightDragger.IsNull()) { myHighlightDragger = new Prs3d_Presentation(thePrsMgr->StructureManager()); } else { myHighlightDragger->Clear(); } { Handle(Graphic3d_Group) aGroup = myHighlightDragger->CurrentGroup(); aGroup->SetGroupPrimitivesAspect(aFillArea); aGroup->AddPrimitiveArray(mySector.Array()); } } }