1 // Created on: 1995-02-15
2 // Created by: Roberc Coublanc
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <SelectMgr_ViewerSelector.hxx>
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_SensitiveEntity.hxx>
25 #include <SelectBasics_PickResult.hxx>
26 #include <SelectMgr_EntityOwner.hxx>
27 #include <SelectMgr_SortCriterion.hxx>
28 #include <SelectMgr_SensitiveEntitySet.hxx>
29 #include <TColStd_Array1OfInteger.hxx>
30 #include <TCollection_AsciiString.hxx>
31 #include <TColStd_HArray1OfInteger.hxx>
32 #include <TColStd_ListOfInteger.hxx>
36 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
39 // Comparison operator for sorting selection results
44 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
45 : myMapOfCriterion (aMapOfCriterion)
49 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
51 return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
55 void operator = (const CompareResults&);
58 const SelectMgr_IndexedDataMapOfOwnerCriterion& myMapOfCriterion;
61 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
64 //=======================================================================
65 // function : updatePoint3d
67 //=======================================================================
68 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
69 const SelectBasics_PickResult& thePickResult,
70 const Handle(Select3D_SensitiveEntity)& theEntity,
71 const gp_GTrsf& theInversedTrsf,
72 const SelectMgr_SelectingVolumeManager& theMgr) const
74 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
79 if (thePickResult.HasPickedPoint())
81 theCriterion.Point = thePickResult.PickedPoint();
83 else if (!thePickResult.IsValid())
85 theCriterion.Point = thePickResult.PickedPoint();
90 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
93 gp_GTrsf anInvTrsf = theInversedTrsf;
94 if (theCriterion.Entity->HasInitLocation())
96 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
98 if (anInvTrsf.Form() != gp_Identity)
100 anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
103 if (mySelectingVolumeMgr.Camera().IsNull())
105 theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
107 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
109 theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
113 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
114 theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
118 //==================================================
119 // Function: Initialize
121 //==================================================
122 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
123 preferclosest(Standard_True),
124 myToUpdateTolerance (Standard_True),
127 myIsLeftChildQueuedFirst (Standard_False),
130 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
133 //==================================================
134 // Function: Activate
136 //==================================================
137 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
139 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
141 aSelEntIter.Value()->SetActiveForSelection();
144 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
146 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
148 myTolerances.Add (theSelection->Sensitivity());
149 myToUpdateTolerance = Standard_True;
153 //==================================================
154 // Function: Deactivate
156 //==================================================
157 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
159 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
161 aSelEntIter.Value()->ResetSelectionActiveStatus();
164 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
166 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
168 myTolerances.Decrement (theSelection->Sensitivity());
169 myToUpdateTolerance = Standard_True;
173 //==================================================
176 //==================================================
177 void SelectMgr_ViewerSelector::Clear()
182 //=======================================================================
183 // function: isToScaleFrustum
184 // purpose : Checks if the entity given requires to scale current selecting frustum
185 //=======================================================================
186 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
188 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
189 && sensitivity (theEntity) < myTolerances.Tolerance();
192 //=======================================================================
193 // function: sensitivity
194 // purpose : In case if custom tolerance is set, this method will return sum of entity
195 // sensitivity and custom tolerance.
196 //=======================================================================
197 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
199 return myTolerances.IsCustomTolSet() ?
200 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
203 //=======================================================================
204 // function: checkOverlap
205 // purpose : Internal function that checks if a particular sensitive
206 // entity theEntity overlaps current selecting volume precisely
207 //=======================================================================
208 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
209 const gp_GTrsf& theInversedTrsf,
210 SelectMgr_SelectingVolumeManager& theMgr)
212 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
213 Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
214 SelectBasics_PickResult aPickResult;
215 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
222 SelectMgr_SortCriterion aCriterion;
223 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
224 aCriterion.Entity = theEntity;
225 aCriterion.Priority = anOwner->Priority();
226 aCriterion.Depth = aPickResult.Depth();
227 aCriterion.MinDist = aPickResult.DistToGeomCenter();
228 aCriterion.ToPreferClosest = preferclosest;
230 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
232 ++aPrevCriterion->NbOwnerMatches;
233 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
234 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
236 if (aCriterion > *aPrevCriterion)
238 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
239 *aPrevCriterion = aCriterion;
245 aCriterion.NbOwnerMatches = 1;
246 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
247 mystored.Add (anOwner, aCriterion);
251 //=======================================================================
252 // function: computeFrustum
253 // purpose : Internal function that checks if a current selecting frustum
254 // needs to be scaled and transformed for the entity and performs
255 // necessary calculations
256 //=======================================================================
257 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
258 const SelectMgr_SelectingVolumeManager& theMgr,
259 const gp_GTrsf& theInvTrsf,
260 SelectMgr_FrustumCache& theCachedMgrs,
261 SelectMgr_SelectingVolumeManager& theResMgr)
263 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
264 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
265 const Standard_Boolean toScale = aScale != 1;
266 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
267 if (toScale && toTransform)
269 theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
273 if (!theCachedMgrs.IsBound (aScale))
275 theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
277 theResMgr = theCachedMgrs.Find (aScale);
279 else if (toTransform)
281 theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
285 //=======================================================================
286 // function: traverseObject
287 // purpose : Internal function that checks if there is possible overlap
288 // between some entity of selectable object theObject and
289 // current selecting volume
290 //=======================================================================
291 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
292 const SelectMgr_SelectingVolumeManager& theMgr,
293 const Handle(Graphic3d_Camera)& theCamera,
294 const Graphic3d_Mat4d& theProjectionMat,
295 const Graphic3d_Mat4d& theWorldViewMat,
296 const Standard_Integer theViewportWidth,
297 const Standard_Integer theViewportHeight)
299 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
300 if (anEntitySet->Size() == 0)
305 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
306 gp_GTrsf aInversedTrsf;
307 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
309 if (theObject->TransformPersistence().IsNull())
311 aInversedTrsf = theObject->InversedTransformation();
316 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
318 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
319 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
320 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
321 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
322 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
323 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
324 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
325 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
326 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
327 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
329 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
333 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
334 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
336 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
337 aSensitivesTree->MaxPoint (0)))
342 if (!theObject->ClipPlanes().IsNull()
343 && theObject->ClipPlanes()->ToOverrideGlobal())
345 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
347 else if (!theObject->TransformPersistence().IsNull())
349 if (theObject->TransformPersistence()->IsZoomOrRotate()
350 && !theMgr.ViewClipping().IsNull())
352 // Zoom/rotate persistence object lives in two worlds at the same time.
353 // Global clipping planes can not be trivially applied without being converted
354 // into local space of transformation persistence object.
355 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
356 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
357 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
359 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
365 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
366 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
373 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
375 else if (!theObject->ClipPlanes().IsNull()
376 && !theObject->ClipPlanes()->IsEmpty())
378 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes());
381 const Standard_Integer aFirstStored = mystored.Extent() + 1;
383 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
384 Standard_Integer aHead = -1;
385 Standard_Integer aNode = 0; // a root node
386 SelectMgr_FrustumCache aScaledTrnsfFrustums;
389 if (!aSensitivesTree->IsOuter (aNode))
391 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
392 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
393 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
394 aSensitivesTree->MaxPoint (aLeftChildIdx));
395 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
396 aSensitivesTree->MaxPoint (aRightChildIdx));
400 aNode = aLeftChildIdx;
402 aStack[aHead] = aRightChildIdx;
404 else if (isLeftChildIn
407 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
416 aNode = aStack[aHead];
422 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
423 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
424 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
426 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
427 if (aSensitive->IsActiveForSelection())
429 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
430 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
431 computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
432 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
440 aNode = aStack[aHead];
445 // in case of Box/Polyline selection - keep only Owners having all Entities detected
446 if (mySelectingVolumeMgr.IsOverlapAllowed()
447 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
448 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
453 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
455 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
456 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
457 Standard_Integer aNbOwnerEntities = 0;
458 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
460 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
462 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
464 // Remove from index map.
465 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
466 // Hence, just keep iterating in backward direction.
467 mystored.RemoveFromIndex (aStoredIter);
475 //=======================================================================
476 // function: TraverseSensitives
477 // purpose : Traverses BVH containing all added selectable objects and
478 // finds candidates for further search of overlap
479 //=======================================================================
480 void SelectMgr_ViewerSelector::TraverseSensitives()
484 Standard_Integer aWidth;
485 Standard_Integer aHeight;
486 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
487 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
488 mySelectingVolumeMgr.ProjectionMatrix(),
489 mySelectingVolumeMgr.WorldViewMatrix(),
490 mySelectingVolumeMgr.WorldViewProjState(),
492 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
493 if (!aCamera.IsNull())
495 myCameraEye = aCamera->Eye().XYZ();
496 myCameraDir = aCamera->Direction().XYZ();
497 myCameraScale = aCamera->IsOrthographic()
499 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
500 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
501 myCameraScale *= aPixelSize;
504 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
506 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
507 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
509 if (mySelectableObjects.IsEmpty (aBVHSubset))
516 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
518 // for 2D space selection transform selecting volumes to perform overap testing
519 // directly in camera's eye space omitting the camera position, which is not
520 // needed there at all
521 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
523 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
524 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
525 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
526 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
527 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
528 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
529 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
530 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
531 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
532 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
533 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
535 // define corresponding frustum builder parameters
536 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
537 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
538 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
539 aBuilder->SetWindowSize (aWidth, aHeight);
540 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
544 aMgr = mySelectingVolumeMgr;
547 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
548 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
549 ? mySelectingVolumeMgr.WorldViewMatrix()
550 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
552 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
554 Standard_Integer aNode = 0;
555 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
560 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
561 Standard_Integer aHead = -1;
564 if (!aBVHTree->IsOuter (aNode))
566 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
567 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
568 const Standard_Boolean isLeftChildIn =
569 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
570 const Standard_Boolean isRightChildIn =
571 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
575 aNode = aLeftChildIdx;
577 aStack[aHead] = aRightChildIdx;
579 else if (isLeftChildIn
582 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
591 aNode = aStack[aHead];
597 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
598 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
599 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
601 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
602 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
604 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
611 aNode = aStack[aHead];
620 //==================================================
621 // Function: ClearPicked
623 //==================================================
624 void SelectMgr_ViewerSelector::ClearPicked()
629 //==================================================
632 //==================================================
633 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
635 const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
636 const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
640 //=======================================================================
643 //=======================================================================
644 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
646 if (theRank < 1 || theRank > NbPicked())
648 return Handle(SelectMgr_EntityOwner)();
651 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
652 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
656 //=======================================================================
657 //function : PickedData
659 //=======================================================================
660 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
662 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
663 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
664 return mystored.FindFromIndex (anOwnerIdx);
667 //===================================================
669 // INTERNAL METHODS ....
671 //==================================================
673 //==================================================
674 // Function: SetEntitySetBuilder
676 //==================================================
677 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
679 myEntitySetBuilder = theBuilder;
680 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
682 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
686 //==================================================
687 // Function: Contains
689 //==================================================
690 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
692 return mySelectableObjects.Contains (theObject);
695 //==================================================
696 // Function: ActiveModes
697 // Purpose : return all the modes with a given state for an object
698 //==================================================
699 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
700 TColStd_ListOfInteger& theModeList,
701 const SelectMgr_StateOfSelection theWantedState) const
703 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
704 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
706 if (theWantedState == SelectMgr_SOS_Any)
708 theModeList.Append (aSelIter.Value()->Mode());
710 else if (theWantedState == aSelIter.Value()->GetSelectionState())
712 theModeList.Append (aSelIter.Value()->Mode());
716 return hasActivatedStates;
719 //==================================================
720 // Function: IsActive
722 //==================================================
723 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
724 const Standard_Integer theMode) const
726 if (!Contains (theSelectableObject))
727 return Standard_False;
729 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
730 return !aSel.IsNull()
731 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
734 //==================================================
735 // Function: IsInside
737 //==================================================
738 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
739 const Standard_Integer theMode) const
741 if (!Contains (theSelectableObject))
742 return Standard_False;
744 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
745 return !aSel.IsNull()
746 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
750 //=======================================================================
753 //=======================================================================
755 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
757 return theSelection->GetSelectionState();
760 //==================================================
762 // Purpose : gives Information about selectors
763 //==================================================
765 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
767 TCollection_AsciiString aStatus ("Status Object :\n\t");
768 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
770 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
772 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
773 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
777 if (!Contains (theSelectableObject))
779 aStatus = aStatus + "Not Present in the selector\n\n";
785 //=======================================================================
786 //function : SortResult
787 //purpose : there is a certain number of entities ranged by criteria
788 // (depth, size, priority, mouse distance from borders or
789 // CDG of the detected primitive. Parsing :
790 // maximum priorities .
791 // then a reasonable compromise between depth and distance...
792 // finally the ranges are stored in myindexes depending on the parsing.
793 // so, it is possible to only read
794 //=======================================================================
795 void SelectMgr_ViewerSelector::SortResult()
797 if(mystored.IsEmpty()) return;
799 const Standard_Integer anExtent = mystored.Extent();
800 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
801 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
803 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
804 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
806 anIndexArray.SetValue (anIndexIter, anIndexIter);
808 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
811 //=======================================================================
812 // function : AddSelectableObject
813 // purpose : Adds new object to the map of selectable objects
814 //=======================================================================
815 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
817 if (!myMapOfObjectSensitives.IsBound (theObject))
819 mySelectableObjects.Append (theObject);
820 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
821 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
825 //=======================================================================
826 // function : AddSelectionToObject
827 // purpose : Adds new selection to the object and builds its BVH tree
828 //=======================================================================
829 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
830 const Handle(SelectMgr_Selection)& theSelection)
832 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
834 (*anEntitySet)->Append (theSelection);
835 (*anEntitySet)->BVH();
839 AddSelectableObject (theObject);
840 AddSelectionToObject (theObject, theSelection);
844 //=======================================================================
845 // function : MoveSelectableObject
847 //=======================================================================
848 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
850 mySelectableObjects.ChangeSubset (theObject);
853 //=======================================================================
854 // function : RemoveSelectableObject
855 // purpose : Removes selectable object from map of selectable ones
856 //=======================================================================
857 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
859 Handle(SelectMgr_SelectableObject) anObj = theObject;
860 if (myMapOfObjectSensitives.UnBind (theObject))
862 mySelectableObjects.Remove (theObject);
866 //=======================================================================
867 // function : RemoveSelectionOfObject
868 // purpose : Removes selection of the object and marks its BVH tree
870 //=======================================================================
871 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
872 const Handle(SelectMgr_Selection)& theSelection)
874 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
876 (*anEntitySet)->Remove (theSelection);
880 //=======================================================================
881 // function : RebuildObjectsTree
882 // purpose : Marks BVH of selectable objects for rebuild
883 //=======================================================================
884 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
886 mySelectableObjects.MarkDirty();
890 Standard_Integer aViewportWidth, aViewportHeight;
891 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
893 Standard_Integer aWidth;
894 Standard_Integer aHeight;
895 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
896 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
897 mySelectingVolumeMgr.ProjectionMatrix(),
898 mySelectingVolumeMgr.WorldViewMatrix(),
899 mySelectingVolumeMgr.WorldViewProjState(),
904 //=======================================================================
905 // function : RebuildSensitivesTree
906 // purpose : Marks BVH of sensitive entities of particular selectable
907 // object for rebuild
908 //=======================================================================
909 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
910 const Standard_Boolean theIsForce)
912 if (!Contains (theObject))
915 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
916 anEntitySet->MarkDirty();
924 //=======================================================================
925 // function : resetSelectionActivationStatus
926 // purpose : Marks all added sensitive entities of all objects as
928 //=======================================================================
929 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
931 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
933 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
934 const Standard_Integer anEntitiesNb = anEntitySet->Size();
935 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
937 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
942 //=======================================================================
943 // function : DetectedEntity
944 // purpose : Returns sensitive entity that was detected during the
945 // previous run of selection algorithm
946 //=======================================================================
947 const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
949 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
950 return mystored.FindFromIndex (aRankInMap).Entity;
953 //=======================================================================
954 // function : ActiveOwners
955 // purpose : Returns the list of active entity owners
956 //=======================================================================
957 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
959 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
961 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
962 const Standard_Integer anEntitiesNb = anEntitySet->Size();
963 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
965 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
966 if (aSensitive->IsActiveForSelection())
968 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
974 //=======================================================================
975 //function : AllowOverlapDetection
976 //purpose : Sets the detection type: if theIsToAllow is false,
977 // only fully included sensitives will be detected, otherwise
978 // the algorithm will mark both included and overlapped entities
980 //=======================================================================
981 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
983 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);