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 SelectBasics_PickResult& thePickResult,
71 const Handle(SelectBasics_SensitiveEntity)& theEntity,
72 const gp_GTrsf& theInversedTrsf,
73 const SelectMgr_SelectingVolumeManager& theMgr) const
75 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
80 if (thePickResult.HasPickedPoint())
82 theCriterion.Point = thePickResult.PickedPoint();
84 else if (!thePickResult.IsValid())
86 theCriterion.Point = thePickResult.PickedPoint();
91 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
94 gp_GTrsf anInvTrsf = theInversedTrsf;
95 if (theCriterion.Entity->HasInitLocation())
97 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
99 if (anInvTrsf.Form() != gp_Identity)
101 anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
104 if (mySelectingVolumeMgr.Camera().IsNull())
106 theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
108 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
110 theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
114 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
115 theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
119 //==================================================
120 // Function: Initialize
122 //==================================================
123 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
124 preferclosest(Standard_True),
125 myToUpdateTolerance (Standard_True),
128 myIsLeftChildQueuedFirst (Standard_False),
131 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
134 //==================================================
135 // Function: Activate
137 //==================================================
138 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
140 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
142 aSelEntIter.Value()->SetActiveForSelection();
145 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
147 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
149 myTolerances.Add (theSelection->Sensitivity());
150 myToUpdateTolerance = Standard_True;
154 //==================================================
155 // Function: Deactivate
157 //==================================================
158 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
160 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
162 aSelEntIter.Value()->ResetSelectionActiveStatus();
165 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
167 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
169 myTolerances.Decrement (theSelection->Sensitivity());
170 myToUpdateTolerance = Standard_True;
174 //==================================================
177 //==================================================
178 void SelectMgr_ViewerSelector::Clear()
183 //=======================================================================
184 // function: isToScaleFrustum
185 // purpose : Checks if the entity given requires to scale current selecting frustum
186 //=======================================================================
187 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
189 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
190 && sensitivity (theEntity) < myTolerances.Tolerance();
193 //=======================================================================
194 // function: sensitivity
195 // purpose : In case if custom tolerance is set, this method will return sum of entity
196 // sensitivity and custom tolerance.
197 //=======================================================================
198 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
200 return myTolerances.IsCustomTolSet() ?
201 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
204 //=======================================================================
205 // function: checkOverlap
206 // purpose : Internal function that checks if a particular sensitive
207 // entity theEntity overlaps current selecting volume precisely
208 //=======================================================================
209 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
210 const gp_GTrsf& theInversedTrsf,
211 SelectMgr_SelectingVolumeManager& theMgr)
213 Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
214 Handle(SelectMgr_SelectableObject) aSelectable;
215 Standard_Boolean toRestoresViewClipEnabled = Standard_False;
216 if (!anOwner.IsNull())
218 aSelectable = anOwner->Selectable();
220 if (!aSelectable.IsNull())
222 if (!aSelectable->ClipPlanes().IsNull()
223 && aSelectable->ClipPlanes()->ToOverrideGlobal())
225 theMgr.SetViewClippingEnabled (Standard_False);
226 toRestoresViewClipEnabled = Standard_True;
228 else if (!aSelectable->TransformPersistence().IsNull())
230 if (aSelectable->TransformPersistence()->IsZoomOrRotate()
231 && !theMgr.ViewClipping().IsNull())
233 // Zoom/rotate persistence object lives in two worlds at the same time.
234 // Global clipping planes can not be trivially applied without being converted
235 // into local space of transformation persistence object.
236 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
237 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
239 const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
240 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
242 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
248 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
249 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
256 theMgr.SetViewClippingEnabled (Standard_False);
257 toRestoresViewClipEnabled = Standard_True;
261 SelectBasics_PickResult aPickResult;
262 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
263 if (toRestoresViewClipEnabled)
265 theMgr.SetViewClippingEnabled (Standard_True);
274 if (HasDepthClipping (anOwner)
275 && !aSelectable.IsNull()
276 && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
278 Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
279 aPickResult.Depth());
284 SelectMgr_SortCriterion aCriterion;
285 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
286 aCriterion.Entity = theEntity;
287 aCriterion.Priority = anOwner->Priority();
288 aCriterion.Depth = aPickResult.Depth();
289 aCriterion.MinDist = aPickResult.DistToGeomCenter();
290 aCriterion.ToPreferClosest = preferclosest;
292 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
294 ++aPrevCriterion->NbOwnerMatches;
295 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
296 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
298 if (aCriterion > *aPrevCriterion)
300 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
301 *aPrevCriterion = aCriterion;
307 aCriterion.NbOwnerMatches = 1;
308 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
309 mystored.Add (anOwner, aCriterion);
313 //=======================================================================
314 // function: computeFrustum
315 // purpose : Internal function that checks if a current selecting frustum
316 // needs to be scaled and transformed for the entity and performs
317 // necessary calculations
318 //=======================================================================
319 void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
320 const SelectMgr_SelectingVolumeManager& theMgr,
321 const gp_GTrsf& theInvTrsf,
322 SelectMgr_FrustumCache& theCachedMgrs,
323 SelectMgr_SelectingVolumeManager& theResMgr)
325 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
326 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
327 const Standard_Boolean toScale = aScale != 1;
328 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
329 if (toScale && toTransform)
331 theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
335 if (!theCachedMgrs.IsBound (aScale))
337 theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
339 theResMgr = theCachedMgrs.Find (aScale);
341 else if (toTransform)
343 theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
347 //=======================================================================
348 // function: traverseObject
349 // purpose : Internal function that checks if there is possible overlap
350 // between some entity of selectable object theObject and
351 // current selecting volume
352 //=======================================================================
353 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
354 const SelectMgr_SelectingVolumeManager& theMgr,
355 const Handle(Graphic3d_Camera)& theCamera,
356 const Graphic3d_Mat4d& theProjectionMat,
357 const Graphic3d_Mat4d& theWorldViewMat,
358 const Standard_Integer theViewportWidth,
359 const Standard_Integer theViewportHeight)
361 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
362 if (anEntitySet->Size() == 0)
367 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
368 gp_GTrsf aInversedTrsf;
369 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
371 if (theObject->TransformPersistence().IsNull())
373 aInversedTrsf = theObject->InversedTransformation();
378 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
380 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
381 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
382 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
383 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
384 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
385 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
386 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
387 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
388 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
389 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
391 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
395 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
396 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
399 SelectMgr_FrustumCache aScaledTrnsfFrustums;
401 Standard_Integer aNode = 0; // a root node
402 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
403 aSensitivesTree->MaxPoint (0)))
408 const Standard_Integer aFirstStored = mystored.Extent() + 1;
410 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
411 Standard_Integer aHead = -1;
414 if (!aSensitivesTree->IsOuter (aNode))
416 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
417 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
418 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
419 aSensitivesTree->MaxPoint (aLeftChildIdx));
420 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
421 aSensitivesTree->MaxPoint (aRightChildIdx));
425 aNode = aLeftChildIdx;
427 aStack[aHead] = aRightChildIdx;
429 else if (isLeftChildIn
432 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
441 aNode = aStack[aHead];
447 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
448 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
449 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
451 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
452 if (aSensitive->IsActiveForSelection())
454 const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
455 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
456 computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
457 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
465 aNode = aStack[aHead];
470 // in case of Box/Polyline selection - keep only Owners having all Entities detected
471 if (mySelectingVolumeMgr.IsOverlapAllowed()
472 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
473 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
478 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
480 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
481 const Handle(SelectBasics_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
482 Standard_Integer aNbOwnerEntities = 0;
483 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
485 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
487 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
489 // Remove from index map.
490 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
491 // Hence, just keep iterating in backward direction.
492 mystored.RemoveFromIndex (aStoredIter);
500 //=======================================================================
501 // function: TraverseSensitives
502 // purpose : Traverses BVH containing all added selectable objects and
503 // finds candidates for further search of overlap
504 //=======================================================================
505 void SelectMgr_ViewerSelector::TraverseSensitives()
509 Standard_Integer aWidth;
510 Standard_Integer aHeight;
511 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
512 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
513 mySelectingVolumeMgr.ProjectionMatrix(),
514 mySelectingVolumeMgr.WorldViewMatrix(),
515 mySelectingVolumeMgr.WorldViewProjState(),
517 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
518 if (!aCamera.IsNull())
520 myCameraEye = aCamera->Eye().XYZ();
521 myCameraDir = aCamera->Direction().XYZ();
522 myCameraScale = aCamera->IsOrthographic()
524 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
525 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
526 myCameraScale *= aPixelSize;
529 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
531 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
532 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
534 if (mySelectableObjects.IsEmpty (aBVHSubset))
541 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
543 // for 2D space selection transform selecting volumes to perform overap testing
544 // directly in camera's eye space omitting the camera position, which is not
545 // needed there at all
546 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
548 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
549 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
550 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
551 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
552 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
553 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
554 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
555 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
556 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
557 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
558 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
560 // define corresponding frustum builder parameters
561 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
562 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
563 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
564 aBuilder->SetWindowSize (aWidth, aHeight);
565 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
569 aMgr = mySelectingVolumeMgr;
572 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
573 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
574 ? mySelectingVolumeMgr.WorldViewMatrix()
575 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
577 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
579 Standard_Integer aNode = 0;
580 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
585 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
586 Standard_Integer aHead = -1;
589 if (!aBVHTree->IsOuter (aNode))
591 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
592 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
593 const Standard_Boolean isLeftChildIn =
594 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
595 const Standard_Boolean isRightChildIn =
596 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
600 aNode = aLeftChildIdx;
602 aStack[aHead] = aRightChildIdx;
604 else if (isLeftChildIn
607 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
616 aNode = aStack[aHead];
622 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
623 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
624 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
626 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
627 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
629 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
636 aNode = aStack[aHead];
645 //==================================================
646 // Function: ClearPicked
648 //==================================================
649 void SelectMgr_ViewerSelector::ClearPicked()
654 //==================================================
657 //==================================================
658 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
661 Standard_Integer RankInMap = myIndexes->Value (myCurRank);
662 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
663 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
667 //=======================================================================
670 //=======================================================================
671 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
673 Handle(SelectMgr_EntityOwner) anOwner;
674 if (theRank < 1 || theRank > NbPicked())
679 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
680 const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
681 anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
685 //=======================================================================
686 //function : PickedData
688 //=======================================================================
689 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
691 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
692 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
693 return mystored.FindFromIndex (anOwnerIdx);
696 //===================================================
698 // INTERNAL METHODS ....
700 //==================================================
702 //==================================================
703 // Function: SetEntitySetBuilder
705 //==================================================
706 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
708 myEntitySetBuilder = theBuilder;
709 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
711 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
715 //==================================================
716 // Function: Contains
718 //==================================================
719 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
721 return mySelectableObjects.Contains (theObject);
724 //==================================================
725 // Function: ActiveModes
726 // Purpose : return all the modes with a given state for an object
727 //==================================================
728 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
729 TColStd_ListOfInteger& theModeList,
730 const SelectMgr_StateOfSelection theWantedState) const
732 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
733 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
735 if (theWantedState == SelectMgr_SOS_Any)
737 theModeList.Append (aSelIter.Value()->Mode());
739 else if (theWantedState == aSelIter.Value()->GetSelectionState())
741 theModeList.Append (aSelIter.Value()->Mode());
745 return hasActivatedStates;
748 //==================================================
749 // Function: IsActive
751 //==================================================
752 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
753 const Standard_Integer theMode) const
755 if (!Contains (theSelectableObject))
756 return Standard_False;
758 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
759 return !aSel.IsNull()
760 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
763 //==================================================
764 // Function: IsInside
766 //==================================================
767 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
768 const Standard_Integer theMode) const
770 if (!Contains (theSelectableObject))
771 return Standard_False;
773 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
774 return !aSel.IsNull()
775 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
779 //=======================================================================
782 //=======================================================================
784 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
786 return theSelection->GetSelectionState();
789 //==================================================
791 // Purpose : gives Information about selectors
792 //==================================================
794 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
796 TCollection_AsciiString aStatus ("Status Object :\n\t");
797 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
799 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
801 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
802 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
806 if (!Contains (theSelectableObject))
808 aStatus = aStatus + "Not Present in the selector\n\n";
814 //=======================================================================
815 //function : SortResult
816 //purpose : there is a certain number of entities ranged by criteria
817 // (depth, size, priority, mouse distance from borders or
818 // CDG of the detected primitive. Parsing :
819 // maximum priorities .
820 // then a reasonable compromise between depth and distance...
821 // finally the ranges are stored in myindexes depending on the parsing.
822 // so, it is possible to only read
823 //=======================================================================
824 void SelectMgr_ViewerSelector::SortResult()
826 if(mystored.IsEmpty()) return;
828 const Standard_Integer anExtent = mystored.Extent();
829 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
830 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
832 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
833 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
835 anIndexArray.SetValue (anIndexIter, anIndexIter);
837 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
840 //=======================================================================
841 //function : HasDepthClipping
843 //=======================================================================
844 Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
846 return Standard_False;
849 //=======================================================================
850 // function : AddSelectableObject
851 // purpose : Adds new object to the map of selectable objects
852 //=======================================================================
853 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
855 if (!myMapOfObjectSensitives.IsBound (theObject))
857 mySelectableObjects.Append (theObject);
858 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
859 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
863 //=======================================================================
864 // function : AddSelectionToObject
865 // purpose : Adds new selection to the object and builds its BVH tree
866 //=======================================================================
867 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
868 const Handle(SelectMgr_Selection)& theSelection)
870 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
872 (*anEntitySet)->Append (theSelection);
873 (*anEntitySet)->BVH();
877 AddSelectableObject (theObject);
878 AddSelectionToObject (theObject, theSelection);
882 //=======================================================================
883 // function : MoveSelectableObject
885 //=======================================================================
886 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
888 mySelectableObjects.ChangeSubset (theObject);
891 //=======================================================================
892 // function : RemoveSelectableObject
893 // purpose : Removes selectable object from map of selectable ones
894 //=======================================================================
895 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
897 Handle(SelectMgr_SelectableObject) anObj = theObject;
898 if (myMapOfObjectSensitives.UnBind (theObject))
900 mySelectableObjects.Remove (theObject);
904 //=======================================================================
905 // function : RemoveSelectionOfObject
906 // purpose : Removes selection of the object and marks its BVH tree
908 //=======================================================================
909 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
910 const Handle(SelectMgr_Selection)& theSelection)
912 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
914 (*anEntitySet)->Remove (theSelection);
918 //=======================================================================
919 // function : RebuildObjectsTree
920 // purpose : Marks BVH of selectable objects for rebuild
921 //=======================================================================
922 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
924 mySelectableObjects.MarkDirty();
928 Standard_Integer aViewportWidth, aViewportHeight;
929 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
931 Standard_Integer aWidth;
932 Standard_Integer aHeight;
933 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
934 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
935 mySelectingVolumeMgr.ProjectionMatrix(),
936 mySelectingVolumeMgr.WorldViewMatrix(),
937 mySelectingVolumeMgr.WorldViewProjState(),
942 //=======================================================================
943 // function : RebuildSensitivesTree
944 // purpose : Marks BVH of sensitive entities of particular selectable
945 // object for rebuild
946 //=======================================================================
947 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
948 const Standard_Boolean theIsForce)
950 if (!Contains (theObject))
953 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
954 anEntitySet->MarkDirty();
962 //=======================================================================
963 // function : resetSelectionActivationStatus
964 // purpose : Marks all added sensitive entities of all objects as
966 //=======================================================================
967 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
969 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
971 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
972 const Standard_Integer anEntitiesNb = anEntitySet->Size();
973 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
975 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
980 //=======================================================================
981 // function : DetectedEntity
982 // purpose : Returns sensitive entity that was detected during the
983 // previous run of selection algorithm
984 //=======================================================================
985 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
987 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
988 return mystored.FindFromIndex (aRankInMap).Entity;
991 //=======================================================================
992 // function : ActiveOwners
993 // purpose : Returns the list of active entity owners
994 //=======================================================================
995 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
997 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
999 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1000 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1001 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1003 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1004 if (aSensitive->IsActiveForSelection())
1006 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1012 //=======================================================================
1013 //function : AllowOverlapDetection
1014 //purpose : Sets the detection type: if theIsToAllow is false,
1015 // only fully included sensitives will be detected, otherwise
1016 // the algorithm will mark both included and overlapped entities
1018 //=======================================================================
1019 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1021 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);