0028987: Visualization, SelectMgr_SelectableObject - move out iterator from object
[occt.git] / src / SelectMgr / SelectMgr_ViewerSelector.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <SelectMgr_ViewerSelector.hxx>
18
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
21 #include <gp_Pnt.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <SelectBasics_EntityOwner.hxx>
25 #include <SelectBasics_SensitiveEntity.hxx>
26 #include <SelectBasics_PickResult.hxx>
27 #include <SelectMgr_EntityOwner.hxx>
28 #include <SelectMgr_SortCriterion.hxx>
29 #include <SelectMgr_SensitiveEntitySet.hxx>
30 #include <TColStd_Array1OfInteger.hxx>
31 #include <TCollection_AsciiString.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColStd_ListOfInteger.hxx>
34
35 #include <algorithm>
36
37 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
38
39 namespace {
40   // Comparison operator for sorting selection results
41   class CompareResults
42   {
43   public:
44    
45     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
46       : myMapOfCriterion (aMapOfCriterion)
47     {
48     }
49
50     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
51     {
52       return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
53     }
54
55   private:
56     void operator = (const CompareResults&);
57
58   private:
59     const SelectMgr_IndexedDataMapOfOwnerCriterion&  myMapOfCriterion;
60   };
61
62   //! Compute 3d position for detected entity.
63   inline void updatePoint3d (SelectMgr_SortCriterion& theCriterion,
64                              const gp_GTrsf& theInversedTrsf,
65                              SelectMgr_SelectingVolumeManager& theMgr)
66   {
67     if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
68     {
69       return;
70     }
71
72     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
73     gp_GTrsf anInvTrsf = theInversedTrsf;
74     if (theCriterion.Entity->HasInitLocation())
75     {
76       anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
77     }
78     if (anInvTrsf.Form() != gp_Identity)
79     {
80       anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
81     }
82   }
83
84   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
85 }
86
87 //==================================================
88 // Function: Initialize
89 // Purpose :
90 //==================================================
91 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
92 preferclosest(Standard_True),
93 myToUpdateTolerance (Standard_True),
94 myCurRank (0),
95 myIsLeftChildQueuedFirst (Standard_False),
96 myEntityIdx (0)
97 {
98   myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
99 }
100
101 //==================================================
102 // Function: Activate
103 // Purpose :
104 //==================================================
105 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
106 {
107   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
108   {
109     aSelEntIter.Value()->SetActiveForSelection();
110   }
111
112   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
113
114   myTolerances.Add (theSelection->Sensitivity());
115   myToUpdateTolerance = Standard_True;
116 }
117
118 //==================================================
119 // Function: Deactivate
120 // Purpose :
121 //==================================================
122 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
123 {
124   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
125   {
126     aSelEntIter.Value()->ResetSelectionActiveStatus();
127   }
128
129   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
130
131   myTolerances.Decrement (theSelection->Sensitivity());
132   myToUpdateTolerance = Standard_True;
133 }
134
135 //==================================================
136 // Function: Clear
137 // Purpose :
138 //==================================================
139 void SelectMgr_ViewerSelector::Clear()
140 {
141   mystored.Clear();
142 }
143
144 //=======================================================================
145 // function: isToScaleFrustum
146 // purpose : Checks if the entity given requires to scale current selecting frustum
147 //=======================================================================
148 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
149 {
150   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
151     && sensitivity (theEntity) < myTolerances.Tolerance();
152 }
153
154 //=======================================================================
155 // function: sensitivity
156 // purpose : In case if custom tolerance is set, this method will return sum of entity
157 //           sensitivity and custom tolerance.
158 //=======================================================================
159 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
160 {
161   return myTolerances.IsCustomTolSet() ?
162     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
163 }
164
165 //=======================================================================
166 // function: checkOverlap
167 // purpose : Internal function that checks if a particular sensitive
168 //           entity theEntity overlaps current selecting volume precisely
169 //=======================================================================
170 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
171                                              const gp_GTrsf& theInversedTrsf,
172                                              SelectMgr_SelectingVolumeManager& theMgr)
173 {
174   Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
175   Handle(SelectMgr_SelectableObject) aSelectable;
176   Standard_Boolean toRestoresViewClipEnabled = Standard_False;
177   if (!anOwner.IsNull())
178   {
179     aSelectable = anOwner->Selectable();
180     if (!aSelectable->ClipPlanes().IsNull()
181       && aSelectable->ClipPlanes()->ToOverrideGlobal())
182     {
183       theMgr.SetViewClippingEnabled (Standard_False);
184       toRestoresViewClipEnabled = Standard_True;
185     }
186     else if (!aSelectable->TransformPersistence().IsNull())
187     {
188       if (aSelectable->TransformPersistence()->IsZoomOrRotate()
189       && !theMgr.ViewClipping().IsNull())
190       {
191         // Zoom/rotate persistence object lives in two worlds at the same time.
192         // Global clipping planes can not be trivially applied without being converted
193         // into local space of transformation persistence object.
194         // As more simple alternative - just clip entire object by its anchor point defined in the world space.
195         const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
196
197         const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
198         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
199         {
200           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
201           if (!aPlane->IsOn())
202           {
203             continue;
204           }
205
206           const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
207           const Graphic3d_Vec4d  aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
208           if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
209           {
210             return;
211           }
212         }
213       }
214
215       theMgr.SetViewClippingEnabled (Standard_False);
216       toRestoresViewClipEnabled = Standard_True;
217     }
218   }
219
220   SelectBasics_PickResult aPickResult;
221   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
222   if (toRestoresViewClipEnabled)
223   {
224     theMgr.SetViewClippingEnabled (Standard_True);
225   }
226
227   if (!isMatched
228     || anOwner.IsNull())
229   {
230     return;
231   }
232
233   if (HasDepthClipping (anOwner)
234   &&  theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
235   {
236     Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
237                                                                   aPickResult.Depth());
238     if (isClipped)
239       return;
240   }
241
242   SelectMgr_SortCriterion aCriterion;
243   myZLayerOrderMap.Find (aSelectable->ZLayer(), aCriterion.ZLayerPosition);
244   aCriterion.Entity    = theEntity;
245   aCriterion.Priority  = anOwner->Priority();
246   aCriterion.Depth     = aPickResult.Depth();
247   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
248   aCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
249   aCriterion.ToPreferClosest = preferclosest;
250
251   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
252   {
253     ++aPrevCriterion->NbOwnerMatches;
254     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
255     if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
256     {
257       if (aCriterion > *aPrevCriterion)
258       {
259         updatePoint3d (aCriterion, theInversedTrsf, theMgr);
260         *aPrevCriterion = aCriterion;
261       }
262     }
263   }
264   else
265   {
266     aCriterion.NbOwnerMatches = 1;
267     updatePoint3d (aCriterion, theInversedTrsf, theMgr);
268     mystored.Add (anOwner, aCriterion);
269   }
270 }
271
272 //=======================================================================
273 // function: computeFrustum
274 // purpose : Internal function that checks if a current selecting frustum
275 //           needs to be scaled and transformed for the entity and performs
276 //           necessary calculations
277 //=======================================================================
278 void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
279                                                const SelectMgr_SelectingVolumeManager&     theMgr,
280                                                const gp_GTrsf&                             theInvTrsf,
281                                                SelectMgr_FrustumCache&                     theCachedMgrs,
282                                                SelectMgr_SelectingVolumeManager&           theResMgr)
283 {
284   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
285   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
286   const Standard_Boolean toScale = aScale != 1;
287   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
288   if (toScale && toTransform)
289   {
290     theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
291   }
292   else if (toScale)
293   {
294     if (!theCachedMgrs.IsBound (aScale))
295     {
296       theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
297     }
298     theResMgr = theCachedMgrs.Find (aScale);
299   }
300   else if (toTransform)
301   {
302     theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
303   }
304 }
305
306 //=======================================================================
307 // function: traverseObject
308 // purpose : Internal function that checks if there is possible overlap
309 //           between some entity of selectable object theObject and
310 //           current selecting volume
311 //=======================================================================
312 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
313                                                const SelectMgr_SelectingVolumeManager& theMgr,
314                                                const Handle(Graphic3d_Camera)& theCamera,
315                                                const Graphic3d_Mat4d& theProjectionMat,
316                                                const Graphic3d_Mat4d& theWorldViewMat,
317                                                const Standard_Integer theViewportWidth,
318                                                const Standard_Integer theViewportHeight)
319 {
320   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
321   if (anEntitySet->Size() == 0)
322   {
323     return;
324   }
325
326   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
327   gp_GTrsf aInversedTrsf;
328   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
329   {
330     if (theObject->TransformPersistence().IsNull())
331     {
332       aInversedTrsf = theObject->InversedTransformation();
333     }
334     else
335     {
336       gp_GTrsf aTPers;
337       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
338
339       aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
340       aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
341       aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
342       aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
343       aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
344       aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
345       aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
346       aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
347       aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
348       aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
349
350       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
351     }
352   }
353
354   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
355                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
356                                         : theMgr;
357
358   SelectMgr_FrustumCache aScaledTrnsfFrustums;
359
360   Standard_Integer aNode = 0; // a root node
361   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
362                       aSensitivesTree->MaxPoint (0)))
363   {
364     return;
365   }
366
367   const Standard_Integer aFirstStored = mystored.Extent() + 1;
368
369   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
370   Standard_Integer aHead = -1;
371   for (;;)
372   {
373     if (!aSensitivesTree->IsOuter (aNode))
374     {
375       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
376       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
377       const Standard_Boolean isLeftChildIn  =  aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
378                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
379       const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
380                                                              aSensitivesTree->MaxPoint (aRightChildIdx));
381       if (isLeftChildIn
382           && isRightChildIn)
383       {
384         aNode = aLeftChildIdx;
385         ++aHead;
386         aStack[aHead] = aRightChildIdx;
387       }
388       else if (isLeftChildIn
389         || isRightChildIn)
390       {
391         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
392       }
393       else
394       {
395         if (aHead < 0)
396         {
397           break;
398         }
399
400         aNode = aStack[aHead];
401         --aHead;
402       }
403     }
404     else
405     {
406       Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
407       Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
408       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
409       {
410         const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
411         if (aSensitive->IsActiveForSelection())
412         {
413           const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
414           SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
415           computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
416           checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
417         }
418       }
419       if (aHead < 0)
420       {
421         break;
422       }
423
424       aNode = aStack[aHead];
425       --aHead;
426     }
427   }
428
429   // in case of Box/Polyline selection - keep only Owners having all Entities detected
430   if (mySelectingVolumeMgr.IsOverlapAllowed()
431   || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
432    && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
433   {
434     return;
435   }
436
437   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
438   {
439     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
440     const Handle(SelectBasics_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
441     Standard_Integer aNbOwnerEntities = 0;
442     for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
443     {
444       if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
445       {
446         if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
447         {
448           // Remove from index map.
449           // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
450           // Hence, just keep iterating in backward direction.
451           mystored.RemoveFromIndex (aStoredIter);
452           break;
453         }
454       }
455     }
456   }
457 }
458
459 //=======================================================================
460 // function: TraverseSensitives
461 // purpose : Traverses BVH containing all added selectable objects and
462 //           finds candidates for further search of overlap
463 //=======================================================================
464 void SelectMgr_ViewerSelector::TraverseSensitives()
465 {
466   mystored.Clear();
467
468   Standard_Integer aWidth;
469   Standard_Integer aHeight;
470   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
471   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
472                                  mySelectingVolumeMgr.ProjectionMatrix(),
473                                  mySelectingVolumeMgr.WorldViewMatrix(),
474                                  mySelectingVolumeMgr.WorldViewProjState(),
475                                  aWidth, aHeight);
476
477   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
478   {
479     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
480       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
481
482     if (mySelectableObjects.IsEmpty (aBVHSubset))
483     {
484       continue;
485     }
486
487     gp_GTrsf aTFrustum;
488
489     SelectMgr_SelectingVolumeManager aMgr (Standard_False);
490
491     // for 2D space selection transform selecting volumes to perform overap testing
492     // directly in camera's eye space omitting the camera position, which is not
493     // needed there at all
494     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
495     {
496       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
497       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
498       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
499       aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
500       aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
501       aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
502       aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
503       aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
504       aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
505       aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
506       aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
507
508       // define corresponding frustum builder parameters
509       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
510       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
511       aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
512       aBuilder->SetWindowSize (aWidth, aHeight);
513       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
514     }
515     else
516     {
517       aMgr = mySelectingVolumeMgr;
518     }
519
520     const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
521     const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
522     const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
523                                             ? mySelectingVolumeMgr.WorldViewMatrix()
524                                             : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
525
526     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
527
528     Standard_Integer aNode = 0;
529     if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
530     {
531       continue;
532     }
533
534     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
535     Standard_Integer aHead = -1;
536     for (;;)
537     {
538       if (!aBVHTree->IsOuter (aNode))
539       {
540         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
541         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
542         const Standard_Boolean isLeftChildIn  =
543           aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
544         const Standard_Boolean isRightChildIn =
545           aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
546         if (isLeftChildIn
547           && isRightChildIn)
548         {
549           aNode = aLeftChildIdx;
550           ++aHead;
551           aStack[aHead] = aRightChildIdx;
552         }
553         else if (isLeftChildIn
554           || isRightChildIn)
555         {
556           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
557         }
558         else
559         {
560           if (aHead < 0)
561           {
562             break;
563           }
564
565           aNode = aStack[aHead];
566           --aHead;
567         }
568       }
569       else
570       {
571         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
572         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
573         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
574         {
575           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
576             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
577
578           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
579         }
580         if (aHead < 0)
581         {
582           break;
583         }
584
585         aNode = aStack[aHead];
586         --aHead;
587       }
588     }
589   }
590
591   SortResult();
592 }
593
594 //==================================================
595 // Function: Picked
596 // Purpose :
597 //==================================================
598 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
599 ::Picked() const
600 {
601   Standard_Integer RankInMap = myIndexes->Value (myCurRank);
602   const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
603   Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
604   return Ownr;
605 }
606
607 //=======================================================================
608 //function : Picked
609 //purpose  :
610 //=======================================================================
611 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
612 {
613   Handle(SelectMgr_EntityOwner) anOwner;
614   if (theRank < 1 || theRank > NbPicked())
615   {
616     return anOwner;
617   }
618
619   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
620   const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
621   anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
622   return anOwner;
623 }
624
625 //=======================================================================
626 //function : PickedData
627 //purpose  :
628 //=======================================================================
629 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
630 {
631   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
632   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
633   return mystored.FindFromIndex (anOwnerIdx);
634 }
635
636 //===================================================
637 //
638 //       INTERNAL METHODS ....
639 //
640 //==================================================
641
642 //==================================================
643 // Function: SetEntitySetBuilder
644 // Purpose :
645 //==================================================
646 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
647 {
648   myEntitySetBuilder = theBuilder;
649   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
650   {
651     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
652   }
653 }
654
655 //==================================================
656 // Function: Contains
657 // Purpose :
658 //==================================================
659 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
660 {
661   return mySelectableObjects.Contains (theObject);
662 }
663
664 //==================================================
665 // Function: ActiveModes
666 // Purpose : return all the  modes with a given state for an object
667 //==================================================
668 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
669                                                   TColStd_ListOfInteger& theModeList,
670                                                   const SelectMgr_StateOfSelection theWantedState) const
671 {
672   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
673   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
674   {
675       if (theWantedState == SelectMgr_SOS_Any)
676       {
677         theModeList.Append (aSelIter.Value()->Mode());
678       }
679       else if (theWantedState == aSelIter.Value()->GetSelectionState())
680       {
681         theModeList.Append (aSelIter.Value()->Mode());
682       }
683   }
684
685   return hasActivatedStates;
686 }
687
688 //==================================================
689 // Function: IsActive
690 // Purpose :
691 //==================================================
692 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
693                                                      const Standard_Integer theMode) const
694 {
695   if (!Contains (theSelectableObject))
696     return Standard_False;
697
698   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
699   return !aSel.IsNull()
700        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
701 }
702
703 //==================================================
704 // Function: IsInside
705 // Purpose :
706 //==================================================
707 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
708                                                      const Standard_Integer theMode) const
709 {
710   if (!Contains (theSelectableObject))
711     return Standard_False;
712
713   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
714   return !aSel.IsNull()
715        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
716 }
717
718
719 //=======================================================================
720 //function : Status
721 //purpose  :
722 //=======================================================================
723
724 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
725 {
726   return theSelection->GetSelectionState();
727 }
728
729 //==================================================
730 // Function: Status
731 // Purpose : gives Information about selectors
732 //==================================================
733
734 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
735 {
736   TCollection_AsciiString aStatus ("Status Object :\n\t");
737   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
738   {
739     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
740     {
741       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
742               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
743     }
744   }
745
746   if (!Contains (theSelectableObject))
747   {
748     aStatus = aStatus + "Not Present in the selector\n\n";
749   }
750
751   return aStatus;
752 }
753
754 //=======================================================================
755 //function : SortResult
756 //purpose  :  there is a certain number of entities ranged by criteria
757 //            (depth, size, priority, mouse distance from borders or
758 //            CDG of the detected primitive. Parsing :
759 //             maximum priorities .
760 //             then a reasonable compromise between depth and distance...
761 // finally the ranges are stored in myindexes depending on the parsing.
762 // so, it is possible to only read
763 //=======================================================================
764 void SelectMgr_ViewerSelector::SortResult()
765 {
766   if(mystored.IsEmpty()) return;
767
768   const Standard_Integer anExtent = mystored.Extent();
769   if(myIndexes.IsNull() || anExtent != myIndexes->Length())
770     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
771
772   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
773   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
774   {
775     anIndexArray.SetValue (anIndexIter, anIndexIter);
776   }
777   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
778 }
779
780 //=======================================================================
781 //function : HasDepthClipping
782 //purpose  : Stub
783 //=======================================================================
784 Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
785 {
786   return Standard_False;
787 }
788
789 //=======================================================================
790 // function : AddSelectableObject
791 // purpose  : Adds new object to the map of selectable objects
792 //=======================================================================
793 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
794 {
795   if (!myMapOfObjectSensitives.IsBound (theObject))
796   {
797     mySelectableObjects.Append (theObject);
798     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
799     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
800   }
801 }
802
803 //=======================================================================
804 // function : AddSelectionToObject
805 // purpose  : Adds new selection to the object and builds its BVH tree
806 //=======================================================================
807 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
808                                                      const Handle(SelectMgr_Selection)& theSelection)
809 {
810   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
811   {
812     (*anEntitySet)->Append (theSelection);
813     (*anEntitySet)->BVH();
814   }
815   else
816   {
817     AddSelectableObject (theObject);
818     AddSelectionToObject (theObject, theSelection);
819   }
820 }
821
822 //=======================================================================
823 // function : MoveSelectableObject
824 // purpose  :
825 //=======================================================================
826 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
827 {
828   mySelectableObjects.ChangeSubset (theObject);
829 }
830
831 //=======================================================================
832 // function : RemoveSelectableObject
833 // purpose  : Removes selectable object from map of selectable ones
834 //=======================================================================
835 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
836 {
837   Handle(SelectMgr_SelectableObject) anObj = theObject;
838   if (myMapOfObjectSensitives.UnBind (theObject))
839   {
840     mySelectableObjects.Remove (theObject);
841   }
842 }
843
844 //=======================================================================
845 // function : RemoveSelectionOfObject
846 // purpose  : Removes selection of the object and marks its BVH tree
847 //            for rebuild
848 //=======================================================================
849 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
850                                                         const Handle(SelectMgr_Selection)& theSelection)
851 {
852   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
853   {
854     (*anEntitySet)->Remove (theSelection);
855   }
856 }
857
858 //=======================================================================
859 // function : RebuildObjectsTree
860 // purpose  : Marks BVH of selectable objects for rebuild
861 //=======================================================================
862 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
863 {
864   mySelectableObjects.MarkDirty();
865
866   if (theIsForce)
867   {
868     Standard_Integer aViewportWidth, aViewportHeight;
869     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
870
871     Standard_Integer aWidth;
872     Standard_Integer aHeight;
873     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
874     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
875                                    mySelectingVolumeMgr.ProjectionMatrix(),
876                                    mySelectingVolumeMgr.WorldViewMatrix(),
877                                    mySelectingVolumeMgr.WorldViewProjState(),
878                                    aWidth, aHeight);
879   }
880 }
881
882 //=======================================================================
883 // function : RebuildSensitivesTree
884 // purpose  : Marks BVH of sensitive entities of particular selectable
885 //            object for rebuild
886 //=======================================================================
887 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
888                                                       const Standard_Boolean theIsForce)
889 {
890   if (!Contains (theObject))
891     return;
892
893   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
894   anEntitySet->MarkDirty();
895
896   if (theIsForce)
897   {
898     anEntitySet->BVH();
899   }
900 }
901
902 //=======================================================================
903 // function : resetSelectionActivationStatus
904 // purpose  : Marks all added sensitive entities of all objects as
905 //            non-selectable
906 //=======================================================================
907 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
908 {
909   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
910   {
911     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
912     const Standard_Integer anEntitiesNb = anEntitySet->Size();
913     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
914     {
915       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
916     }
917   }
918 }
919
920 //=======================================================================
921 // function : DetectedEntity
922 // purpose  : Returns sensitive entity that was detected during the
923 //            previous run of selection algorithm
924 //=======================================================================
925 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
926 {
927   const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
928   return mystored.FindFromIndex (aRankInMap).Entity;
929 }
930
931 //=======================================================================
932 // function : ActiveOwners
933 // purpose  : Returns the list of active entity owners
934 //=======================================================================
935 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
936 {
937   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
938   {
939     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
940     const Standard_Integer anEntitiesNb = anEntitySet->Size();
941     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
942     {
943       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
944       if (aSensitive->IsActiveForSelection())
945       {
946         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
947       }
948     }
949   }
950 }
951
952 //=======================================================================
953 //function : AllowOverlapDetection
954 //purpose  : Sets the detection type: if theIsToAllow is false,
955 //           only fully included sensitives will be detected, otherwise
956 //           the algorithm will mark both included and overlapped entities
957 //           as matched
958 //=======================================================================
959 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
960 {
961   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
962 }