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