4d4cdab5409774fe0db3e66315159fd36e343c09
[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_FrustumBuilder.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 {
41   //! Comparison operator for sorting selection results
42   class CompareResults
43   {
44   public:
45
46     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
47                     bool theToPreferClosest)
48     : myMapOfCriterion (&theMapOfCriterion),
49       myToPreferClosest (theToPreferClosest) {}
50
51     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
52     {
53       const SelectMgr_SortCriterion& anElemLeft  = myMapOfCriterion->FindFromIndex (theLeft);
54       const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
55       if (myToPreferClosest)
56       {
57         return anElemLeft.IsCloserDepth (anElemRight);
58       }
59       else
60       {
61         return anElemLeft.IsHigherPriority (anElemRight);
62       }
63     }
64
65   private:
66     const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
67     bool myToPreferClosest;
68   };
69
70   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
71 }
72
73 //=======================================================================
74 // function : updatePoint3d
75 // purpose  :
76 //=======================================================================
77 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
78                                               const SelectBasics_PickResult& thePickResult,
79                                               const Handle(Select3D_SensitiveEntity)& theEntity,
80                                               const gp_GTrsf& theInversedTrsf,
81                                               const SelectMgr_SelectingVolumeManager& theMgr) const
82 {
83   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
84   {
85     return;
86   }
87
88   bool hasNormal = false;
89   if (thePickResult.HasPickedPoint())
90   {
91     theCriterion.Point  = thePickResult.PickedPoint();
92     theCriterion.Normal = thePickResult.SurfaceNormal();
93     const float aNormLen2 = theCriterion.Normal.SquareModulus();
94     if (aNormLen2 > ShortRealEpsilon())
95     {
96       hasNormal = true;
97       theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
98     }
99   }
100   else if (!thePickResult.IsValid())
101   {
102     theCriterion.Point = thePickResult.PickedPoint();
103     return;
104   }
105   else
106   {
107     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
108   }
109
110   gp_GTrsf anInvTrsf = theInversedTrsf;
111   if (theCriterion.Entity->HasInitLocation())
112   {
113     anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
114   }
115   if (anInvTrsf.Form() != gp_Identity)
116   {
117     const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
118     anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
119     if (hasNormal)
120     {
121       Graphic3d_Mat4d aMat4;
122       anInvInvTrsd.GetMat4 (aMat4);
123       const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
124       theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
125     }
126   }
127
128   const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
129   switch (myDepthTolType)
130   {
131     case SelectMgr_TypeOfDepthTolerance_Uniform:
132     {
133       theCriterion.Tolerance = myDepthTolerance;
134       break;
135     }
136     case SelectMgr_TypeOfDepthTolerance_UniformPixels:
137     case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
138     {
139       if (mySelectingVolumeMgr.Camera().IsNull())
140       {
141         // fallback for an arbitrary projection matrix
142         theCriterion.Tolerance = aSensFactor / 33.0;
143       }
144       else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
145       {
146         theCriterion.Tolerance = myCameraScale * aSensFactor;
147       }
148       else
149       {
150         const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
151         theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
152       }
153       break;
154     }
155   }
156 }
157
158 //==================================================
159 // Function: Initialize
160 // Purpose :
161 //==================================================
162 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
163 : myDepthTolerance (0.0),
164   myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
165   myToPreferClosest (Standard_True),
166   myCameraScale (1.0),
167   myToPrebuildBVH (Standard_False),
168   myIsLeftChildQueuedFirst (Standard_False)
169 {
170   myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
171 }
172
173 //=======================================================================
174 // Function: SetPixelTolerance
175 // Purpose :
176 //=======================================================================
177 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
178 {
179   if (myTolerances.Tolerance() == theTolerance)
180   {
181     return;
182   }
183   if (theTolerance < 0)
184   {
185     myTolerances.ResetDefaults();
186   }
187   else
188   {
189     myTolerances.SetCustomTolerance (theTolerance);
190   }
191 }
192
193 //==================================================
194 // Function: Activate
195 // Purpose :
196 //==================================================
197 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
198 {
199   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
200   {
201     aSelEntIter.Value()->SetActiveForSelection();
202   }
203
204   if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
205   {
206     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
207
208     myTolerances.Add (theSelection->Sensitivity());
209   }
210 }
211
212 //==================================================
213 // Function: Deactivate
214 // Purpose :
215 //==================================================
216 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
217 {
218   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
219   {
220     aSelEntIter.Value()->ResetSelectionActiveStatus();
221   }
222
223   if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
224   {
225     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
226
227     myTolerances.Decrement (theSelection->Sensitivity());
228   }
229 }
230
231 //==================================================
232 // Function: Clear
233 // Purpose :
234 //==================================================
235 void SelectMgr_ViewerSelector::Clear()
236 {
237   mystored.Clear();
238 }
239
240 //=======================================================================
241 // function: isToScaleFrustum
242 // purpose : Checks if the entity given requires to scale current selecting frustum
243 //=======================================================================
244 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
245 {
246   return mySelectingVolumeMgr.IsScalableActiveVolume()
247     && sensitivity (theEntity) < myTolerances.Tolerance();
248 }
249
250 //=======================================================================
251 // function: sensitivity
252 // purpose : In case if custom tolerance is set, this method will return sum of entity
253 //           sensitivity and custom tolerance.
254 //=======================================================================
255 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
256 {
257   return myTolerances.IsCustomTolSet() ?
258     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
259 }
260
261 //=======================================================================
262 // function: checkOverlap
263 // purpose : Internal function that checks if a particular sensitive
264 //           entity theEntity overlaps current selecting volume precisely
265 //=======================================================================
266 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
267                                              const gp_GTrsf& theInversedTrsf,
268                                              SelectMgr_SelectingVolumeManager& theMgr)
269 {
270   const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
271   Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
272   SelectBasics_PickResult aPickResult;
273   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
274   if (!isMatched
275     || anOwner.IsNull())
276   {
277     return;
278   }
279
280   SelectMgr_SortCriterion aCriterion;
281   myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
282   aCriterion.Entity    = theEntity;
283   aCriterion.Priority  = anOwner->Priority();
284   aCriterion.Depth     = aPickResult.Depth();
285   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
286
287   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
288   {
289     ++aPrevCriterion->NbOwnerMatches;
290     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
291     if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
292     {
293       if (aCriterion.IsCloserDepth (*aPrevCriterion))
294       {
295         updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
296         *aPrevCriterion = aCriterion;
297       }
298     }
299   }
300   else
301   {
302     aCriterion.NbOwnerMatches = 1;
303     updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
304     mystored.Add (anOwner, aCriterion);
305   }
306 }
307
308 //=======================================================================
309 // function: computeFrustum
310 // purpose :
311 //=======================================================================
312 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
313                                                const SelectMgr_SelectingVolumeManager& theMgrGlobal,
314                                                const SelectMgr_SelectingVolumeManager& theMgrObject,
315                                                const gp_GTrsf& theInvTrsf,
316                                                SelectMgr_FrustumCache& theCachedMgrs,
317                                                SelectMgr_SelectingVolumeManager& theResMgr)
318 {
319   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
320   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
321   const Standard_Boolean toScale = aScale != 1;
322   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
323   if (toScale && toTransform)
324   {
325     theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
326     theResMgr.SetViewClipping (theMgrObject);
327   }
328   else if (toScale)
329   {
330     if (!theCachedMgrs.Find (aScale, theResMgr))
331     {
332       theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
333       theCachedMgrs.Bind (aScale, theResMgr);
334     }
335     theResMgr.SetViewClipping (theMgrObject);
336   }
337   else if (toTransform)
338   {
339     theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
340     theResMgr.SetViewClipping (theMgrObject);
341   }
342   else
343   {
344     theResMgr = theMgrObject;
345   }
346 }
347
348 //=======================================================================
349 // function: traverseObject
350 // purpose : Internal function that checks if there is possible overlap
351 //           between some entity of selectable object theObject and
352 //           current selecting volume
353 //=======================================================================
354 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
355                                                const SelectMgr_SelectingVolumeManager& theMgr,
356                                                const Handle(Graphic3d_Camera)& theCamera,
357                                                const Graphic3d_Mat4d& theProjectionMat,
358                                                const Graphic3d_Mat4d& theWorldViewMat,
359                                                const Standard_Integer theViewportWidth,
360                                                const Standard_Integer theViewportHeight)
361 {
362   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
363   if (anEntitySet->Size() == 0)
364   {
365     return;
366   }
367
368   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
369   gp_GTrsf aInversedTrsf;
370   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
371   {
372     if (theObject->TransformPersistence().IsNull())
373     {
374       aInversedTrsf = theObject->InversedTransformation();
375     }
376     else
377     {
378       if (theCamera.IsNull())
379       {
380         return;
381       }
382       gp_GTrsf aTPers;
383       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
384
385       aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
386       aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
387       aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
388       aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
389       aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
390       aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
391       aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
392       aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
393       aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
394       aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
395
396       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
397     }
398   }
399
400   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
401                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
402                                         : theMgr;
403   if (!aMgr.OverlapsBox (aSensitivesTree->MinPoint (0),
404                          aSensitivesTree->MaxPoint (0)))
405   {
406     return;
407   }
408
409   if (!theObject->ClipPlanes().IsNull()
410     && theObject->ClipPlanes()->ToOverrideGlobal())
411   {
412     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
413   }
414   else if (!theObject->TransformPersistence().IsNull())
415   {
416     if (theObject->TransformPersistence()->IsZoomOrRotate()
417     && !theMgr.ViewClipping().IsNull())
418     {
419       // Zoom/rotate persistence object lives in two worlds at the same time.
420       // Global clipping planes can not be trivially applied without being converted
421       // into local space of transformation persistence object.
422       // As more simple alternative - just clip entire object by its anchor point defined in the world space.
423       const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
424       for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
425       {
426         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
427         if (!aPlane->IsOn())
428         {
429           continue;
430         }
431
432         const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
433         if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
434         {
435           return;
436         }
437       }
438     }
439
440     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
441   }
442   else if (!theObject->ClipPlanes().IsNull()
443         && !theObject->ClipPlanes()->IsEmpty())
444   {
445     aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
446   }
447
448   if (!theMgr.ViewClipping().IsNull() &&
449       theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
450   {
451     Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
452     // If box selection is active, and the whole sensitive tree is out of the clip planes
453     // selection is empty for this object
454     const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
455
456     for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
457     {
458       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
459       if (!aPlane->IsOn())
460       {
461         continue;
462       }
463
464       Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
465       if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
466       {
467         return;
468       }
469     }
470   }
471
472   const Standard_Integer aFirstStored = mystored.Extent() + 1;
473
474   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
475   Standard_Integer aHead = -1;
476   Standard_Integer aNode = 0; // a root node
477   SelectMgr_FrustumCache aScaledTrnsfFrustums;
478   SelectMgr_SelectingVolumeManager aTmpMgr;
479   for (;;)
480   {
481     if (!aSensitivesTree->IsOuter (aNode))
482     {
483       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
484       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
485       const Standard_Boolean isLeftChildIn  =  aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx),
486                                                                  aSensitivesTree->MaxPoint (aLeftChildIdx));
487       const Standard_Boolean isRightChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx),
488                                                                 aSensitivesTree->MaxPoint (aRightChildIdx));
489       if (isLeftChildIn
490           && isRightChildIn)
491       {
492         aNode = aLeftChildIdx;
493         ++aHead;
494         aStack[aHead] = aRightChildIdx;
495       }
496       else if (isLeftChildIn
497         || isRightChildIn)
498       {
499         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
500       }
501       else
502       {
503         if (aHead < 0)
504         {
505           break;
506         }
507
508         aNode = aStack[aHead];
509         --aHead;
510       }
511     }
512     else
513     {
514       bool aClipped = false;
515       if (!theMgr.ViewClipping().IsNull() &&
516           theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
517       {
518         Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
519         // If box selection is active, and the whole sensitive tree is out of the clip planes
520         // selection is empty for this object
521         const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
522
523         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
524         {
525           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
526           if (!aPlane->IsOn())
527           {
528             continue;
529           }
530           Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
531           if (aState == Graphic3d_ClipState_Out)
532           {
533             aClipped = true;
534             break;
535           }
536           if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
537           {
538             if (aPlane->ProbeBoxTouch (aBBox))
539               continue;
540             aClipped = true;
541             break;
542           }
543         }
544       }
545       if (!aClipped)
546       {
547         Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
548         Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
549         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
550         {
551           const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
552           if (aSensitive->IsActiveForSelection())
553           {
554             const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
555             computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
556             checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
557           }
558         }
559       }
560       if (aHead < 0)
561       {
562         break;
563       }
564
565       aNode = aStack[aHead];
566       --aHead;
567     }
568   }
569
570   // in case of Box/Polyline selection - keep only Owners having all Entities detected
571   if (mySelectingVolumeMgr.IsOverlapAllowed()
572   || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
573    && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
574   {
575     return;
576   }
577
578   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
579   {
580     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
581     const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
582     Standard_Integer aNbOwnerEntities = 0;
583     anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
584     if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
585     {
586       mystored.RemoveFromIndex (aStoredIter);
587     }
588   }
589 }
590
591 //=======================================================================
592 // function: TraverseSensitives
593 // purpose : Traverses BVH containing all added selectable objects and
594 //           finds candidates for further search of overlap
595 //=======================================================================
596 void SelectMgr_ViewerSelector::TraverseSensitives()
597 {
598   SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
599
600   mystored.Clear();
601
602   Standard_Integer aWidth = 0;
603   Standard_Integer aHeight = 0;
604   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
605
606   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
607   Graphic3d_Mat4d aProjectionMat, aWorldViewMat;
608   Graphic3d_WorldViewProjState aViewState;
609   if (!aCamera.IsNull())
610   {
611     aProjectionMat = aCamera->ProjectionMatrix();
612     aWorldViewMat = aCamera->OrientationMatrix();
613     aViewState = aCamera->WorldViewProjState();
614
615     myCameraEye = aCamera->Eye().XYZ();
616     myCameraDir = aCamera->Direction().XYZ();
617     myCameraScale = aCamera->IsOrthographic()
618                   ? aCamera->Scale()
619                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
620     const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
621     myCameraScale *= aPixelSize;
622   }
623   mySelectableObjects.UpdateBVH (aCamera, aProjectionMat, aWorldViewMat, aViewState, aWidth, aHeight);
624
625   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
626   {
627     const SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = (SelectMgr_SelectableObjectSet::BVHSubset )aBVHSetIt;
628     if (mySelectableObjects.IsEmpty (aBVHSubset))
629     {
630       continue;
631     }
632     if (aCamera.IsNull()
633      && aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_3d)
634     {
635       continue;
636     }
637
638     SelectMgr_SelectingVolumeManager aMgr;
639
640     // for 2D space selection transform selecting volumes to perform overlap testing
641     // directly in camera's eye space omitting the camera position, which is not
642     // needed there at all
643     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
644     {
645       gp_GTrsf aTFrustum;
646       aTFrustum.SetValue (1, 1, aWorldViewMat.GetValue (0, 0));
647       aTFrustum.SetValue (1, 2, aWorldViewMat.GetValue (0, 1));
648       aTFrustum.SetValue (1, 3, aWorldViewMat.GetValue (0, 2));
649       aTFrustum.SetValue (2, 1, aWorldViewMat.GetValue (1, 0));
650       aTFrustum.SetValue (2, 2, aWorldViewMat.GetValue (1, 1));
651       aTFrustum.SetValue (2, 3, aWorldViewMat.GetValue (1, 2));
652       aTFrustum.SetValue (3, 1, aWorldViewMat.GetValue (2, 0));
653       aTFrustum.SetValue (3, 2, aWorldViewMat.GetValue (2, 1));
654       aTFrustum.SetValue (3, 3, aWorldViewMat.GetValue (2, 2));
655       aTFrustum.SetTranslationPart (gp_XYZ (aWorldViewMat.GetValue (0, 3),
656                                             aWorldViewMat.GetValue (1, 3),
657                                             aWorldViewMat.GetValue (2, 3)));
658
659       // define corresponding frustum builder parameters
660       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
661       Handle(Graphic3d_Camera) aNewCamera = new Graphic3d_Camera();
662       aNewCamera->CopyMappingData (aCamera);
663       aNewCamera->SetIdentityOrientation();
664       aWorldViewMat = aNewCamera->OrientationMatrix(); // should be identity matrix
665       aProjectionMat = aNewCamera->ProjectionMatrix(); // should be the same to aProjectionMat
666       aBuilder->SetCamera (aNewCamera);
667       aBuilder->SetWindowSize (aWidth, aHeight);
668       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
669     }
670     else
671     {
672       aMgr = mySelectingVolumeMgr;
673     }
674
675     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
676
677     Standard_Integer aNode = 0;
678     if (!aMgr.OverlapsBox (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
679     {
680       continue;
681     }
682
683     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
684     Standard_Integer aHead = -1;
685     for (;;)
686     {
687       if (!aBVHTree->IsOuter (aNode))
688       {
689         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
690         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
691         const Standard_Boolean isLeftChildIn  =
692           aMgr.OverlapsBox (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
693         const Standard_Boolean isRightChildIn =
694           aMgr.OverlapsBox (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
695         if (isLeftChildIn
696           && isRightChildIn)
697         {
698           aNode = aLeftChildIdx;
699           ++aHead;
700           aStack[aHead] = aRightChildIdx;
701         }
702         else if (isLeftChildIn
703           || isRightChildIn)
704         {
705           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
706         }
707         else
708         {
709           if (aHead < 0)
710           {
711             break;
712           }
713
714           aNode = aStack[aHead];
715           --aHead;
716         }
717       }
718       else
719       {
720         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
721         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
722         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
723         {
724           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
725             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
726
727           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
728         }
729         if (aHead < 0)
730         {
731           break;
732         }
733
734         aNode = aStack[aHead];
735         --aHead;
736       }
737     }
738   }
739
740   SortResult();
741 }
742
743 //==================================================
744 // Function: ClearPicked
745 // Purpose :
746 //==================================================
747 void SelectMgr_ViewerSelector::ClearPicked()
748 {
749   mystored.Clear();
750 }
751
752 //=======================================================================
753 //function : Picked
754 //purpose  :
755 //=======================================================================
756 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
757 {
758   if (theRank < 1 || theRank > NbPicked())
759   {
760     return Handle(SelectMgr_EntityOwner)();
761   }
762
763   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
764   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
765   return aStoredOwner;
766 }
767
768 //=======================================================================
769 //function : PickedData
770 //purpose  :
771 //=======================================================================
772 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
773 {
774   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
775   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
776   return mystored.FindFromIndex (anOwnerIdx);
777 }
778
779 //===================================================
780 //
781 //       INTERNAL METHODS ....
782 //
783 //==================================================
784
785 //==================================================
786 // Function: SetEntitySetBuilder
787 // Purpose :
788 //==================================================
789 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
790 {
791   myEntitySetBuilder = theBuilder;
792   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
793   {
794     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
795   }
796 }
797
798 //==================================================
799 // Function: Contains
800 // Purpose :
801 //==================================================
802 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
803 {
804   return mySelectableObjects.Contains (theObject);
805 }
806
807 //==================================================
808 // Function: ActiveModes
809 // Purpose : return all the  modes with a given state for an object
810 //==================================================
811 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
812                                                   TColStd_ListOfInteger& theModeList,
813                                                   const SelectMgr_StateOfSelection theWantedState) const
814 {
815   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
816   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
817   {
818     if (theWantedState == SelectMgr_SOS_Any)
819     {
820       theModeList.Append (aSelIter.Value()->Mode());
821     }
822     else if (theWantedState == aSelIter.Value()->GetSelectionState())
823     {
824       theModeList.Append (aSelIter.Value()->Mode());
825     }
826   }
827
828   return hasActivatedStates;
829 }
830
831 //==================================================
832 // Function: IsActive
833 // Purpose :
834 //==================================================
835 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
836                                                      const Standard_Integer theMode) const
837 {
838   if (!Contains (theSelectableObject))
839     return Standard_False;
840
841   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
842   return !aSel.IsNull()
843        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
844 }
845
846 //==================================================
847 // Function: IsInside
848 // Purpose :
849 //==================================================
850 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
851                                                      const Standard_Integer theMode) const
852 {
853   if (!Contains (theSelectableObject))
854     return Standard_False;
855
856   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
857   return !aSel.IsNull()
858        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
859 }
860
861
862 //=======================================================================
863 //function : Status
864 //purpose  :
865 //=======================================================================
866
867 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
868 {
869   return theSelection->GetSelectionState();
870 }
871
872 //==================================================
873 // Function: Status
874 // Purpose : gives Information about selectors
875 //==================================================
876
877 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
878 {
879   TCollection_AsciiString aStatus ("Status Object :\n\t");
880   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
881   {
882     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
883     {
884       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
885               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
886     }
887   }
888
889   if (!Contains (theSelectableObject))
890   {
891     aStatus = aStatus + "Not Present in the selector\n\n";
892   }
893
894   return aStatus;
895 }
896
897 //=======================================================================
898 //function : SortResult
899 //purpose  :
900 //=======================================================================
901 void SelectMgr_ViewerSelector::SortResult()
902 {
903   if (mystored.IsEmpty())
904   {
905     return;
906   }
907
908   const Standard_Integer anExtent = mystored.Extent();
909   if (myIndexes.IsNull() || anExtent != myIndexes->Length())
910   {
911     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
912   }
913
914   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
915   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
916   {
917     anIndexArray.SetValue (anIndexIter, anIndexIter);
918   }
919   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
920 }
921
922 //=======================================================================
923 // function : AddSelectableObject
924 // purpose  : Adds new object to the map of selectable objects
925 //=======================================================================
926 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
927 {
928   if (!myMapOfObjectSensitives.IsBound (theObject))
929   {
930     mySelectableObjects.Append (theObject);
931     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
932     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
933   }
934 }
935
936 //=======================================================================
937 // function : AddSelectionToObject
938 // purpose  : Adds new selection to the object and builds its BVH tree
939 //=======================================================================
940 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
941                                                      const Handle(SelectMgr_Selection)& theSelection)
942 {
943   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
944   {
945     (*anEntitySet)->Append (theSelection);
946     (*anEntitySet)->BVH();
947   }
948   else
949   {
950     AddSelectableObject (theObject);
951     AddSelectionToObject (theObject, theSelection);
952   }
953 }
954
955 //=======================================================================
956 // function : MoveSelectableObject
957 // purpose  :
958 //=======================================================================
959 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
960 {
961   mySelectableObjects.ChangeSubset (theObject);
962 }
963
964 //=======================================================================
965 // function : RemoveSelectableObject
966 // purpose  : Removes selectable object from map of selectable ones
967 //=======================================================================
968 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
969 {
970   Handle(SelectMgr_SelectableObject) anObj = theObject;
971   if (myMapOfObjectSensitives.UnBind (theObject))
972   {
973     mySelectableObjects.Remove (theObject);
974   }
975 }
976
977 //=======================================================================
978 // function : RemoveSelectionOfObject
979 // purpose  : Removes selection of the object and marks its BVH tree
980 //            for rebuild
981 //=======================================================================
982 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
983                                                         const Handle(SelectMgr_Selection)& theSelection)
984 {
985   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
986   {
987     (*anEntitySet)->Remove (theSelection);
988   }
989 }
990
991 //=======================================================================
992 // function : RebuildObjectsTree
993 // purpose  : Marks BVH of selectable objects for rebuild
994 //=======================================================================
995 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
996 {
997   mySelectableObjects.MarkDirty();
998
999   if (theIsForce)
1000   {
1001     Standard_Integer aViewportWidth, aViewportHeight;
1002     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
1003
1004     Standard_Integer aWidth;
1005     Standard_Integer aHeight;
1006     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
1007     const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
1008     const Graphic3d_Mat4d&       aProjMat    = !aCamera.IsNull() ? aCamera->ProjectionMatrix()
1009                                                                  : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
1010     const Graphic3d_Mat4d&       anOrientMat = !aCamera.IsNull() ? aCamera->OrientationMatrix()
1011                                                                  : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
1012     Graphic3d_WorldViewProjState aViewState  = !aCamera.IsNull() ? aCamera->WorldViewProjState()
1013                                                                  : Graphic3d_WorldViewProjState();
1014     mySelectableObjects.UpdateBVH (aCamera, aProjMat, anOrientMat, aViewState, aWidth, aHeight);
1015   }
1016 }
1017
1018 //=======================================================================
1019 // function : RebuildSensitivesTree
1020 // purpose  : Marks BVH of sensitive entities of particular selectable
1021 //            object for rebuild
1022 //=======================================================================
1023 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1024                                                       const Standard_Boolean theIsForce)
1025 {
1026   if (!Contains (theObject))
1027     return;
1028
1029   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1030   anEntitySet->MarkDirty();
1031
1032   if (theIsForce)
1033   {
1034     anEntitySet->BVH();
1035   }
1036 }
1037
1038 //=======================================================================
1039 // function : resetSelectionActivationStatus
1040 // purpose  : Marks all added sensitive entities of all objects as
1041 //            non-selectable
1042 //=======================================================================
1043 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1044 {
1045   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1046   {
1047     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1048     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1049     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1050     {
1051       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1052     }
1053   }
1054 }
1055
1056 //=======================================================================
1057 // function : ActiveOwners
1058 // purpose  : Returns the list of active entity owners
1059 //=======================================================================
1060 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1061 {
1062   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1063   {
1064     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1065     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1066     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1067     {
1068       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1069       if (aSensitive->IsActiveForSelection())
1070       {
1071         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1072       }
1073     }
1074   }
1075 }
1076
1077 //=======================================================================
1078 //function : AllowOverlapDetection
1079 //purpose  : Sets the detection type: if theIsToAllow is false,
1080 //           only fully included sensitives will be detected, otherwise
1081 //           the algorithm will mark both included and overlapped entities
1082 //           as matched
1083 //=======================================================================
1084 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1085 {
1086   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1087 }
1088
1089 //=======================================================================
1090 //function : DumpJson
1091 //purpose  : 
1092 //=======================================================================
1093 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const 
1094 {
1095   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1096
1097   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1098   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1099
1100   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1101   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1102
1103   Standard_Integer aNbOfSelectableObjects = 0;
1104   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1105   {
1106     aNbOfSelectableObjects++;
1107   }
1108   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1109
1110   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1111   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1112   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1113
1114   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1115   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1116   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1117   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1118
1119   if (!myIndexes.IsNull())
1120     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1121
1122   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1123   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1124 }
1125
1126 //=======================================================================
1127 //function : SetToPrebuildBVH
1128 //purpose  : 
1129 //=======================================================================
1130 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1131 {
1132   if (!theToPrebuild && !myBVHThreadPool.IsNull())
1133   {
1134     myBVHThreadPool.Nullify();
1135   }
1136   else if (theToPrebuild)
1137   {
1138     myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1139   }
1140   myToPrebuildBVH = theToPrebuild;
1141 }
1142
1143 //=======================================================================
1144 //function : QueueBVHBuild
1145 //purpose  : 
1146 //=======================================================================
1147 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1148 {
1149   if (myToPrebuildBVH)
1150   {
1151     myBVHThreadPool->AddEntity (theEntity);
1152   }
1153 }
1154
1155 //=======================================================================
1156 //function : WaitForBVHBuild
1157 //purpose  : 
1158 //=======================================================================
1159 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1160 {
1161   if (myToPrebuildBVH)
1162   {
1163     myBVHThreadPool->WaitThreads();
1164   }
1165 }