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 <SelectBasics_EntityOwner.hxx>
25 #include <SelectBasics_SensitiveEntity.hxx>
26 #include <SelectBasics_PickResult.hxx>
27 #include <SelectMgr_EntityOwner.hxx>
28 #include <SelectMgr_SortCriterion.hxx>
29 #include <SelectMgr_SensitiveEntitySet.hxx>
30 #include <TColStd_Array1OfInteger.hxx>
31 #include <TCollection_AsciiString.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColStd_ListOfInteger.hxx>
37 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
40 // Comparison operator for sorting selection results
45 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
46 : myMapOfCriterion (aMapOfCriterion)
50 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
52 return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
56 void operator = (const CompareResults&);
59 const SelectMgr_IndexedDataMapOfOwnerCriterion& myMapOfCriterion;
62 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
65 //=======================================================================
66 // function : updatePoint3d
68 //=======================================================================
69 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
70 const Handle(SelectBasics_SensitiveEntity)& theEntity,
71 const gp_GTrsf& theInversedTrsf,
72 const SelectMgr_SelectingVolumeManager& theMgr) const
74 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
79 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
80 gp_GTrsf anInvTrsf = theInversedTrsf;
81 if (theCriterion.Entity->HasInitLocation())
83 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
85 if (anInvTrsf.Form() != gp_Identity)
87 anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
90 if (mySelectingVolumeMgr.Camera().IsNull())
92 theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
94 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
96 theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
100 const Standard_Real aDistFromEye = (theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ());
101 theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
105 //==================================================
106 // Function: Initialize
108 //==================================================
109 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
110 preferclosest(Standard_True),
111 myToUpdateTolerance (Standard_True),
114 myIsLeftChildQueuedFirst (Standard_False),
117 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
120 //==================================================
121 // Function: Activate
123 //==================================================
124 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
126 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
128 aSelEntIter.Value()->SetActiveForSelection();
131 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
133 myTolerances.Add (theSelection->Sensitivity());
134 myToUpdateTolerance = Standard_True;
137 //==================================================
138 // Function: Deactivate
140 //==================================================
141 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
143 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
145 aSelEntIter.Value()->ResetSelectionActiveStatus();
148 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
150 myTolerances.Decrement (theSelection->Sensitivity());
151 myToUpdateTolerance = Standard_True;
154 //==================================================
157 //==================================================
158 void SelectMgr_ViewerSelector::Clear()
163 //=======================================================================
164 // function: isToScaleFrustum
165 // purpose : Checks if the entity given requires to scale current selecting frustum
166 //=======================================================================
167 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
169 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
170 && sensitivity (theEntity) < myTolerances.Tolerance();
173 //=======================================================================
174 // function: sensitivity
175 // purpose : In case if custom tolerance is set, this method will return sum of entity
176 // sensitivity and custom tolerance.
177 //=======================================================================
178 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
180 return myTolerances.IsCustomTolSet() ?
181 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
184 //=======================================================================
185 // function: checkOverlap
186 // purpose : Internal function that checks if a particular sensitive
187 // entity theEntity overlaps current selecting volume precisely
188 //=======================================================================
189 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
190 const gp_GTrsf& theInversedTrsf,
191 SelectMgr_SelectingVolumeManager& theMgr)
193 Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
194 Handle(SelectMgr_SelectableObject) aSelectable;
195 Standard_Boolean toRestoresViewClipEnabled = Standard_False;
196 if (!anOwner.IsNull())
198 aSelectable = anOwner->Selectable();
200 if (!aSelectable.IsNull())
202 if (!aSelectable->ClipPlanes().IsNull()
203 && aSelectable->ClipPlanes()->ToOverrideGlobal())
205 theMgr.SetViewClippingEnabled (Standard_False);
206 toRestoresViewClipEnabled = Standard_True;
208 else if (!aSelectable->TransformPersistence().IsNull())
210 if (aSelectable->TransformPersistence()->IsZoomOrRotate()
211 && !theMgr.ViewClipping().IsNull())
213 // Zoom/rotate persistence object lives in two worlds at the same time.
214 // Global clipping planes can not be trivially applied without being converted
215 // into local space of transformation persistence object.
216 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
217 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
219 const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
220 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
222 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
228 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
229 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
230 if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
237 theMgr.SetViewClippingEnabled (Standard_False);
238 toRestoresViewClipEnabled = Standard_True;
242 SelectBasics_PickResult aPickResult;
243 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
244 if (toRestoresViewClipEnabled)
246 theMgr.SetViewClippingEnabled (Standard_True);
255 if (HasDepthClipping (anOwner)
256 && !aSelectable.IsNull()
257 && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
259 Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
260 aPickResult.Depth());
265 SelectMgr_SortCriterion aCriterion;
266 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
267 aCriterion.Entity = theEntity;
268 aCriterion.Priority = anOwner->Priority();
269 aCriterion.Depth = aPickResult.Depth();
270 aCriterion.MinDist = aPickResult.DistToGeomCenter();
271 aCriterion.ToPreferClosest = preferclosest;
273 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
275 ++aPrevCriterion->NbOwnerMatches;
276 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
277 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
279 if (aCriterion > *aPrevCriterion)
281 updatePoint3d (aCriterion, theEntity, theInversedTrsf, theMgr);
282 *aPrevCriterion = aCriterion;
288 aCriterion.NbOwnerMatches = 1;
289 updatePoint3d (aCriterion, theEntity, theInversedTrsf, theMgr);
290 mystored.Add (anOwner, aCriterion);
294 //=======================================================================
295 // function: computeFrustum
296 // purpose : Internal function that checks if a current selecting frustum
297 // needs to be scaled and transformed for the entity and performs
298 // necessary calculations
299 //=======================================================================
300 void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
301 const SelectMgr_SelectingVolumeManager& theMgr,
302 const gp_GTrsf& theInvTrsf,
303 SelectMgr_FrustumCache& theCachedMgrs,
304 SelectMgr_SelectingVolumeManager& theResMgr)
306 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
307 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
308 const Standard_Boolean toScale = aScale != 1;
309 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
310 if (toScale && toTransform)
312 theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
316 if (!theCachedMgrs.IsBound (aScale))
318 theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
320 theResMgr = theCachedMgrs.Find (aScale);
322 else if (toTransform)
324 theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
328 //=======================================================================
329 // function: traverseObject
330 // purpose : Internal function that checks if there is possible overlap
331 // between some entity of selectable object theObject and
332 // current selecting volume
333 //=======================================================================
334 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
335 const SelectMgr_SelectingVolumeManager& theMgr,
336 const Handle(Graphic3d_Camera)& theCamera,
337 const Graphic3d_Mat4d& theProjectionMat,
338 const Graphic3d_Mat4d& theWorldViewMat,
339 const Standard_Integer theViewportWidth,
340 const Standard_Integer theViewportHeight)
342 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
343 if (anEntitySet->Size() == 0)
348 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
349 gp_GTrsf aInversedTrsf;
350 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
352 if (theObject->TransformPersistence().IsNull())
354 aInversedTrsf = theObject->InversedTransformation();
359 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
361 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
362 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
363 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
364 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
365 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
366 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
367 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
368 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
369 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
370 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
372 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
376 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
377 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
380 SelectMgr_FrustumCache aScaledTrnsfFrustums;
382 Standard_Integer aNode = 0; // a root node
383 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
384 aSensitivesTree->MaxPoint (0)))
389 const Standard_Integer aFirstStored = mystored.Extent() + 1;
391 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
392 Standard_Integer aHead = -1;
395 if (!aSensitivesTree->IsOuter (aNode))
397 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
398 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
399 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
400 aSensitivesTree->MaxPoint (aLeftChildIdx));
401 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
402 aSensitivesTree->MaxPoint (aRightChildIdx));
406 aNode = aLeftChildIdx;
408 aStack[aHead] = aRightChildIdx;
410 else if (isLeftChildIn
413 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
422 aNode = aStack[aHead];
428 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
429 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
430 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
432 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
433 if (aSensitive->IsActiveForSelection())
435 const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
436 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
437 computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
438 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
446 aNode = aStack[aHead];
451 // in case of Box/Polyline selection - keep only Owners having all Entities detected
452 if (mySelectingVolumeMgr.IsOverlapAllowed()
453 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
454 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
459 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
461 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
462 const Handle(SelectBasics_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
463 Standard_Integer aNbOwnerEntities = 0;
464 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
466 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
468 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
470 // Remove from index map.
471 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
472 // Hence, just keep iterating in backward direction.
473 mystored.RemoveFromIndex (aStoredIter);
481 //=======================================================================
482 // function: TraverseSensitives
483 // purpose : Traverses BVH containing all added selectable objects and
484 // finds candidates for further search of overlap
485 //=======================================================================
486 void SelectMgr_ViewerSelector::TraverseSensitives()
490 Standard_Integer aWidth;
491 Standard_Integer aHeight;
492 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
493 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
494 mySelectingVolumeMgr.ProjectionMatrix(),
495 mySelectingVolumeMgr.WorldViewMatrix(),
496 mySelectingVolumeMgr.WorldViewProjState(),
498 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
499 if (!aCamera.IsNull())
501 myCameraEye = aCamera->Eye().XYZ();
502 myCameraDir = aCamera->Direction().XYZ();
503 myCameraScale = aCamera->IsOrthographic()
505 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
506 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
507 myCameraScale *= aPixelSize;
510 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
512 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
513 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
515 if (mySelectableObjects.IsEmpty (aBVHSubset))
522 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
524 // for 2D space selection transform selecting volumes to perform overap testing
525 // directly in camera's eye space omitting the camera position, which is not
526 // needed there at all
527 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
529 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
530 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
531 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
532 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
533 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
534 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
535 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
536 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
537 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
538 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
539 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
541 // define corresponding frustum builder parameters
542 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
543 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
544 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
545 aBuilder->SetWindowSize (aWidth, aHeight);
546 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
550 aMgr = mySelectingVolumeMgr;
553 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
554 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
555 ? mySelectingVolumeMgr.WorldViewMatrix()
556 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
558 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
560 Standard_Integer aNode = 0;
561 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
566 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
567 Standard_Integer aHead = -1;
570 if (!aBVHTree->IsOuter (aNode))
572 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
573 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
574 const Standard_Boolean isLeftChildIn =
575 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
576 const Standard_Boolean isRightChildIn =
577 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
581 aNode = aLeftChildIdx;
583 aStack[aHead] = aRightChildIdx;
585 else if (isLeftChildIn
588 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
597 aNode = aStack[aHead];
603 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
604 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
605 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
607 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
608 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
610 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
617 aNode = aStack[aHead];
626 //==================================================
627 // Function: ClearPicked
629 //==================================================
630 void SelectMgr_ViewerSelector::ClearPicked()
635 //==================================================
638 //==================================================
639 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
642 Standard_Integer RankInMap = myIndexes->Value (myCurRank);
643 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
644 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
648 //=======================================================================
651 //=======================================================================
652 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
654 Handle(SelectMgr_EntityOwner) anOwner;
655 if (theRank < 1 || theRank > NbPicked())
660 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
661 const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
662 anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
666 //=======================================================================
667 //function : PickedData
669 //=======================================================================
670 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
672 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
673 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
674 return mystored.FindFromIndex (anOwnerIdx);
677 //===================================================
679 // INTERNAL METHODS ....
681 //==================================================
683 //==================================================
684 // Function: SetEntitySetBuilder
686 //==================================================
687 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
689 myEntitySetBuilder = theBuilder;
690 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
692 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
696 //==================================================
697 // Function: Contains
699 //==================================================
700 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
702 return mySelectableObjects.Contains (theObject);
705 //==================================================
706 // Function: ActiveModes
707 // Purpose : return all the modes with a given state for an object
708 //==================================================
709 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
710 TColStd_ListOfInteger& theModeList,
711 const SelectMgr_StateOfSelection theWantedState) const
713 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
714 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
716 if (theWantedState == SelectMgr_SOS_Any)
718 theModeList.Append (aSelIter.Value()->Mode());
720 else if (theWantedState == aSelIter.Value()->GetSelectionState())
722 theModeList.Append (aSelIter.Value()->Mode());
726 return hasActivatedStates;
729 //==================================================
730 // Function: IsActive
732 //==================================================
733 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
734 const Standard_Integer theMode) const
736 if (!Contains (theSelectableObject))
737 return Standard_False;
739 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
740 return !aSel.IsNull()
741 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
744 //==================================================
745 // Function: IsInside
747 //==================================================
748 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
749 const Standard_Integer theMode) const
751 if (!Contains (theSelectableObject))
752 return Standard_False;
754 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
755 return !aSel.IsNull()
756 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
760 //=======================================================================
763 //=======================================================================
765 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
767 return theSelection->GetSelectionState();
770 //==================================================
772 // Purpose : gives Information about selectors
773 //==================================================
775 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
777 TCollection_AsciiString aStatus ("Status Object :\n\t");
778 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
780 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
782 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
783 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
787 if (!Contains (theSelectableObject))
789 aStatus = aStatus + "Not Present in the selector\n\n";
795 //=======================================================================
796 //function : SortResult
797 //purpose : there is a certain number of entities ranged by criteria
798 // (depth, size, priority, mouse distance from borders or
799 // CDG of the detected primitive. Parsing :
800 // maximum priorities .
801 // then a reasonable compromise between depth and distance...
802 // finally the ranges are stored in myindexes depending on the parsing.
803 // so, it is possible to only read
804 //=======================================================================
805 void SelectMgr_ViewerSelector::SortResult()
807 if(mystored.IsEmpty()) return;
809 const Standard_Integer anExtent = mystored.Extent();
810 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
811 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
813 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
814 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
816 anIndexArray.SetValue (anIndexIter, anIndexIter);
818 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
821 //=======================================================================
822 //function : HasDepthClipping
824 //=======================================================================
825 Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
827 return Standard_False;
830 //=======================================================================
831 // function : AddSelectableObject
832 // purpose : Adds new object to the map of selectable objects
833 //=======================================================================
834 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
836 if (!myMapOfObjectSensitives.IsBound (theObject))
838 mySelectableObjects.Append (theObject);
839 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
840 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
844 //=======================================================================
845 // function : AddSelectionToObject
846 // purpose : Adds new selection to the object and builds its BVH tree
847 //=======================================================================
848 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
849 const Handle(SelectMgr_Selection)& theSelection)
851 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
853 (*anEntitySet)->Append (theSelection);
854 (*anEntitySet)->BVH();
858 AddSelectableObject (theObject);
859 AddSelectionToObject (theObject, theSelection);
863 //=======================================================================
864 // function : MoveSelectableObject
866 //=======================================================================
867 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
869 mySelectableObjects.ChangeSubset (theObject);
872 //=======================================================================
873 // function : RemoveSelectableObject
874 // purpose : Removes selectable object from map of selectable ones
875 //=======================================================================
876 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
878 Handle(SelectMgr_SelectableObject) anObj = theObject;
879 if (myMapOfObjectSensitives.UnBind (theObject))
881 mySelectableObjects.Remove (theObject);
885 //=======================================================================
886 // function : RemoveSelectionOfObject
887 // purpose : Removes selection of the object and marks its BVH tree
889 //=======================================================================
890 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
891 const Handle(SelectMgr_Selection)& theSelection)
893 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
895 (*anEntitySet)->Remove (theSelection);
899 //=======================================================================
900 // function : RebuildObjectsTree
901 // purpose : Marks BVH of selectable objects for rebuild
902 //=======================================================================
903 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
905 mySelectableObjects.MarkDirty();
909 Standard_Integer aViewportWidth, aViewportHeight;
910 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
912 Standard_Integer aWidth;
913 Standard_Integer aHeight;
914 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
915 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
916 mySelectingVolumeMgr.ProjectionMatrix(),
917 mySelectingVolumeMgr.WorldViewMatrix(),
918 mySelectingVolumeMgr.WorldViewProjState(),
923 //=======================================================================
924 // function : RebuildSensitivesTree
925 // purpose : Marks BVH of sensitive entities of particular selectable
926 // object for rebuild
927 //=======================================================================
928 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
929 const Standard_Boolean theIsForce)
931 if (!Contains (theObject))
934 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
935 anEntitySet->MarkDirty();
943 //=======================================================================
944 // function : resetSelectionActivationStatus
945 // purpose : Marks all added sensitive entities of all objects as
947 //=======================================================================
948 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
950 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
952 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
953 const Standard_Integer anEntitiesNb = anEntitySet->Size();
954 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
956 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
961 //=======================================================================
962 // function : DetectedEntity
963 // purpose : Returns sensitive entity that was detected during the
964 // previous run of selection algorithm
965 //=======================================================================
966 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
968 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
969 return mystored.FindFromIndex (aRankInMap).Entity;
972 //=======================================================================
973 // function : ActiveOwners
974 // purpose : Returns the list of active entity owners
975 //=======================================================================
976 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
978 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
980 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
981 const Standard_Integer anEntitiesNb = anEntitySet->Size();
982 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
984 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
985 if (aSensitive->IsActiveForSelection())
987 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
993 //=======================================================================
994 //function : AllowOverlapDetection
995 //purpose : Sets the detection type: if theIsToAllow is false,
996 // only fully included sensitives will be detected, otherwise
997 // the algorithm will mark both included and overlapped entities
999 //=======================================================================
1000 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1002 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);