0031987: Visualization - Slow rectangular selection on models with big number of...
[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 <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>
33
34 #include <algorithm>
35
36 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
37
38 namespace
39 {
40   //! Comparison operator for sorting selection results
41   class CompareResults
42   {
43   public:
44
45     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
46                     bool theToPreferClosest)
47     : myMapOfCriterion (&theMapOfCriterion),
48       myToPreferClosest (theToPreferClosest) {}
49
50     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
51     {
52       const SelectMgr_SortCriterion& anElemLeft  = myMapOfCriterion->FindFromIndex (theLeft);
53       const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
54       if (myToPreferClosest)
55       {
56         return anElemLeft.IsCloserDepth (anElemRight);
57       }
58       else
59       {
60         return anElemLeft.IsHigherPriority (anElemRight);
61       }
62     }
63
64   private:
65     const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
66     bool myToPreferClosest;
67   };
68
69   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
70 }
71
72 //=======================================================================
73 // function : updatePoint3d
74 // purpose  :
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
81 {
82   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
83   {
84     return;
85   }
86
87   bool hasNormal = false;
88   if (thePickResult.HasPickedPoint())
89   {
90     theCriterion.Point  = thePickResult.PickedPoint();
91     theCriterion.Normal = thePickResult.SurfaceNormal();
92     const float aNormLen2 = theCriterion.Normal.SquareModulus();
93     if (aNormLen2 > ShortRealEpsilon())
94     {
95       hasNormal = true;
96       theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
97     }
98   }
99   else if (!thePickResult.IsValid())
100   {
101     theCriterion.Point = thePickResult.PickedPoint();
102     return;
103   }
104   else
105   {
106     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
107   }
108
109   gp_GTrsf anInvTrsf = theInversedTrsf;
110   if (theCriterion.Entity->HasInitLocation())
111   {
112     anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
113   }
114   if (anInvTrsf.Form() != gp_Identity)
115   {
116     const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
117     anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
118     if (hasNormal)
119     {
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());
124     }
125   }
126
127   const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
128   switch (myDepthTolType)
129   {
130     case SelectMgr_TypeOfDepthTolerance_Uniform:
131     {
132       theCriterion.Tolerance = myDepthTolerance;
133       break;
134     }
135     case SelectMgr_TypeOfDepthTolerance_UniformPixels:
136     case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
137     {
138       if (mySelectingVolumeMgr.Camera().IsNull())
139       {
140         // fallback for an arbitrary projection matrix
141         theCriterion.Tolerance = aSensFactor / 33.0;
142       }
143       else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
144       {
145         theCriterion.Tolerance = myCameraScale * aSensFactor;
146       }
147       else
148       {
149         const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
150         theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
151       }
152       break;
153     }
154   }
155 }
156
157 //==================================================
158 // Function: Initialize
159 // Purpose :
160 //==================================================
161 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
162 : myDepthTolerance (0.0),
163   myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
164   myToPreferClosest (Standard_True),
165   myToUpdateTolerance (Standard_True),
166   myCameraScale (1.0),
167   myToPrebuildBVH (Standard_False),
168   myCurRank (0),
169   myIsLeftChildQueuedFirst (Standard_False)
170 {
171   myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
172 }
173
174 //=======================================================================
175 // Function: SetPixelTolerance
176 // Purpose :
177 //=======================================================================
178 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
179 {
180   if (myTolerances.Tolerance() == theTolerance)
181   {
182     return;
183   }
184
185   myToUpdateTolerance = Standard_True;
186   if (theTolerance < 0)
187   {
188     myTolerances.ResetDefaults();
189   }
190   else
191   {
192     myTolerances.SetCustomTolerance (theTolerance);
193   }
194 }
195
196 //==================================================
197 // Function: Activate
198 // Purpose :
199 //==================================================
200 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
201 {
202   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
203   {
204     aSelEntIter.Value()->SetActiveForSelection();
205   }
206
207   if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
208   {
209     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
210
211     myTolerances.Add (theSelection->Sensitivity());
212     myToUpdateTolerance = Standard_True;
213   }
214 }
215
216 //==================================================
217 // Function: Deactivate
218 // Purpose :
219 //==================================================
220 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
221 {
222   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
223   {
224     aSelEntIter.Value()->ResetSelectionActiveStatus();
225   }
226
227   if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
228   {
229     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
230
231     myTolerances.Decrement (theSelection->Sensitivity());
232     myToUpdateTolerance = Standard_True;
233   }
234 }
235
236 //==================================================
237 // Function: Clear
238 // Purpose :
239 //==================================================
240 void SelectMgr_ViewerSelector::Clear()
241 {
242   mystored.Clear();
243 }
244
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)
250 {
251   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
252     && sensitivity (theEntity) < myTolerances.Tolerance();
253 }
254
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
261 {
262   return myTolerances.IsCustomTolSet() ?
263     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
264 }
265
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)
274 {
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);
279   if (!isMatched
280     || anOwner.IsNull())
281   {
282     return;
283   }
284
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();
291
292   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
293   {
294     ++aPrevCriterion->NbOwnerMatches;
295     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
296     if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
297     {
298       if (aCriterion.IsCloserDepth (*aPrevCriterion))
299       {
300         updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
301         *aPrevCriterion = aCriterion;
302       }
303     }
304   }
305   else
306   {
307     aCriterion.NbOwnerMatches = 1;
308     updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
309     mystored.Add (anOwner, aCriterion);
310   }
311 }
312
313 //=======================================================================
314 // function: computeFrustum
315 // purpose :
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)
323 {
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)
329   {
330     theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
331     theResMgr.SetViewClipping (theMgrObject);
332   }
333   else if (toScale)
334   {
335     if (!theCachedMgrs.Find (aScale, theResMgr))
336     {
337       theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
338       theCachedMgrs.Bind (aScale, theResMgr);
339     }
340     theResMgr.SetViewClipping (theMgrObject);
341   }
342   else if (toTransform)
343   {
344     theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
345     theResMgr.SetViewClipping (theMgrObject);
346   }
347   else
348   {
349     theResMgr = theMgrObject;
350   }
351 }
352
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)
366 {
367   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
368   if (anEntitySet->Size() == 0)
369   {
370     return;
371   }
372
373   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
374   gp_GTrsf aInversedTrsf;
375   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
376   {
377     if (theObject->TransformPersistence().IsNull())
378     {
379       aInversedTrsf = theObject->InversedTransformation();
380     }
381     else
382     {
383       gp_GTrsf aTPers;
384       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
385
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)));
396
397       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
398     }
399   }
400
401   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
402                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
403                                         : theMgr;
404   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
405                       aSensitivesTree->MaxPoint (0)))
406   {
407     return;
408   }
409
410   if (!theObject->ClipPlanes().IsNull()
411     && theObject->ClipPlanes()->ToOverrideGlobal())
412   {
413     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
414   }
415   else if (!theObject->TransformPersistence().IsNull())
416   {
417     if (theObject->TransformPersistence()->IsZoomOrRotate()
418     && !theMgr.ViewClipping().IsNull())
419     {
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())
426       {
427         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
428         if (!aPlane->IsOn())
429         {
430           continue;
431         }
432
433         const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
434         if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
435         {
436           return;
437         }
438       }
439     }
440
441     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
442   }
443   else if (!theObject->ClipPlanes().IsNull()
444         && !theObject->ClipPlanes()->IsEmpty())
445   {
446     aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
447   }
448
449   if (!theMgr.ViewClipping().IsNull() &&
450       theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
451   {
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();
456
457     for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
458     {
459       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
460       if (!aPlane->IsOn())
461       {
462         continue;
463       }
464
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
467       {
468         return;
469       }
470     }
471   }
472
473   const Standard_Integer aFirstStored = mystored.Extent() + 1;
474
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);
480   for (;;)
481   {
482     if (!aSensitivesTree->IsOuter (aNode))
483     {
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));
490       if (isLeftChildIn
491           && isRightChildIn)
492       {
493         aNode = aLeftChildIdx;
494         ++aHead;
495         aStack[aHead] = aRightChildIdx;
496       }
497       else if (isLeftChildIn
498         || isRightChildIn)
499       {
500         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
501       }
502       else
503       {
504         if (aHead < 0)
505         {
506           break;
507         }
508
509         aNode = aStack[aHead];
510         --aHead;
511       }
512     }
513     else
514     {
515       bool aClipped = false;
516       if (!theMgr.ViewClipping().IsNull() &&
517           theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
518       {
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();
523
524         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
525         {
526           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
527           if (!aPlane->IsOn())
528           {
529             continue;
530           }
531           Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
532           if (aState == Graphic3d_ClipState_Out)
533           {
534             aClipped = true;
535             break;
536           }
537           if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
538           {
539             if (aPlane->ProbeBoxTouch (aBBox))
540               continue;
541             aClipped = true;
542             break;
543           }
544         }
545       }
546       if (!aClipped)
547       {
548         Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
549         Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
550         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
551         {
552           const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
553           if (aSensitive->IsActiveForSelection())
554           {
555             const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
556             computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
557             checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
558           }
559         }
560       }
561       if (aHead < 0)
562       {
563         break;
564       }
565
566       aNode = aStack[aHead];
567       --aHead;
568     }
569   }
570
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))
575   {
576     return;
577   }
578
579   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
580   {
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)
586     {
587       mystored.RemoveFromIndex (aStoredIter);
588     }
589   }
590 }
591
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()
598 {
599   SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
600
601   mystored.Clear();
602
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(),
610                                  aWidth, aHeight);
611   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
612   if (!aCamera.IsNull())
613   {
614     myCameraEye = aCamera->Eye().XYZ();
615     myCameraDir = aCamera->Direction().XYZ();
616     myCameraScale = aCamera->IsOrthographic()
617                   ? aCamera->Scale()
618                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
619     const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
620     myCameraScale *= aPixelSize;
621   }
622
623   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
624   {
625     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
626       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
627
628     if (mySelectableObjects.IsEmpty (aBVHSubset))
629     {
630       continue;
631     }
632
633     gp_GTrsf aTFrustum;
634
635     SelectMgr_SelectingVolumeManager aMgr (Standard_False);
636
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)
641     {
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)));
653
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);
660     }
661     else
662     {
663       aMgr = mySelectingVolumeMgr;
664     }
665
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;
670
671     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
672
673     Standard_Integer aNode = 0;
674     if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
675     {
676       continue;
677     }
678
679     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
680     Standard_Integer aHead = -1;
681     for (;;)
682     {
683       if (!aBVHTree->IsOuter (aNode))
684       {
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));
691         if (isLeftChildIn
692           && isRightChildIn)
693         {
694           aNode = aLeftChildIdx;
695           ++aHead;
696           aStack[aHead] = aRightChildIdx;
697         }
698         else if (isLeftChildIn
699           || isRightChildIn)
700         {
701           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
702         }
703         else
704         {
705           if (aHead < 0)
706           {
707             break;
708           }
709
710           aNode = aStack[aHead];
711           --aHead;
712         }
713       }
714       else
715       {
716         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
717         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
718         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
719         {
720           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
721             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
722
723           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
724         }
725         if (aHead < 0)
726         {
727           break;
728         }
729
730         aNode = aStack[aHead];
731         --aHead;
732       }
733     }
734   }
735
736   SortResult();
737 }
738
739 //==================================================
740 // Function: ClearPicked
741 // Purpose :
742 //==================================================
743 void SelectMgr_ViewerSelector::ClearPicked()
744 {
745   mystored.Clear();
746 }
747
748 //==================================================
749 // Function: Picked
750 // Purpose :
751 //==================================================
752 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
753 {
754   const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
755   const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
756   return anOwner;
757 }
758
759 //=======================================================================
760 //function : Picked
761 //purpose  :
762 //=======================================================================
763 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
764 {
765   if (theRank < 1 || theRank > NbPicked())
766   {
767     return Handle(SelectMgr_EntityOwner)();
768   }
769
770   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
771   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
772   return aStoredOwner;
773 }
774
775 //=======================================================================
776 //function : PickedData
777 //purpose  :
778 //=======================================================================
779 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
780 {
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);
784 }
785
786 //===================================================
787 //
788 //       INTERNAL METHODS ....
789 //
790 //==================================================
791
792 //==================================================
793 // Function: SetEntitySetBuilder
794 // Purpose :
795 //==================================================
796 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
797 {
798   myEntitySetBuilder = theBuilder;
799   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
800   {
801     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
802   }
803 }
804
805 //==================================================
806 // Function: Contains
807 // Purpose :
808 //==================================================
809 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
810 {
811   return mySelectableObjects.Contains (theObject);
812 }
813
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
821 {
822   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
823   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
824   {
825     if (theWantedState == SelectMgr_SOS_Any)
826     {
827       theModeList.Append (aSelIter.Value()->Mode());
828     }
829     else if (theWantedState == aSelIter.Value()->GetSelectionState())
830     {
831       theModeList.Append (aSelIter.Value()->Mode());
832     }
833   }
834
835   return hasActivatedStates;
836 }
837
838 //==================================================
839 // Function: IsActive
840 // Purpose :
841 //==================================================
842 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
843                                                      const Standard_Integer theMode) const
844 {
845   if (!Contains (theSelectableObject))
846     return Standard_False;
847
848   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
849   return !aSel.IsNull()
850        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
851 }
852
853 //==================================================
854 // Function: IsInside
855 // Purpose :
856 //==================================================
857 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
858                                                      const Standard_Integer theMode) const
859 {
860   if (!Contains (theSelectableObject))
861     return Standard_False;
862
863   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
864   return !aSel.IsNull()
865        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
866 }
867
868
869 //=======================================================================
870 //function : Status
871 //purpose  :
872 //=======================================================================
873
874 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
875 {
876   return theSelection->GetSelectionState();
877 }
878
879 //==================================================
880 // Function: Status
881 // Purpose : gives Information about selectors
882 //==================================================
883
884 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
885 {
886   TCollection_AsciiString aStatus ("Status Object :\n\t");
887   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
888   {
889     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
890     {
891       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
892               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
893     }
894   }
895
896   if (!Contains (theSelectableObject))
897   {
898     aStatus = aStatus + "Not Present in the selector\n\n";
899   }
900
901   return aStatus;
902 }
903
904 //=======================================================================
905 //function : SortResult
906 //purpose  :
907 //=======================================================================
908 void SelectMgr_ViewerSelector::SortResult()
909 {
910   if (mystored.IsEmpty())
911   {
912     return;
913   }
914
915   const Standard_Integer anExtent = mystored.Extent();
916   if (myIndexes.IsNull() || anExtent != myIndexes->Length())
917   {
918     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
919   }
920
921   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
922   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
923   {
924     anIndexArray.SetValue (anIndexIter, anIndexIter);
925   }
926   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
927 }
928
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)
934 {
935   if (!myMapOfObjectSensitives.IsBound (theObject))
936   {
937     mySelectableObjects.Append (theObject);
938     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
939     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
940   }
941 }
942
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)
949 {
950   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
951   {
952     (*anEntitySet)->Append (theSelection);
953     (*anEntitySet)->BVH();
954   }
955   else
956   {
957     AddSelectableObject (theObject);
958     AddSelectionToObject (theObject, theSelection);
959   }
960 }
961
962 //=======================================================================
963 // function : MoveSelectableObject
964 // purpose  :
965 //=======================================================================
966 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
967 {
968   mySelectableObjects.ChangeSubset (theObject);
969 }
970
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)
976 {
977   Handle(SelectMgr_SelectableObject) anObj = theObject;
978   if (myMapOfObjectSensitives.UnBind (theObject))
979   {
980     mySelectableObjects.Remove (theObject);
981   }
982 }
983
984 //=======================================================================
985 // function : RemoveSelectionOfObject
986 // purpose  : Removes selection of the object and marks its BVH tree
987 //            for rebuild
988 //=======================================================================
989 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
990                                                         const Handle(SelectMgr_Selection)& theSelection)
991 {
992   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
993   {
994     (*anEntitySet)->Remove (theSelection);
995   }
996 }
997
998 //=======================================================================
999 // function : RebuildObjectsTree
1000 // purpose  : Marks BVH of selectable objects for rebuild
1001 //=======================================================================
1002 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
1003 {
1004   mySelectableObjects.MarkDirty();
1005
1006   if (theIsForce)
1007   {
1008     Standard_Integer aViewportWidth, aViewportHeight;
1009     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
1010
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(),
1018                                    aWidth, aHeight);
1019   }
1020 }
1021
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)
1029 {
1030   if (!Contains (theObject))
1031     return;
1032
1033   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1034   anEntitySet->MarkDirty();
1035
1036   if (theIsForce)
1037   {
1038     anEntitySet->BVH();
1039   }
1040 }
1041
1042 //=======================================================================
1043 // function : resetSelectionActivationStatus
1044 // purpose  : Marks all added sensitive entities of all objects as
1045 //            non-selectable
1046 //=======================================================================
1047 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1048 {
1049   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1050   {
1051     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1052     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1053     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1054     {
1055       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1056     }
1057   }
1058 }
1059
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
1066 {
1067   const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
1068   return mystored.FindFromIndex (aRankInMap).Entity;
1069 }
1070
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
1076 {
1077   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1078   {
1079     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1080     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1081     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1082     {
1083       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1084       if (aSensitive->IsActiveForSelection())
1085       {
1086         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1087       }
1088     }
1089   }
1090 }
1091
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
1097 //           as matched
1098 //=======================================================================
1099 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1100 {
1101   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1102 }
1103
1104 //=======================================================================
1105 //function : DumpJson
1106 //purpose  : 
1107 //=======================================================================
1108 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const 
1109 {
1110   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1111
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())
1115
1116   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1117   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1118
1119   Standard_Integer aNbOfSelectableObjects = 0;
1120   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1121   {
1122     aNbOfSelectableObjects++;
1123   }
1124   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1125
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())
1129
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)
1134
1135   if (!myIndexes.IsNull())
1136     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1137
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())
1141 }
1142
1143 //=======================================================================
1144 //function : SetToPrebuildBVH
1145 //purpose  : 
1146 //=======================================================================
1147 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1148 {
1149   if (!theToPrebuild && !myBVHThreadPool.IsNull())
1150   {
1151     myBVHThreadPool.Nullify();
1152   }
1153   else if (theToPrebuild)
1154   {
1155     myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1156   }
1157   myToPrebuildBVH = theToPrebuild;
1158 }
1159
1160 //=======================================================================
1161 //function : QueueBVHBuild
1162 //purpose  : 
1163 //=======================================================================
1164 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1165 {
1166   if (myToPrebuildBVH)
1167   {
1168     myBVHThreadPool->AddEntity (theEntity);
1169   }
1170 }
1171
1172 //=======================================================================
1173 //function : WaitForBVHBuild
1174 //purpose  : 
1175 //=======================================================================
1176 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1177 {
1178   if (myToPrebuildBVH)
1179   {
1180     myBVHThreadPool->WaitThreads();
1181   }
1182 }