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
254 //=======================================================================
255 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
256 const SelectMgr_SelectingVolumeManager& theMgrGlobal,
257 const SelectMgr_SelectingVolumeManager& theMgrObject,
258 const gp_GTrsf& theInvTrsf,
259 SelectMgr_FrustumCache& theCachedMgrs,
260 SelectMgr_SelectingVolumeManager& theResMgr)
262 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
263 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
264 const Standard_Boolean toScale = aScale != 1;
265 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
266 if (toScale && toTransform)
268 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
269 theResMgr.SetViewClipping (theMgrObject);
273 if (!theCachedMgrs.Find (aScale, theResMgr))
275 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
276 theCachedMgrs.Bind (aScale, theResMgr);
278 theResMgr.SetViewClipping (theMgrObject);
280 else if (toTransform)
282 theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
283 theResMgr.SetViewClipping (theMgrObject);
287 theResMgr = theMgrObject;
291 //=======================================================================
292 // function: traverseObject
293 // purpose : Internal function that checks if there is possible overlap
294 // between some entity of selectable object theObject and
295 // current selecting volume
296 //=======================================================================
297 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
298 const SelectMgr_SelectingVolumeManager& theMgr,
299 const Handle(Graphic3d_Camera)& theCamera,
300 const Graphic3d_Mat4d& theProjectionMat,
301 const Graphic3d_Mat4d& theWorldViewMat,
302 const Standard_Integer theViewportWidth,
303 const Standard_Integer theViewportHeight)
305 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
306 if (anEntitySet->Size() == 0)
311 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
312 gp_GTrsf aInversedTrsf;
313 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
315 if (theObject->TransformPersistence().IsNull())
317 aInversedTrsf = theObject->InversedTransformation();
322 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
324 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
325 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
326 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
327 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
328 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
329 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
330 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
331 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
332 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
333 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
335 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
339 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
340 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
342 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
343 aSensitivesTree->MaxPoint (0)))
348 if (!theObject->ClipPlanes().IsNull()
349 && theObject->ClipPlanes()->ToOverrideGlobal())
351 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
353 else if (!theObject->TransformPersistence().IsNull())
355 if (theObject->TransformPersistence()->IsZoomOrRotate()
356 && !theMgr.ViewClipping().IsNull())
358 // Zoom/rotate persistence object lives in two worlds at the same time.
359 // Global clipping planes can not be trivially applied without being converted
360 // into local space of transformation persistence object.
361 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
362 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
363 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
365 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
371 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
372 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
379 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
381 else if (!theObject->ClipPlanes().IsNull()
382 && !theObject->ClipPlanes()->IsEmpty())
384 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes());
387 if (!theMgr.ViewClipping().IsNull() &&
388 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
390 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
391 // If box selection is active, and the whole sensitive tree is out of the clip planes
392 // selection is empty for this object
393 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
395 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
397 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
403 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
404 if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
411 const Standard_Integer aFirstStored = mystored.Extent() + 1;
413 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
414 Standard_Integer aHead = -1;
415 Standard_Integer aNode = 0; // a root node
416 SelectMgr_FrustumCache aScaledTrnsfFrustums;
417 SelectMgr_SelectingVolumeManager aTmpMgr (false);
420 if (!aSensitivesTree->IsOuter (aNode))
422 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
423 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
424 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
425 aSensitivesTree->MaxPoint (aLeftChildIdx));
426 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
427 aSensitivesTree->MaxPoint (aRightChildIdx));
431 aNode = aLeftChildIdx;
433 aStack[aHead] = aRightChildIdx;
435 else if (isLeftChildIn
438 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
447 aNode = aStack[aHead];
453 bool aClipped = false;
454 if (!theMgr.ViewClipping().IsNull() &&
455 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
457 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
458 // If box selection is active, and the whole sensitive tree is out of the clip planes
459 // selection is empty for this object
460 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
462 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
464 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
469 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
470 if (aState == Graphic3d_ClipState_Out)
475 if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
477 if (aPlane->ProbeBoxTouch (aBBox))
486 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
487 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
488 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
490 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
491 if (aSensitive->IsActiveForSelection())
493 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
494 computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
495 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
504 aNode = aStack[aHead];
509 // in case of Box/Polyline selection - keep only Owners having all Entities detected
510 if (mySelectingVolumeMgr.IsOverlapAllowed()
511 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
512 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
517 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
519 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
520 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
521 Standard_Integer aNbOwnerEntities = 0;
522 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
524 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
526 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
528 // Remove from index map.
529 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
530 // Hence, just keep iterating in backward direction.
531 mystored.RemoveFromIndex (aStoredIter);
539 //=======================================================================
540 // function: TraverseSensitives
541 // purpose : Traverses BVH containing all added selectable objects and
542 // finds candidates for further search of overlap
543 //=======================================================================
544 void SelectMgr_ViewerSelector::TraverseSensitives()
548 Standard_Integer aWidth;
549 Standard_Integer aHeight;
550 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
551 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
552 mySelectingVolumeMgr.ProjectionMatrix(),
553 mySelectingVolumeMgr.WorldViewMatrix(),
554 mySelectingVolumeMgr.WorldViewProjState(),
556 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
557 if (!aCamera.IsNull())
559 myCameraEye = aCamera->Eye().XYZ();
560 myCameraDir = aCamera->Direction().XYZ();
561 myCameraScale = aCamera->IsOrthographic()
563 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
564 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
565 myCameraScale *= aPixelSize;
568 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
570 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
571 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
573 if (mySelectableObjects.IsEmpty (aBVHSubset))
580 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
582 // for 2D space selection transform selecting volumes to perform overap testing
583 // directly in camera's eye space omitting the camera position, which is not
584 // needed there at all
585 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
587 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
588 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
589 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
590 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
591 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
592 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
593 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
594 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
595 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
596 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
597 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
599 // define corresponding frustum builder parameters
600 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
601 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
602 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
603 aBuilder->SetWindowSize (aWidth, aHeight);
604 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
608 aMgr = mySelectingVolumeMgr;
611 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
612 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
613 ? mySelectingVolumeMgr.WorldViewMatrix()
614 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
616 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
618 Standard_Integer aNode = 0;
619 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
624 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
625 Standard_Integer aHead = -1;
628 if (!aBVHTree->IsOuter (aNode))
630 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
631 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
632 const Standard_Boolean isLeftChildIn =
633 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
634 const Standard_Boolean isRightChildIn =
635 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
639 aNode = aLeftChildIdx;
641 aStack[aHead] = aRightChildIdx;
643 else if (isLeftChildIn
646 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
655 aNode = aStack[aHead];
661 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
662 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
663 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
665 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
666 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
668 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
675 aNode = aStack[aHead];
684 //==================================================
685 // Function: ClearPicked
687 //==================================================
688 void SelectMgr_ViewerSelector::ClearPicked()
693 //==================================================
696 //==================================================
697 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
699 const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
700 const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
704 //=======================================================================
707 //=======================================================================
708 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
710 if (theRank < 1 || theRank > NbPicked())
712 return Handle(SelectMgr_EntityOwner)();
715 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
716 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
720 //=======================================================================
721 //function : PickedData
723 //=======================================================================
724 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
726 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
727 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
728 return mystored.FindFromIndex (anOwnerIdx);
731 //===================================================
733 // INTERNAL METHODS ....
735 //==================================================
737 //==================================================
738 // Function: SetEntitySetBuilder
740 //==================================================
741 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
743 myEntitySetBuilder = theBuilder;
744 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
746 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
750 //==================================================
751 // Function: Contains
753 //==================================================
754 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
756 return mySelectableObjects.Contains (theObject);
759 //==================================================
760 // Function: ActiveModes
761 // Purpose : return all the modes with a given state for an object
762 //==================================================
763 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
764 TColStd_ListOfInteger& theModeList,
765 const SelectMgr_StateOfSelection theWantedState) const
767 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
768 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
770 if (theWantedState == SelectMgr_SOS_Any)
772 theModeList.Append (aSelIter.Value()->Mode());
774 else if (theWantedState == aSelIter.Value()->GetSelectionState())
776 theModeList.Append (aSelIter.Value()->Mode());
780 return hasActivatedStates;
783 //==================================================
784 // Function: IsActive
786 //==================================================
787 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
788 const Standard_Integer theMode) const
790 if (!Contains (theSelectableObject))
791 return Standard_False;
793 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
794 return !aSel.IsNull()
795 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
798 //==================================================
799 // Function: IsInside
801 //==================================================
802 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
803 const Standard_Integer theMode) const
805 if (!Contains (theSelectableObject))
806 return Standard_False;
808 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
809 return !aSel.IsNull()
810 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
814 //=======================================================================
817 //=======================================================================
819 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
821 return theSelection->GetSelectionState();
824 //==================================================
826 // Purpose : gives Information about selectors
827 //==================================================
829 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
831 TCollection_AsciiString aStatus ("Status Object :\n\t");
832 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
834 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
836 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
837 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
841 if (!Contains (theSelectableObject))
843 aStatus = aStatus + "Not Present in the selector\n\n";
849 //=======================================================================
850 //function : SortResult
851 //purpose : there is a certain number of entities ranged by criteria
852 // (depth, size, priority, mouse distance from borders or
853 // CDG of the detected primitive. Parsing :
854 // maximum priorities .
855 // then a reasonable compromise between depth and distance...
856 // finally the ranges are stored in myindexes depending on the parsing.
857 // so, it is possible to only read
858 //=======================================================================
859 void SelectMgr_ViewerSelector::SortResult()
861 if(mystored.IsEmpty()) return;
863 const Standard_Integer anExtent = mystored.Extent();
864 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
865 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
867 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
868 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
870 anIndexArray.SetValue (anIndexIter, anIndexIter);
872 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
875 //=======================================================================
876 // function : AddSelectableObject
877 // purpose : Adds new object to the map of selectable objects
878 //=======================================================================
879 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
881 if (!myMapOfObjectSensitives.IsBound (theObject))
883 mySelectableObjects.Append (theObject);
884 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
885 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
889 //=======================================================================
890 // function : AddSelectionToObject
891 // purpose : Adds new selection to the object and builds its BVH tree
892 //=======================================================================
893 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
894 const Handle(SelectMgr_Selection)& theSelection)
896 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
898 (*anEntitySet)->Append (theSelection);
899 (*anEntitySet)->BVH();
903 AddSelectableObject (theObject);
904 AddSelectionToObject (theObject, theSelection);
908 //=======================================================================
909 // function : MoveSelectableObject
911 //=======================================================================
912 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
914 mySelectableObjects.ChangeSubset (theObject);
917 //=======================================================================
918 // function : RemoveSelectableObject
919 // purpose : Removes selectable object from map of selectable ones
920 //=======================================================================
921 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
923 Handle(SelectMgr_SelectableObject) anObj = theObject;
924 if (myMapOfObjectSensitives.UnBind (theObject))
926 mySelectableObjects.Remove (theObject);
930 //=======================================================================
931 // function : RemoveSelectionOfObject
932 // purpose : Removes selection of the object and marks its BVH tree
934 //=======================================================================
935 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
936 const Handle(SelectMgr_Selection)& theSelection)
938 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
940 (*anEntitySet)->Remove (theSelection);
944 //=======================================================================
945 // function : RebuildObjectsTree
946 // purpose : Marks BVH of selectable objects for rebuild
947 //=======================================================================
948 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
950 mySelectableObjects.MarkDirty();
954 Standard_Integer aViewportWidth, aViewportHeight;
955 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
957 Standard_Integer aWidth;
958 Standard_Integer aHeight;
959 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
960 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
961 mySelectingVolumeMgr.ProjectionMatrix(),
962 mySelectingVolumeMgr.WorldViewMatrix(),
963 mySelectingVolumeMgr.WorldViewProjState(),
968 //=======================================================================
969 // function : RebuildSensitivesTree
970 // purpose : Marks BVH of sensitive entities of particular selectable
971 // object for rebuild
972 //=======================================================================
973 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
974 const Standard_Boolean theIsForce)
976 if (!Contains (theObject))
979 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
980 anEntitySet->MarkDirty();
988 //=======================================================================
989 // function : resetSelectionActivationStatus
990 // purpose : Marks all added sensitive entities of all objects as
992 //=======================================================================
993 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
995 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
997 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
998 const Standard_Integer anEntitiesNb = anEntitySet->Size();
999 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1001 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1006 //=======================================================================
1007 // function : DetectedEntity
1008 // purpose : Returns sensitive entity that was detected during the
1009 // previous run of selection algorithm
1010 //=======================================================================
1011 const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
1013 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
1014 return mystored.FindFromIndex (aRankInMap).Entity;
1017 //=======================================================================
1018 // function : ActiveOwners
1019 // purpose : Returns the list of active entity owners
1020 //=======================================================================
1021 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1023 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1025 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1026 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1027 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1029 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1030 if (aSensitive->IsActiveForSelection())
1032 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1038 //=======================================================================
1039 //function : AllowOverlapDetection
1040 //purpose : Sets the detection type: if theIsToAllow is false,
1041 // only fully included sensitives will be detected, otherwise
1042 // the algorithm will mark both included and overlapped entities
1044 //=======================================================================
1045 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1047 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);