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)
40 //! Comparison operator for sorting selection results
45 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion)
46 : myMapOfCriterion (&theMapOfCriterion)
50 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
52 return myMapOfCriterion->FindFromIndex (theLeft) > myMapOfCriterion->FindFromIndex (theRight);
56 const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
59 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
62 //=======================================================================
63 // function : updatePoint3d
65 //=======================================================================
66 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
67 const SelectBasics_PickResult& thePickResult,
68 const Handle(Select3D_SensitiveEntity)& theEntity,
69 const gp_GTrsf& theInversedTrsf,
70 const SelectMgr_SelectingVolumeManager& theMgr) const
72 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
77 bool hasNormal = false;
78 if (thePickResult.HasPickedPoint())
80 theCriterion.Point = thePickResult.PickedPoint();
81 theCriterion.Normal = thePickResult.SurfaceNormal();
82 const float aNormLen2 = theCriterion.Normal.SquareModulus();
83 if (aNormLen2 > ShortRealEpsilon())
86 theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
89 else if (!thePickResult.IsValid())
91 theCriterion.Point = thePickResult.PickedPoint();
96 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
99 gp_GTrsf anInvTrsf = theInversedTrsf;
100 if (theCriterion.Entity->HasInitLocation())
102 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
104 if (anInvTrsf.Form() != gp_Identity)
106 const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
107 anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
110 Graphic3d_Mat4d aMat4;
111 anInvInvTrsd.GetMat4 (aMat4);
112 const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
113 theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
117 if (mySelectingVolumeMgr.Camera().IsNull())
119 theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
121 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
123 theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
127 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
128 theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
132 //==================================================
133 // Function: Initialize
135 //==================================================
136 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
137 preferclosest(Standard_True),
138 myToUpdateTolerance (Standard_True),
141 myIsLeftChildQueuedFirst (Standard_False),
144 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
147 //=======================================================================
148 // Function: SetPixelTolerance
150 //=======================================================================
151 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
153 if (myTolerances.Tolerance() == theTolerance)
158 myToUpdateTolerance = Standard_True;
159 if (theTolerance < 0)
161 myTolerances.ResetDefaults();
165 myTolerances.SetCustomTolerance (theTolerance);
169 //==================================================
170 // Function: Activate
172 //==================================================
173 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
175 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
177 aSelEntIter.Value()->SetActiveForSelection();
180 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
182 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
184 myTolerances.Add (theSelection->Sensitivity());
185 myToUpdateTolerance = Standard_True;
189 //==================================================
190 // Function: Deactivate
192 //==================================================
193 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
195 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
197 aSelEntIter.Value()->ResetSelectionActiveStatus();
200 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
202 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
204 myTolerances.Decrement (theSelection->Sensitivity());
205 myToUpdateTolerance = Standard_True;
209 //==================================================
212 //==================================================
213 void SelectMgr_ViewerSelector::Clear()
218 //=======================================================================
219 // function: isToScaleFrustum
220 // purpose : Checks if the entity given requires to scale current selecting frustum
221 //=======================================================================
222 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
224 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
225 && sensitivity (theEntity) < myTolerances.Tolerance();
228 //=======================================================================
229 // function: sensitivity
230 // purpose : In case if custom tolerance is set, this method will return sum of entity
231 // sensitivity and custom tolerance.
232 //=======================================================================
233 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
235 return myTolerances.IsCustomTolSet() ?
236 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
239 //=======================================================================
240 // function: checkOverlap
241 // purpose : Internal function that checks if a particular sensitive
242 // entity theEntity overlaps current selecting volume precisely
243 //=======================================================================
244 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
245 const gp_GTrsf& theInversedTrsf,
246 SelectMgr_SelectingVolumeManager& theMgr)
248 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
249 Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
250 SelectBasics_PickResult aPickResult;
251 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
258 SelectMgr_SortCriterion aCriterion;
259 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
260 aCriterion.Entity = theEntity;
261 aCriterion.Priority = anOwner->Priority();
262 aCriterion.Depth = aPickResult.Depth();
263 aCriterion.MinDist = aPickResult.DistToGeomCenter();
264 aCriterion.ToPreferClosest = preferclosest;
266 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
268 ++aPrevCriterion->NbOwnerMatches;
269 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
270 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
272 if (aCriterion > *aPrevCriterion)
274 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
275 *aPrevCriterion = aCriterion;
281 aCriterion.NbOwnerMatches = 1;
282 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
283 mystored.Add (anOwner, aCriterion);
287 //=======================================================================
288 // function: computeFrustum
290 //=======================================================================
291 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
292 const SelectMgr_SelectingVolumeManager& theMgrGlobal,
293 const SelectMgr_SelectingVolumeManager& theMgrObject,
294 const gp_GTrsf& theInvTrsf,
295 SelectMgr_FrustumCache& theCachedMgrs,
296 SelectMgr_SelectingVolumeManager& theResMgr)
298 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
299 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
300 const Standard_Boolean toScale = aScale != 1;
301 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
302 if (toScale && toTransform)
304 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
305 theResMgr.SetViewClipping (theMgrObject);
309 if (!theCachedMgrs.Find (aScale, theResMgr))
311 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
312 theCachedMgrs.Bind (aScale, theResMgr);
314 theResMgr.SetViewClipping (theMgrObject);
316 else if (toTransform)
318 theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
319 theResMgr.SetViewClipping (theMgrObject);
323 theResMgr = theMgrObject;
327 //=======================================================================
328 // function: traverseObject
329 // purpose : Internal function that checks if there is possible overlap
330 // between some entity of selectable object theObject and
331 // current selecting volume
332 //=======================================================================
333 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
334 const SelectMgr_SelectingVolumeManager& theMgr,
335 const Handle(Graphic3d_Camera)& theCamera,
336 const Graphic3d_Mat4d& theProjectionMat,
337 const Graphic3d_Mat4d& theWorldViewMat,
338 const Standard_Integer theViewportWidth,
339 const Standard_Integer theViewportHeight)
341 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
342 if (anEntitySet->Size() == 0)
347 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
348 gp_GTrsf aInversedTrsf;
349 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
351 if (theObject->TransformPersistence().IsNull())
353 aInversedTrsf = theObject->InversedTransformation();
358 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
360 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
361 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
362 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
363 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
364 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
365 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
366 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
367 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
368 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
369 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
371 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
375 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
376 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
378 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
379 aSensitivesTree->MaxPoint (0)))
384 if (!theObject->ClipPlanes().IsNull()
385 && theObject->ClipPlanes()->ToOverrideGlobal())
387 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
389 else if (!theObject->TransformPersistence().IsNull())
391 if (theObject->TransformPersistence()->IsZoomOrRotate()
392 && !theMgr.ViewClipping().IsNull())
394 // Zoom/rotate persistence object lives in two worlds at the same time.
395 // Global clipping planes can not be trivially applied without being converted
396 // into local space of transformation persistence object.
397 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
398 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
399 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
401 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
407 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
408 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
415 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
417 else if (!theObject->ClipPlanes().IsNull()
418 && !theObject->ClipPlanes()->IsEmpty())
420 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
423 if (!theMgr.ViewClipping().IsNull() &&
424 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
426 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
427 // If box selection is active, and the whole sensitive tree is out of the clip planes
428 // selection is empty for this object
429 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
431 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
433 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
439 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
440 if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
447 const Standard_Integer aFirstStored = mystored.Extent() + 1;
449 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
450 Standard_Integer aHead = -1;
451 Standard_Integer aNode = 0; // a root node
452 SelectMgr_FrustumCache aScaledTrnsfFrustums;
453 SelectMgr_SelectingVolumeManager aTmpMgr (false);
456 if (!aSensitivesTree->IsOuter (aNode))
458 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
459 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
460 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
461 aSensitivesTree->MaxPoint (aLeftChildIdx));
462 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
463 aSensitivesTree->MaxPoint (aRightChildIdx));
467 aNode = aLeftChildIdx;
469 aStack[aHead] = aRightChildIdx;
471 else if (isLeftChildIn
474 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
483 aNode = aStack[aHead];
489 bool aClipped = false;
490 if (!theMgr.ViewClipping().IsNull() &&
491 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
493 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
494 // If box selection is active, and the whole sensitive tree is out of the clip planes
495 // selection is empty for this object
496 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
498 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
500 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
505 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
506 if (aState == Graphic3d_ClipState_Out)
511 if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
513 if (aPlane->ProbeBoxTouch (aBBox))
522 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
523 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
524 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
526 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
527 if (aSensitive->IsActiveForSelection())
529 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
530 computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
531 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
540 aNode = aStack[aHead];
545 // in case of Box/Polyline selection - keep only Owners having all Entities detected
546 if (mySelectingVolumeMgr.IsOverlapAllowed()
547 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
548 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
553 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
555 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
556 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
557 Standard_Integer aNbOwnerEntities = 0;
558 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
560 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
562 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
564 // Remove from index map.
565 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
566 // Hence, just keep iterating in backward direction.
567 mystored.RemoveFromIndex (aStoredIter);
575 //=======================================================================
576 // function: TraverseSensitives
577 // purpose : Traverses BVH containing all added selectable objects and
578 // finds candidates for further search of overlap
579 //=======================================================================
580 void SelectMgr_ViewerSelector::TraverseSensitives()
584 Standard_Integer aWidth;
585 Standard_Integer aHeight;
586 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
587 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
588 mySelectingVolumeMgr.ProjectionMatrix(),
589 mySelectingVolumeMgr.WorldViewMatrix(),
590 mySelectingVolumeMgr.WorldViewProjState(),
592 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
593 if (!aCamera.IsNull())
595 myCameraEye = aCamera->Eye().XYZ();
596 myCameraDir = aCamera->Direction().XYZ();
597 myCameraScale = aCamera->IsOrthographic()
599 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
600 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
601 myCameraScale *= aPixelSize;
604 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
606 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
607 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
609 if (mySelectableObjects.IsEmpty (aBVHSubset))
616 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
618 // for 2D space selection transform selecting volumes to perform overap testing
619 // directly in camera's eye space omitting the camera position, which is not
620 // needed there at all
621 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
623 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
624 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
625 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
626 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
627 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
628 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
629 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
630 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
631 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
632 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
633 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
635 // define corresponding frustum builder parameters
636 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
637 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
638 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
639 aBuilder->SetWindowSize (aWidth, aHeight);
640 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
644 aMgr = mySelectingVolumeMgr;
647 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
648 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
649 ? mySelectingVolumeMgr.WorldViewMatrix()
650 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
652 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
654 Standard_Integer aNode = 0;
655 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
660 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
661 Standard_Integer aHead = -1;
664 if (!aBVHTree->IsOuter (aNode))
666 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
667 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
668 const Standard_Boolean isLeftChildIn =
669 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
670 const Standard_Boolean isRightChildIn =
671 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
675 aNode = aLeftChildIdx;
677 aStack[aHead] = aRightChildIdx;
679 else if (isLeftChildIn
682 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
691 aNode = aStack[aHead];
697 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
698 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
699 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
701 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
702 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
704 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
711 aNode = aStack[aHead];
720 //==================================================
721 // Function: ClearPicked
723 //==================================================
724 void SelectMgr_ViewerSelector::ClearPicked()
729 //==================================================
732 //==================================================
733 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
735 const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
736 const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
740 //=======================================================================
743 //=======================================================================
744 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
746 if (theRank < 1 || theRank > NbPicked())
748 return Handle(SelectMgr_EntityOwner)();
751 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
752 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
756 //=======================================================================
757 //function : PickedData
759 //=======================================================================
760 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
762 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
763 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
764 return mystored.FindFromIndex (anOwnerIdx);
767 //===================================================
769 // INTERNAL METHODS ....
771 //==================================================
773 //==================================================
774 // Function: SetEntitySetBuilder
776 //==================================================
777 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
779 myEntitySetBuilder = theBuilder;
780 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
782 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
786 //==================================================
787 // Function: Contains
789 //==================================================
790 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
792 return mySelectableObjects.Contains (theObject);
795 //==================================================
796 // Function: ActiveModes
797 // Purpose : return all the modes with a given state for an object
798 //==================================================
799 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
800 TColStd_ListOfInteger& theModeList,
801 const SelectMgr_StateOfSelection theWantedState) const
803 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
804 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
806 if (theWantedState == SelectMgr_SOS_Any)
808 theModeList.Append (aSelIter.Value()->Mode());
810 else if (theWantedState == aSelIter.Value()->GetSelectionState())
812 theModeList.Append (aSelIter.Value()->Mode());
816 return hasActivatedStates;
819 //==================================================
820 // Function: IsActive
822 //==================================================
823 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
824 const Standard_Integer theMode) const
826 if (!Contains (theSelectableObject))
827 return Standard_False;
829 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
830 return !aSel.IsNull()
831 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
834 //==================================================
835 // Function: IsInside
837 //==================================================
838 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
839 const Standard_Integer theMode) const
841 if (!Contains (theSelectableObject))
842 return Standard_False;
844 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
845 return !aSel.IsNull()
846 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
850 //=======================================================================
853 //=======================================================================
855 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
857 return theSelection->GetSelectionState();
860 //==================================================
862 // Purpose : gives Information about selectors
863 //==================================================
865 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
867 TCollection_AsciiString aStatus ("Status Object :\n\t");
868 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
870 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
872 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
873 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
877 if (!Contains (theSelectableObject))
879 aStatus = aStatus + "Not Present in the selector\n\n";
885 //=======================================================================
886 //function : SortResult
887 //purpose : there is a certain number of entities ranged by criteria
888 // (depth, size, priority, mouse distance from borders or
889 // CDG of the detected primitive. Parsing :
890 // maximum priorities .
891 // then a reasonable compromise between depth and distance...
892 // finally the ranges are stored in myindexes depending on the parsing.
893 // so, it is possible to only read
894 //=======================================================================
895 void SelectMgr_ViewerSelector::SortResult()
897 if(mystored.IsEmpty()) return;
899 const Standard_Integer anExtent = mystored.Extent();
900 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
901 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
903 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
904 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
906 anIndexArray.SetValue (anIndexIter, anIndexIter);
908 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
911 //=======================================================================
912 // function : AddSelectableObject
913 // purpose : Adds new object to the map of selectable objects
914 //=======================================================================
915 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
917 if (!myMapOfObjectSensitives.IsBound (theObject))
919 mySelectableObjects.Append (theObject);
920 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
921 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
925 //=======================================================================
926 // function : AddSelectionToObject
927 // purpose : Adds new selection to the object and builds its BVH tree
928 //=======================================================================
929 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
930 const Handle(SelectMgr_Selection)& theSelection)
932 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
934 (*anEntitySet)->Append (theSelection);
935 (*anEntitySet)->BVH();
939 AddSelectableObject (theObject);
940 AddSelectionToObject (theObject, theSelection);
944 //=======================================================================
945 // function : MoveSelectableObject
947 //=======================================================================
948 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
950 mySelectableObjects.ChangeSubset (theObject);
953 //=======================================================================
954 // function : RemoveSelectableObject
955 // purpose : Removes selectable object from map of selectable ones
956 //=======================================================================
957 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
959 Handle(SelectMgr_SelectableObject) anObj = theObject;
960 if (myMapOfObjectSensitives.UnBind (theObject))
962 mySelectableObjects.Remove (theObject);
966 //=======================================================================
967 // function : RemoveSelectionOfObject
968 // purpose : Removes selection of the object and marks its BVH tree
970 //=======================================================================
971 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
972 const Handle(SelectMgr_Selection)& theSelection)
974 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
976 (*anEntitySet)->Remove (theSelection);
980 //=======================================================================
981 // function : RebuildObjectsTree
982 // purpose : Marks BVH of selectable objects for rebuild
983 //=======================================================================
984 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
986 mySelectableObjects.MarkDirty();
990 Standard_Integer aViewportWidth, aViewportHeight;
991 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
993 Standard_Integer aWidth;
994 Standard_Integer aHeight;
995 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
996 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
997 mySelectingVolumeMgr.ProjectionMatrix(),
998 mySelectingVolumeMgr.WorldViewMatrix(),
999 mySelectingVolumeMgr.WorldViewProjState(),
1004 //=======================================================================
1005 // function : RebuildSensitivesTree
1006 // purpose : Marks BVH of sensitive entities of particular selectable
1007 // object for rebuild
1008 //=======================================================================
1009 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1010 const Standard_Boolean theIsForce)
1012 if (!Contains (theObject))
1015 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1016 anEntitySet->MarkDirty();
1024 //=======================================================================
1025 // function : resetSelectionActivationStatus
1026 // purpose : Marks all added sensitive entities of all objects as
1028 //=======================================================================
1029 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1031 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1033 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1034 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1035 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1037 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1042 //=======================================================================
1043 // function : DetectedEntity
1044 // purpose : Returns sensitive entity that was detected during the
1045 // previous run of selection algorithm
1046 //=======================================================================
1047 const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
1049 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
1050 return mystored.FindFromIndex (aRankInMap).Entity;
1053 //=======================================================================
1054 // function : ActiveOwners
1055 // purpose : Returns the list of active entity owners
1056 //=======================================================================
1057 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1059 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1061 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1062 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1063 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1065 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1066 if (aSensitive->IsActiveForSelection())
1068 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1074 //=======================================================================
1075 //function : AllowOverlapDetection
1076 //purpose : Sets the detection type: if theIsToAllow is false,
1077 // only fully included sensitives will be detected, otherwise
1078 // the algorithm will mark both included and overlapped entities
1080 //=======================================================================
1081 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1083 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1086 //=======================================================================
1087 //function : DumpJson
1089 //=======================================================================
1090 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1092 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1094 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, preferclosest)
1095 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
1096 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1098 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectingVolumeMgr)
1099 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1101 Standard_Integer aNbOfSelectableObjects = 0;
1102 for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1104 aNbOfSelectableObjects++;
1106 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1108 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1109 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1110 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1112 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1113 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1114 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1115 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1117 if (!myIndexes.IsNull())
1118 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1120 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurRank)
1121 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1122 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myEntityIdx)
1123 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())