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 bool theToPreferClosest)
47 : myMapOfCriterion (&theMapOfCriterion),
48 myToPreferClosest (theToPreferClosest) {}
50 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
52 const SelectMgr_SortCriterion& anElemLeft = myMapOfCriterion->FindFromIndex (theLeft);
53 const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
54 if (myToPreferClosest)
56 return anElemLeft.IsCloserDepth (anElemRight);
60 return anElemLeft.IsHigherPriority (anElemRight);
65 const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
66 bool myToPreferClosest;
69 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
72 //=======================================================================
73 // function : updatePoint3d
75 //=======================================================================
76 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
77 const SelectBasics_PickResult& thePickResult,
78 const Handle(Select3D_SensitiveEntity)& theEntity,
79 const gp_GTrsf& theInversedTrsf,
80 const SelectMgr_SelectingVolumeManager& theMgr) const
82 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
87 bool hasNormal = false;
88 if (thePickResult.HasPickedPoint())
90 theCriterion.Point = thePickResult.PickedPoint();
91 theCriterion.Normal = thePickResult.SurfaceNormal();
92 const float aNormLen2 = theCriterion.Normal.SquareModulus();
93 if (aNormLen2 > ShortRealEpsilon())
96 theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
99 else if (!thePickResult.IsValid())
101 theCriterion.Point = thePickResult.PickedPoint();
106 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
109 gp_GTrsf anInvTrsf = theInversedTrsf;
110 if (theCriterion.Entity->HasInitLocation())
112 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
114 if (anInvTrsf.Form() != gp_Identity)
116 const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
117 anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
120 Graphic3d_Mat4d aMat4;
121 anInvInvTrsd.GetMat4 (aMat4);
122 const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
123 theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
127 const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
128 switch (myDepthTolType)
130 case SelectMgr_TypeOfDepthTolerance_Uniform:
132 theCriterion.Tolerance = myDepthTolerance;
135 case SelectMgr_TypeOfDepthTolerance_UniformPixels:
136 case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
138 if (mySelectingVolumeMgr.Camera().IsNull())
140 // fallback for an arbitrary projection matrix
141 theCriterion.Tolerance = aSensFactor / 33.0;
143 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
145 theCriterion.Tolerance = myCameraScale * aSensFactor;
149 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
150 theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
157 //==================================================
158 // Function: Initialize
160 //==================================================
161 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
162 : myDepthTolerance (0.0),
163 myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
164 myToPreferClosest (Standard_True),
165 myToUpdateTolerance (Standard_True),
167 myToPrebuildBVH (Standard_False),
169 myIsLeftChildQueuedFirst (Standard_False)
171 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
174 //=======================================================================
175 // Function: SetPixelTolerance
177 //=======================================================================
178 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
180 if (myTolerances.Tolerance() == theTolerance)
185 myToUpdateTolerance = Standard_True;
186 if (theTolerance < 0)
188 myTolerances.ResetDefaults();
192 myTolerances.SetCustomTolerance (theTolerance);
196 //==================================================
197 // Function: Activate
199 //==================================================
200 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
202 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
204 aSelEntIter.Value()->SetActiveForSelection();
207 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
209 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
211 myTolerances.Add (theSelection->Sensitivity());
212 myToUpdateTolerance = Standard_True;
216 //==================================================
217 // Function: Deactivate
219 //==================================================
220 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
222 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
224 aSelEntIter.Value()->ResetSelectionActiveStatus();
227 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
229 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
231 myTolerances.Decrement (theSelection->Sensitivity());
232 myToUpdateTolerance = Standard_True;
236 //==================================================
239 //==================================================
240 void SelectMgr_ViewerSelector::Clear()
245 //=======================================================================
246 // function: isToScaleFrustum
247 // purpose : Checks if the entity given requires to scale current selecting frustum
248 //=======================================================================
249 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
251 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
252 && sensitivity (theEntity) < myTolerances.Tolerance();
255 //=======================================================================
256 // function: sensitivity
257 // purpose : In case if custom tolerance is set, this method will return sum of entity
258 // sensitivity and custom tolerance.
259 //=======================================================================
260 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
262 return myTolerances.IsCustomTolSet() ?
263 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
266 //=======================================================================
267 // function: checkOverlap
268 // purpose : Internal function that checks if a particular sensitive
269 // entity theEntity overlaps current selecting volume precisely
270 //=======================================================================
271 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
272 const gp_GTrsf& theInversedTrsf,
273 SelectMgr_SelectingVolumeManager& theMgr)
275 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
276 Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
277 SelectBasics_PickResult aPickResult;
278 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
285 SelectMgr_SortCriterion aCriterion;
286 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
287 aCriterion.Entity = theEntity;
288 aCriterion.Priority = anOwner->Priority();
289 aCriterion.Depth = aPickResult.Depth();
290 aCriterion.MinDist = aPickResult.DistToGeomCenter();
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.IsCloserDepth (*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
316 //=======================================================================
317 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
318 const SelectMgr_SelectingVolumeManager& theMgrGlobal,
319 const SelectMgr_SelectingVolumeManager& theMgrObject,
320 const gp_GTrsf& theInvTrsf,
321 SelectMgr_FrustumCache& theCachedMgrs,
322 SelectMgr_SelectingVolumeManager& theResMgr)
324 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
325 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
326 const Standard_Boolean toScale = aScale != 1;
327 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
328 if (toScale && toTransform)
330 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
331 theResMgr.SetViewClipping (theMgrObject);
335 if (!theCachedMgrs.Find (aScale, theResMgr))
337 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
338 theCachedMgrs.Bind (aScale, theResMgr);
340 theResMgr.SetViewClipping (theMgrObject);
342 else if (toTransform)
344 theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
345 theResMgr.SetViewClipping (theMgrObject);
349 theResMgr = theMgrObject;
353 //=======================================================================
354 // function: traverseObject
355 // purpose : Internal function that checks if there is possible overlap
356 // between some entity of selectable object theObject and
357 // current selecting volume
358 //=======================================================================
359 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
360 const SelectMgr_SelectingVolumeManager& theMgr,
361 const Handle(Graphic3d_Camera)& theCamera,
362 const Graphic3d_Mat4d& theProjectionMat,
363 const Graphic3d_Mat4d& theWorldViewMat,
364 const Standard_Integer theViewportWidth,
365 const Standard_Integer theViewportHeight)
367 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
368 if (anEntitySet->Size() == 0)
373 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
374 gp_GTrsf aInversedTrsf;
375 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
377 if (theObject->TransformPersistence().IsNull())
379 aInversedTrsf = theObject->InversedTransformation();
384 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
386 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
387 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
388 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
389 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
390 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
391 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
392 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
393 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
394 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
395 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
397 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
401 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
402 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
404 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
405 aSensitivesTree->MaxPoint (0)))
410 if (!theObject->ClipPlanes().IsNull()
411 && theObject->ClipPlanes()->ToOverrideGlobal())
413 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
415 else if (!theObject->TransformPersistence().IsNull())
417 if (theObject->TransformPersistence()->IsZoomOrRotate()
418 && !theMgr.ViewClipping().IsNull())
420 // Zoom/rotate persistence object lives in two worlds at the same time.
421 // Global clipping planes can not be trivially applied without being converted
422 // into local space of transformation persistence object.
423 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
424 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
425 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
427 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
433 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
434 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
441 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
443 else if (!theObject->ClipPlanes().IsNull()
444 && !theObject->ClipPlanes()->IsEmpty())
446 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
449 if (!theMgr.ViewClipping().IsNull() &&
450 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
452 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
453 // If box selection is active, and the whole sensitive tree is out of the clip planes
454 // selection is empty for this object
455 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
457 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
459 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
465 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
466 if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
473 const Standard_Integer aFirstStored = mystored.Extent() + 1;
475 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
476 Standard_Integer aHead = -1;
477 Standard_Integer aNode = 0; // a root node
478 SelectMgr_FrustumCache aScaledTrnsfFrustums;
479 SelectMgr_SelectingVolumeManager aTmpMgr (false);
482 if (!aSensitivesTree->IsOuter (aNode))
484 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
485 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
486 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
487 aSensitivesTree->MaxPoint (aLeftChildIdx));
488 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
489 aSensitivesTree->MaxPoint (aRightChildIdx));
493 aNode = aLeftChildIdx;
495 aStack[aHead] = aRightChildIdx;
497 else if (isLeftChildIn
500 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
509 aNode = aStack[aHead];
515 bool aClipped = false;
516 if (!theMgr.ViewClipping().IsNull() &&
517 theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
519 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
520 // If box selection is active, and the whole sensitive tree is out of the clip planes
521 // selection is empty for this object
522 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
524 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
526 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
531 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
532 if (aState == Graphic3d_ClipState_Out)
537 if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
539 if (aPlane->ProbeBoxTouch (aBBox))
548 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
549 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
550 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
552 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
553 if (aSensitive->IsActiveForSelection())
555 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
556 computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
557 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
566 aNode = aStack[aHead];
571 // in case of Box/Polyline selection - keep only Owners having all Entities detected
572 if (mySelectingVolumeMgr.IsOverlapAllowed()
573 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
574 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
579 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
581 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
582 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
583 Standard_Integer aNbOwnerEntities = 0;
584 anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
585 if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
587 mystored.RemoveFromIndex (aStoredIter);
592 //=======================================================================
593 // function: TraverseSensitives
594 // purpose : Traverses BVH containing all added selectable objects and
595 // finds candidates for further search of overlap
596 //=======================================================================
597 void SelectMgr_ViewerSelector::TraverseSensitives()
599 SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
603 Standard_Integer aWidth;
604 Standard_Integer aHeight;
605 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
606 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
607 mySelectingVolumeMgr.ProjectionMatrix(),
608 mySelectingVolumeMgr.WorldViewMatrix(),
609 mySelectingVolumeMgr.WorldViewProjState(),
611 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
612 if (!aCamera.IsNull())
614 myCameraEye = aCamera->Eye().XYZ();
615 myCameraDir = aCamera->Direction().XYZ();
616 myCameraScale = aCamera->IsOrthographic()
618 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
619 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
620 myCameraScale *= aPixelSize;
623 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
625 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
626 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
628 if (mySelectableObjects.IsEmpty (aBVHSubset))
635 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
637 // for 2D space selection transform selecting volumes to perform overap testing
638 // directly in camera's eye space omitting the camera position, which is not
639 // needed there at all
640 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
642 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
643 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
644 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
645 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
646 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
647 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
648 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
649 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
650 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
651 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
652 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
654 // define corresponding frustum builder parameters
655 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
656 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
657 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
658 aBuilder->SetWindowSize (aWidth, aHeight);
659 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
663 aMgr = mySelectingVolumeMgr;
666 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
667 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
668 ? mySelectingVolumeMgr.WorldViewMatrix()
669 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
671 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
673 Standard_Integer aNode = 0;
674 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
679 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
680 Standard_Integer aHead = -1;
683 if (!aBVHTree->IsOuter (aNode))
685 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
686 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
687 const Standard_Boolean isLeftChildIn =
688 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
689 const Standard_Boolean isRightChildIn =
690 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
694 aNode = aLeftChildIdx;
696 aStack[aHead] = aRightChildIdx;
698 else if (isLeftChildIn
701 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
710 aNode = aStack[aHead];
716 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
717 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
718 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
720 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
721 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
723 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
730 aNode = aStack[aHead];
739 //==================================================
740 // Function: ClearPicked
742 //==================================================
743 void SelectMgr_ViewerSelector::ClearPicked()
748 //==================================================
751 //==================================================
752 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
754 const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
755 const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
759 //=======================================================================
762 //=======================================================================
763 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
765 if (theRank < 1 || theRank > NbPicked())
767 return Handle(SelectMgr_EntityOwner)();
770 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
771 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
775 //=======================================================================
776 //function : PickedData
778 //=======================================================================
779 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
781 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
782 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
783 return mystored.FindFromIndex (anOwnerIdx);
786 //===================================================
788 // INTERNAL METHODS ....
790 //==================================================
792 //==================================================
793 // Function: SetEntitySetBuilder
795 //==================================================
796 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
798 myEntitySetBuilder = theBuilder;
799 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
801 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
805 //==================================================
806 // Function: Contains
808 //==================================================
809 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
811 return mySelectableObjects.Contains (theObject);
814 //==================================================
815 // Function: ActiveModes
816 // Purpose : return all the modes with a given state for an object
817 //==================================================
818 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
819 TColStd_ListOfInteger& theModeList,
820 const SelectMgr_StateOfSelection theWantedState) const
822 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
823 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
825 if (theWantedState == SelectMgr_SOS_Any)
827 theModeList.Append (aSelIter.Value()->Mode());
829 else if (theWantedState == aSelIter.Value()->GetSelectionState())
831 theModeList.Append (aSelIter.Value()->Mode());
835 return hasActivatedStates;
838 //==================================================
839 // Function: IsActive
841 //==================================================
842 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
843 const Standard_Integer theMode) const
845 if (!Contains (theSelectableObject))
846 return Standard_False;
848 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
849 return !aSel.IsNull()
850 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
853 //==================================================
854 // Function: IsInside
856 //==================================================
857 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
858 const Standard_Integer theMode) const
860 if (!Contains (theSelectableObject))
861 return Standard_False;
863 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
864 return !aSel.IsNull()
865 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
869 //=======================================================================
872 //=======================================================================
874 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
876 return theSelection->GetSelectionState();
879 //==================================================
881 // Purpose : gives Information about selectors
882 //==================================================
884 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
886 TCollection_AsciiString aStatus ("Status Object :\n\t");
887 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
889 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
891 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
892 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
896 if (!Contains (theSelectableObject))
898 aStatus = aStatus + "Not Present in the selector\n\n";
904 //=======================================================================
905 //function : SortResult
907 //=======================================================================
908 void SelectMgr_ViewerSelector::SortResult()
910 if (mystored.IsEmpty())
915 const Standard_Integer anExtent = mystored.Extent();
916 if (myIndexes.IsNull() || anExtent != myIndexes->Length())
918 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
921 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
922 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
924 anIndexArray.SetValue (anIndexIter, anIndexIter);
926 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
929 //=======================================================================
930 // function : AddSelectableObject
931 // purpose : Adds new object to the map of selectable objects
932 //=======================================================================
933 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
935 if (!myMapOfObjectSensitives.IsBound (theObject))
937 mySelectableObjects.Append (theObject);
938 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
939 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
943 //=======================================================================
944 // function : AddSelectionToObject
945 // purpose : Adds new selection to the object and builds its BVH tree
946 //=======================================================================
947 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
948 const Handle(SelectMgr_Selection)& theSelection)
950 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
952 (*anEntitySet)->Append (theSelection);
953 (*anEntitySet)->BVH();
957 AddSelectableObject (theObject);
958 AddSelectionToObject (theObject, theSelection);
962 //=======================================================================
963 // function : MoveSelectableObject
965 //=======================================================================
966 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
968 mySelectableObjects.ChangeSubset (theObject);
971 //=======================================================================
972 // function : RemoveSelectableObject
973 // purpose : Removes selectable object from map of selectable ones
974 //=======================================================================
975 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
977 Handle(SelectMgr_SelectableObject) anObj = theObject;
978 if (myMapOfObjectSensitives.UnBind (theObject))
980 mySelectableObjects.Remove (theObject);
984 //=======================================================================
985 // function : RemoveSelectionOfObject
986 // purpose : Removes selection of the object and marks its BVH tree
988 //=======================================================================
989 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
990 const Handle(SelectMgr_Selection)& theSelection)
992 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
994 (*anEntitySet)->Remove (theSelection);
998 //=======================================================================
999 // function : RebuildObjectsTree
1000 // purpose : Marks BVH of selectable objects for rebuild
1001 //=======================================================================
1002 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
1004 mySelectableObjects.MarkDirty();
1008 Standard_Integer aViewportWidth, aViewportHeight;
1009 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
1011 Standard_Integer aWidth;
1012 Standard_Integer aHeight;
1013 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
1014 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
1015 mySelectingVolumeMgr.ProjectionMatrix(),
1016 mySelectingVolumeMgr.WorldViewMatrix(),
1017 mySelectingVolumeMgr.WorldViewProjState(),
1022 //=======================================================================
1023 // function : RebuildSensitivesTree
1024 // purpose : Marks BVH of sensitive entities of particular selectable
1025 // object for rebuild
1026 //=======================================================================
1027 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1028 const Standard_Boolean theIsForce)
1030 if (!Contains (theObject))
1033 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1034 anEntitySet->MarkDirty();
1042 //=======================================================================
1043 // function : resetSelectionActivationStatus
1044 // purpose : Marks all added sensitive entities of all objects as
1046 //=======================================================================
1047 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1049 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1051 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1052 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1053 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1055 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1060 //=======================================================================
1061 // function : DetectedEntity
1062 // purpose : Returns sensitive entity that was detected during the
1063 // previous run of selection algorithm
1064 //=======================================================================
1065 const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
1067 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
1068 return mystored.FindFromIndex (aRankInMap).Entity;
1071 //=======================================================================
1072 // function : ActiveOwners
1073 // purpose : Returns the list of active entity owners
1074 //=======================================================================
1075 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1077 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1079 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1080 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1081 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1083 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1084 if (aSensitive->IsActiveForSelection())
1086 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1092 //=======================================================================
1093 //function : AllowOverlapDetection
1094 //purpose : Sets the detection type: if theIsToAllow is false,
1095 // only fully included sensitives will be detected, otherwise
1096 // the algorithm will mark both included and overlapped entities
1098 //=======================================================================
1099 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1101 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1104 //=======================================================================
1105 //function : DumpJson
1107 //=======================================================================
1108 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1110 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1112 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1113 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
1114 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1116 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1117 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1119 Standard_Integer aNbOfSelectableObjects = 0;
1120 for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1122 aNbOfSelectableObjects++;
1124 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1126 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1127 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1128 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1130 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1131 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1132 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1133 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1135 if (!myIndexes.IsNull())
1136 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1138 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurRank)
1139 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1140 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1143 //=======================================================================
1144 //function : SetToPrebuildBVH
1146 //=======================================================================
1147 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1149 if (!theToPrebuild && !myBVHThreadPool.IsNull())
1151 myBVHThreadPool.Nullify();
1153 else if (theToPrebuild)
1155 myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1157 myToPrebuildBVH = theToPrebuild;
1160 //=======================================================================
1161 //function : QueueBVHBuild
1163 //=======================================================================
1164 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1166 if (myToPrebuildBVH)
1168 myBVHThreadPool->AddEntity (theEntity);
1172 //=======================================================================
1173 //function : WaitForBVHBuild
1175 //=======================================================================
1176 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1178 if (myToPrebuildBVH)
1180 myBVHThreadPool->WaitThreads();