0032337: Visualization - rename Overlaps() method in selection to more self-describab...
[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   myToUpdateTolerance (Standard_True),
167   myCameraScale (1.0),
168   myToPrebuildBVH (Standard_False),
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.IsScalableActiveVolume()
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() != SelectMgr_SelectionType_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       if (theCamera.IsNull())
384       {
385         return;
386       }
387       gp_GTrsf aTPers;
388       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
389
390       aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
391       aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
392       aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
393       aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
394       aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
395       aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
396       aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
397       aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
398       aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
399       aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
400
401       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
402     }
403   }
404
405   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
406                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
407                                         : theMgr;
408   if (!aMgr.OverlapsBox (aSensitivesTree->MinPoint (0),
409                          aSensitivesTree->MaxPoint (0)))
410   {
411     return;
412   }
413
414   if (!theObject->ClipPlanes().IsNull()
415     && theObject->ClipPlanes()->ToOverrideGlobal())
416   {
417     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
418   }
419   else if (!theObject->TransformPersistence().IsNull())
420   {
421     if (theObject->TransformPersistence()->IsZoomOrRotate()
422     && !theMgr.ViewClipping().IsNull())
423     {
424       // Zoom/rotate persistence object lives in two worlds at the same time.
425       // Global clipping planes can not be trivially applied without being converted
426       // into local space of transformation persistence object.
427       // As more simple alternative - just clip entire object by its anchor point defined in the world space.
428       const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
429       for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
430       {
431         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
432         if (!aPlane->IsOn())
433         {
434           continue;
435         }
436
437         const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
438         if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
439         {
440           return;
441         }
442       }
443     }
444
445     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
446   }
447   else if (!theObject->ClipPlanes().IsNull()
448         && !theObject->ClipPlanes()->IsEmpty())
449   {
450     aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
451   }
452
453   if (!theMgr.ViewClipping().IsNull() &&
454       theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
455   {
456     Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
457     // If box selection is active, and the whole sensitive tree is out of the clip planes
458     // selection is empty for this object
459     const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
460
461     for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
462     {
463       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
464       if (!aPlane->IsOn())
465       {
466         continue;
467       }
468
469       Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
470       if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
471       {
472         return;
473       }
474     }
475   }
476
477   const Standard_Integer aFirstStored = mystored.Extent() + 1;
478
479   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
480   Standard_Integer aHead = -1;
481   Standard_Integer aNode = 0; // a root node
482   SelectMgr_FrustumCache aScaledTrnsfFrustums;
483   SelectMgr_SelectingVolumeManager aTmpMgr;
484   for (;;)
485   {
486     if (!aSensitivesTree->IsOuter (aNode))
487     {
488       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
489       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
490       const Standard_Boolean isLeftChildIn  =  aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx),
491                                                                  aSensitivesTree->MaxPoint (aLeftChildIdx));
492       const Standard_Boolean isRightChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx),
493                                                                 aSensitivesTree->MaxPoint (aRightChildIdx));
494       if (isLeftChildIn
495           && isRightChildIn)
496       {
497         aNode = aLeftChildIdx;
498         ++aHead;
499         aStack[aHead] = aRightChildIdx;
500       }
501       else if (isLeftChildIn
502         || isRightChildIn)
503       {
504         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
505       }
506       else
507       {
508         if (aHead < 0)
509         {
510           break;
511         }
512
513         aNode = aStack[aHead];
514         --aHead;
515       }
516     }
517     else
518     {
519       bool aClipped = false;
520       if (!theMgr.ViewClipping().IsNull() &&
521           theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
522       {
523         Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
524         // If box selection is active, and the whole sensitive tree is out of the clip planes
525         // selection is empty for this object
526         const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
527
528         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
529         {
530           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
531           if (!aPlane->IsOn())
532           {
533             continue;
534           }
535           Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
536           if (aState == Graphic3d_ClipState_Out)
537           {
538             aClipped = true;
539             break;
540           }
541           if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
542           {
543             if (aPlane->ProbeBoxTouch (aBBox))
544               continue;
545             aClipped = true;
546             break;
547           }
548         }
549       }
550       if (!aClipped)
551       {
552         Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
553         Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
554         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
555         {
556           const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
557           if (aSensitive->IsActiveForSelection())
558           {
559             const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
560             computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
561             checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
562           }
563         }
564       }
565       if (aHead < 0)
566       {
567         break;
568       }
569
570       aNode = aStack[aHead];
571       --aHead;
572     }
573   }
574
575   // in case of Box/Polyline selection - keep only Owners having all Entities detected
576   if (mySelectingVolumeMgr.IsOverlapAllowed()
577   || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
578    && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
579   {
580     return;
581   }
582
583   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
584   {
585     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
586     const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
587     Standard_Integer aNbOwnerEntities = 0;
588     anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
589     if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
590     {
591       mystored.RemoveFromIndex (aStoredIter);
592     }
593   }
594 }
595
596 //=======================================================================
597 // function: TraverseSensitives
598 // purpose : Traverses BVH containing all added selectable objects and
599 //           finds candidates for further search of overlap
600 //=======================================================================
601 void SelectMgr_ViewerSelector::TraverseSensitives()
602 {
603   SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
604
605   mystored.Clear();
606
607   Standard_Integer aWidth = 0;
608   Standard_Integer aHeight = 0;
609   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
610   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
611                                  mySelectingVolumeMgr.ProjectionMatrix(),
612                                  mySelectingVolumeMgr.WorldViewMatrix(),
613                                  mySelectingVolumeMgr.WorldViewProjState(),
614                                  aWidth, aHeight);
615   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
616   if (!aCamera.IsNull())
617   {
618     myCameraEye = aCamera->Eye().XYZ();
619     myCameraDir = aCamera->Direction().XYZ();
620     myCameraScale = aCamera->IsOrthographic()
621                   ? aCamera->Scale()
622                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
623     const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
624     myCameraScale *= aPixelSize;
625   }
626
627   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
628   {
629     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
630       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
631
632     if (mySelectableObjects.IsEmpty (aBVHSubset))
633     {
634       continue;
635     }
636
637     gp_GTrsf aTFrustum;
638
639     SelectMgr_SelectingVolumeManager aMgr;
640
641     // for 2D space selection transform selecting volumes to perform overap testing
642     // directly in camera's eye space omitting the camera position, which is not
643     // needed there at all
644     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
645     {
646       if (aCamera.IsNull())
647       {
648         continue;
649       }
650       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
651       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
652       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
653       aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
654       aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
655       aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
656       aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
657       aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
658       aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
659       aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
660       aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
661
662       // define corresponding frustum builder parameters
663       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
664       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix(),
665                                      aCamera->IsZeroToOneDepth());
666       aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
667       aBuilder->SetWindowSize (aWidth, aHeight);
668       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
669     }
670     else
671     {
672       aMgr = mySelectingVolumeMgr;
673     }
674
675     const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
676     const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
677                                             ? mySelectingVolumeMgr.WorldViewMatrix()
678                                             : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
679
680     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
681
682     Standard_Integer aNode = 0;
683     if (!aMgr.OverlapsBox (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
684     {
685       continue;
686     }
687
688     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
689     Standard_Integer aHead = -1;
690     for (;;)
691     {
692       if (!aBVHTree->IsOuter (aNode))
693       {
694         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
695         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
696         const Standard_Boolean isLeftChildIn  =
697           aMgr.OverlapsBox (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
698         const Standard_Boolean isRightChildIn =
699           aMgr.OverlapsBox (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
700         if (isLeftChildIn
701           && isRightChildIn)
702         {
703           aNode = aLeftChildIdx;
704           ++aHead;
705           aStack[aHead] = aRightChildIdx;
706         }
707         else if (isLeftChildIn
708           || isRightChildIn)
709         {
710           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
711         }
712         else
713         {
714           if (aHead < 0)
715           {
716             break;
717           }
718
719           aNode = aStack[aHead];
720           --aHead;
721         }
722       }
723       else
724       {
725         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
726         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
727         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
728         {
729           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
730             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
731
732           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
733         }
734         if (aHead < 0)
735         {
736           break;
737         }
738
739         aNode = aStack[aHead];
740         --aHead;
741       }
742     }
743   }
744
745   SortResult();
746 }
747
748 //==================================================
749 // Function: ClearPicked
750 // Purpose :
751 //==================================================
752 void SelectMgr_ViewerSelector::ClearPicked()
753 {
754   mystored.Clear();
755 }
756
757 //=======================================================================
758 //function : Picked
759 //purpose  :
760 //=======================================================================
761 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
762 {
763   if (theRank < 1 || theRank > NbPicked())
764   {
765     return Handle(SelectMgr_EntityOwner)();
766   }
767
768   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
769   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
770   return aStoredOwner;
771 }
772
773 //=======================================================================
774 //function : PickedData
775 //purpose  :
776 //=======================================================================
777 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
778 {
779   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
780   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
781   return mystored.FindFromIndex (anOwnerIdx);
782 }
783
784 //===================================================
785 //
786 //       INTERNAL METHODS ....
787 //
788 //==================================================
789
790 //==================================================
791 // Function: SetEntitySetBuilder
792 // Purpose :
793 //==================================================
794 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
795 {
796   myEntitySetBuilder = theBuilder;
797   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
798   {
799     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
800   }
801 }
802
803 //==================================================
804 // Function: Contains
805 // Purpose :
806 //==================================================
807 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
808 {
809   return mySelectableObjects.Contains (theObject);
810 }
811
812 //==================================================
813 // Function: ActiveModes
814 // Purpose : return all the  modes with a given state for an object
815 //==================================================
816 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
817                                                   TColStd_ListOfInteger& theModeList,
818                                                   const SelectMgr_StateOfSelection theWantedState) const
819 {
820   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
821   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
822   {
823     if (theWantedState == SelectMgr_SOS_Any)
824     {
825       theModeList.Append (aSelIter.Value()->Mode());
826     }
827     else if (theWantedState == aSelIter.Value()->GetSelectionState())
828     {
829       theModeList.Append (aSelIter.Value()->Mode());
830     }
831   }
832
833   return hasActivatedStates;
834 }
835
836 //==================================================
837 // Function: IsActive
838 // Purpose :
839 //==================================================
840 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
841                                                      const Standard_Integer theMode) const
842 {
843   if (!Contains (theSelectableObject))
844     return Standard_False;
845
846   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
847   return !aSel.IsNull()
848        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
849 }
850
851 //==================================================
852 // Function: IsInside
853 // Purpose :
854 //==================================================
855 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
856                                                      const Standard_Integer theMode) const
857 {
858   if (!Contains (theSelectableObject))
859     return Standard_False;
860
861   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
862   return !aSel.IsNull()
863        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
864 }
865
866
867 //=======================================================================
868 //function : Status
869 //purpose  :
870 //=======================================================================
871
872 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
873 {
874   return theSelection->GetSelectionState();
875 }
876
877 //==================================================
878 // Function: Status
879 // Purpose : gives Information about selectors
880 //==================================================
881
882 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
883 {
884   TCollection_AsciiString aStatus ("Status Object :\n\t");
885   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
886   {
887     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
888     {
889       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
890               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
891     }
892   }
893
894   if (!Contains (theSelectableObject))
895   {
896     aStatus = aStatus + "Not Present in the selector\n\n";
897   }
898
899   return aStatus;
900 }
901
902 //=======================================================================
903 //function : SortResult
904 //purpose  :
905 //=======================================================================
906 void SelectMgr_ViewerSelector::SortResult()
907 {
908   if (mystored.IsEmpty())
909   {
910     return;
911   }
912
913   const Standard_Integer anExtent = mystored.Extent();
914   if (myIndexes.IsNull() || anExtent != myIndexes->Length())
915   {
916     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
917   }
918
919   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
920   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
921   {
922     anIndexArray.SetValue (anIndexIter, anIndexIter);
923   }
924   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
925 }
926
927 //=======================================================================
928 // function : AddSelectableObject
929 // purpose  : Adds new object to the map of selectable objects
930 //=======================================================================
931 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
932 {
933   if (!myMapOfObjectSensitives.IsBound (theObject))
934   {
935     mySelectableObjects.Append (theObject);
936     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
937     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
938   }
939 }
940
941 //=======================================================================
942 // function : AddSelectionToObject
943 // purpose  : Adds new selection to the object and builds its BVH tree
944 //=======================================================================
945 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
946                                                      const Handle(SelectMgr_Selection)& theSelection)
947 {
948   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
949   {
950     (*anEntitySet)->Append (theSelection);
951     (*anEntitySet)->BVH();
952   }
953   else
954   {
955     AddSelectableObject (theObject);
956     AddSelectionToObject (theObject, theSelection);
957   }
958 }
959
960 //=======================================================================
961 // function : MoveSelectableObject
962 // purpose  :
963 //=======================================================================
964 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
965 {
966   mySelectableObjects.ChangeSubset (theObject);
967 }
968
969 //=======================================================================
970 // function : RemoveSelectableObject
971 // purpose  : Removes selectable object from map of selectable ones
972 //=======================================================================
973 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
974 {
975   Handle(SelectMgr_SelectableObject) anObj = theObject;
976   if (myMapOfObjectSensitives.UnBind (theObject))
977   {
978     mySelectableObjects.Remove (theObject);
979   }
980 }
981
982 //=======================================================================
983 // function : RemoveSelectionOfObject
984 // purpose  : Removes selection of the object and marks its BVH tree
985 //            for rebuild
986 //=======================================================================
987 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
988                                                         const Handle(SelectMgr_Selection)& theSelection)
989 {
990   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
991   {
992     (*anEntitySet)->Remove (theSelection);
993   }
994 }
995
996 //=======================================================================
997 // function : RebuildObjectsTree
998 // purpose  : Marks BVH of selectable objects for rebuild
999 //=======================================================================
1000 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
1001 {
1002   mySelectableObjects.MarkDirty();
1003
1004   if (theIsForce)
1005   {
1006     Standard_Integer aViewportWidth, aViewportHeight;
1007     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
1008
1009     Standard_Integer aWidth;
1010     Standard_Integer aHeight;
1011     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
1012     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
1013                                    mySelectingVolumeMgr.ProjectionMatrix(),
1014                                    mySelectingVolumeMgr.WorldViewMatrix(),
1015                                    mySelectingVolumeMgr.WorldViewProjState(),
1016                                    aWidth, aHeight);
1017   }
1018 }
1019
1020 //=======================================================================
1021 // function : RebuildSensitivesTree
1022 // purpose  : Marks BVH of sensitive entities of particular selectable
1023 //            object for rebuild
1024 //=======================================================================
1025 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1026                                                       const Standard_Boolean theIsForce)
1027 {
1028   if (!Contains (theObject))
1029     return;
1030
1031   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1032   anEntitySet->MarkDirty();
1033
1034   if (theIsForce)
1035   {
1036     anEntitySet->BVH();
1037   }
1038 }
1039
1040 //=======================================================================
1041 // function : resetSelectionActivationStatus
1042 // purpose  : Marks all added sensitive entities of all objects as
1043 //            non-selectable
1044 //=======================================================================
1045 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1046 {
1047   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1048   {
1049     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1050     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1051     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1052     {
1053       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1054     }
1055   }
1056 }
1057
1058 //=======================================================================
1059 // function : ActiveOwners
1060 // purpose  : Returns the list of active entity owners
1061 //=======================================================================
1062 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1063 {
1064   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1065   {
1066     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1067     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1068     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1069     {
1070       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1071       if (aSensitive->IsActiveForSelection())
1072       {
1073         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1074       }
1075     }
1076   }
1077 }
1078
1079 //=======================================================================
1080 //function : AllowOverlapDetection
1081 //purpose  : Sets the detection type: if theIsToAllow is false,
1082 //           only fully included sensitives will be detected, otherwise
1083 //           the algorithm will mark both included and overlapped entities
1084 //           as matched
1085 //=======================================================================
1086 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1087 {
1088   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1089 }
1090
1091 //=======================================================================
1092 //function : DumpJson
1093 //purpose  : 
1094 //=======================================================================
1095 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const 
1096 {
1097   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1098
1099   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1100   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
1101   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1102
1103   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1104   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1105
1106   Standard_Integer aNbOfSelectableObjects = 0;
1107   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1108   {
1109     aNbOfSelectableObjects++;
1110   }
1111   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1112
1113   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1114   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1115   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1116
1117   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1118   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1119   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1120   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1121
1122   if (!myIndexes.IsNull())
1123     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1124
1125   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1126   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1127 }
1128
1129 //=======================================================================
1130 //function : SetToPrebuildBVH
1131 //purpose  : 
1132 //=======================================================================
1133 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1134 {
1135   if (!theToPrebuild && !myBVHThreadPool.IsNull())
1136   {
1137     myBVHThreadPool.Nullify();
1138   }
1139   else if (theToPrebuild)
1140   {
1141     myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1142   }
1143   myToPrebuildBVH = theToPrebuild;
1144 }
1145
1146 //=======================================================================
1147 //function : QueueBVHBuild
1148 //purpose  : 
1149 //=======================================================================
1150 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1151 {
1152   if (myToPrebuildBVH)
1153   {
1154     myBVHThreadPool->AddEntity (theEntity);
1155   }
1156 }
1157
1158 //=======================================================================
1159 //function : WaitForBVHBuild
1160 //purpose  : 
1161 //=======================================================================
1162 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1163 {
1164   if (myToPrebuildBVH)
1165   {
1166     myBVHThreadPool->WaitThreads();
1167   }
1168 }