0030640: Visualization, Graphic3d_Camera - add option creating Projection matrix...
[occt.git] / src / SelectMgr / SelectMgr_ViewerSelector.cxx
1 // Created on: 1995-02-15
2 // Created by: Roberc Coublanc
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <SelectMgr_ViewerSelector.hxx>
18
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
21 #include <gp_Pnt.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_SensitiveEntity.hxx>
25 #include <SelectBasics_PickResult.hxx>
26 #include <SelectMgr_EntityOwner.hxx>
27 #include <SelectMgr_SortCriterion.hxx>
28 #include <SelectMgr_SensitiveEntitySet.hxx>
29 #include <TColStd_Array1OfInteger.hxx>
30 #include <TCollection_AsciiString.hxx>
31 #include <TColStd_HArray1OfInteger.hxx>
32 #include <TColStd_ListOfInteger.hxx>
33
34 #include <algorithm>
35
36 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
37
38 namespace
39 {
40   //! Comparison operator for sorting selection results
41   class CompareResults
42   {
43   public:
44
45     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
46                     bool theToPreferClosest)
47     : myMapOfCriterion (&theMapOfCriterion),
48       myToPreferClosest (theToPreferClosest) {}
49
50     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
51     {
52       const SelectMgr_SortCriterion& anElemLeft  = myMapOfCriterion->FindFromIndex (theLeft);
53       const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
54       if (myToPreferClosest)
55       {
56         return anElemLeft.IsCloserDepth (anElemRight);
57       }
58       else
59       {
60         return anElemLeft.IsHigherPriority (anElemRight);
61       }
62     }
63
64   private:
65     const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
66     bool myToPreferClosest;
67   };
68
69   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
70 }
71
72 //=======================================================================
73 // function : updatePoint3d
74 // purpose  :
75 //=======================================================================
76 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
77                                               const SelectBasics_PickResult& thePickResult,
78                                               const Handle(Select3D_SensitiveEntity)& theEntity,
79                                               const gp_GTrsf& theInversedTrsf,
80                                               const SelectMgr_SelectingVolumeManager& theMgr) const
81 {
82   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
83   {
84     return;
85   }
86
87   bool hasNormal = false;
88   if (thePickResult.HasPickedPoint())
89   {
90     theCriterion.Point  = thePickResult.PickedPoint();
91     theCriterion.Normal = thePickResult.SurfaceNormal();
92     const float aNormLen2 = theCriterion.Normal.SquareModulus();
93     if (aNormLen2 > ShortRealEpsilon())
94     {
95       hasNormal = true;
96       theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
97     }
98   }
99   else if (!thePickResult.IsValid())
100   {
101     theCriterion.Point = thePickResult.PickedPoint();
102     return;
103   }
104   else
105   {
106     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
107   }
108
109   gp_GTrsf anInvTrsf = theInversedTrsf;
110   if (theCriterion.Entity->HasInitLocation())
111   {
112     anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
113   }
114   if (anInvTrsf.Form() != gp_Identity)
115   {
116     const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
117     anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
118     if (hasNormal)
119     {
120       Graphic3d_Mat4d aMat4;
121       anInvInvTrsd.GetMat4 (aMat4);
122       const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
123       theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
124     }
125   }
126
127   const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
128   switch (myDepthTolType)
129   {
130     case SelectMgr_TypeOfDepthTolerance_Uniform:
131     {
132       theCriterion.Tolerance = myDepthTolerance;
133       break;
134     }
135     case SelectMgr_TypeOfDepthTolerance_UniformPixels:
136     case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
137     {
138       if (mySelectingVolumeMgr.Camera().IsNull())
139       {
140         // fallback for an arbitrary projection matrix
141         theCriterion.Tolerance = aSensFactor / 33.0;
142       }
143       else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
144       {
145         theCriterion.Tolerance = myCameraScale * aSensFactor;
146       }
147       else
148       {
149         const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
150         theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
151       }
152       break;
153     }
154   }
155 }
156
157 //==================================================
158 // Function: Initialize
159 // Purpose :
160 //==================================================
161 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
162 : myDepthTolerance (0.0),
163   myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
164   myToPreferClosest (Standard_True),
165   myToUpdateTolerance (Standard_True),
166   myCameraScale (1.0),
167   myToPrebuildBVH (Standard_False),
168   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
184   myToUpdateTolerance = Standard_True;
185   if (theTolerance < 0)
186   {
187     myTolerances.ResetDefaults();
188   }
189   else
190   {
191     myTolerances.SetCustomTolerance (theTolerance);
192   }
193 }
194
195 //==================================================
196 // Function: Activate
197 // Purpose :
198 //==================================================
199 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
200 {
201   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
202   {
203     aSelEntIter.Value()->SetActiveForSelection();
204   }
205
206   if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
207   {
208     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
209
210     myTolerances.Add (theSelection->Sensitivity());
211     myToUpdateTolerance = Standard_True;
212   }
213 }
214
215 //==================================================
216 // Function: Deactivate
217 // Purpose :
218 //==================================================
219 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
220 {
221   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
222   {
223     aSelEntIter.Value()->ResetSelectionActiveStatus();
224   }
225
226   if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
227   {
228     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
229
230     myTolerances.Decrement (theSelection->Sensitivity());
231     myToUpdateTolerance = Standard_True;
232   }
233 }
234
235 //==================================================
236 // Function: Clear
237 // Purpose :
238 //==================================================
239 void SelectMgr_ViewerSelector::Clear()
240 {
241   mystored.Clear();
242 }
243
244 //=======================================================================
245 // function: isToScaleFrustum
246 // purpose : Checks if the entity given requires to scale current selecting frustum
247 //=======================================================================
248 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
249 {
250   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
251     && sensitivity (theEntity) < myTolerances.Tolerance();
252 }
253
254 //=======================================================================
255 // function: sensitivity
256 // purpose : In case if custom tolerance is set, this method will return sum of entity
257 //           sensitivity and custom tolerance.
258 //=======================================================================
259 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
260 {
261   return myTolerances.IsCustomTolSet() ?
262     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
263 }
264
265 //=======================================================================
266 // function: checkOverlap
267 // purpose : Internal function that checks if a particular sensitive
268 //           entity theEntity overlaps current selecting volume precisely
269 //=======================================================================
270 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
271                                              const gp_GTrsf& theInversedTrsf,
272                                              SelectMgr_SelectingVolumeManager& theMgr)
273 {
274   const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
275   Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
276   SelectBasics_PickResult aPickResult;
277   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
278   if (!isMatched
279     || anOwner.IsNull())
280   {
281     return;
282   }
283
284   SelectMgr_SortCriterion aCriterion;
285   myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
286   aCriterion.Entity    = theEntity;
287   aCriterion.Priority  = anOwner->Priority();
288   aCriterion.Depth     = aPickResult.Depth();
289   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
290
291   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
292   {
293     ++aPrevCriterion->NbOwnerMatches;
294     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
295     if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
296     {
297       if (aCriterion.IsCloserDepth (*aPrevCriterion))
298       {
299         updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
300         *aPrevCriterion = aCriterion;
301       }
302     }
303   }
304   else
305   {
306     aCriterion.NbOwnerMatches = 1;
307     updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
308     mystored.Add (anOwner, aCriterion);
309   }
310 }
311
312 //=======================================================================
313 // function: computeFrustum
314 // purpose :
315 //=======================================================================
316 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
317                                                const SelectMgr_SelectingVolumeManager& theMgrGlobal,
318                                                const SelectMgr_SelectingVolumeManager& theMgrObject,
319                                                const gp_GTrsf& theInvTrsf,
320                                                SelectMgr_FrustumCache& theCachedMgrs,
321                                                SelectMgr_SelectingVolumeManager& theResMgr)
322 {
323   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
324   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
325   const Standard_Boolean toScale = aScale != 1;
326   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
327   if (toScale && toTransform)
328   {
329     theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
330     theResMgr.SetViewClipping (theMgrObject);
331   }
332   else if (toScale)
333   {
334     if (!theCachedMgrs.Find (aScale, theResMgr))
335     {
336       theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
337       theCachedMgrs.Bind (aScale, theResMgr);
338     }
339     theResMgr.SetViewClipping (theMgrObject);
340   }
341   else if (toTransform)
342   {
343     theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
344     theResMgr.SetViewClipping (theMgrObject);
345   }
346   else
347   {
348     theResMgr = theMgrObject;
349   }
350 }
351
352 //=======================================================================
353 // function: traverseObject
354 // purpose : Internal function that checks if there is possible overlap
355 //           between some entity of selectable object theObject and
356 //           current selecting volume
357 //=======================================================================
358 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
359                                                const SelectMgr_SelectingVolumeManager& theMgr,
360                                                const Handle(Graphic3d_Camera)& theCamera,
361                                                const Graphic3d_Mat4d& theProjectionMat,
362                                                const Graphic3d_Mat4d& theWorldViewMat,
363                                                const Standard_Integer theViewportWidth,
364                                                const Standard_Integer theViewportHeight)
365 {
366   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
367   if (anEntitySet->Size() == 0)
368   {
369     return;
370   }
371
372   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
373   gp_GTrsf aInversedTrsf;
374   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
375   {
376     if (theObject->TransformPersistence().IsNull())
377     {
378       aInversedTrsf = theObject->InversedTransformation();
379     }
380     else
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.Overlaps (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() == SelectBasics_SelectingVolumeManager::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 (false);
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.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
486                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
487       const Standard_Boolean isRightChildIn = aMgr.Overlaps (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() == SelectBasics_SelectingVolumeManager::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() != SelectBasics_SelectingVolumeManager::Box
573    && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::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;
603   Standard_Integer aHeight;
604   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
605   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
606                                  mySelectingVolumeMgr.ProjectionMatrix(),
607                                  mySelectingVolumeMgr.WorldViewMatrix(),
608                                  mySelectingVolumeMgr.WorldViewProjState(),
609                                  aWidth, aHeight);
610   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
611   if (!aCamera.IsNull())
612   {
613     myCameraEye = aCamera->Eye().XYZ();
614     myCameraDir = aCamera->Direction().XYZ();
615     myCameraScale = aCamera->IsOrthographic()
616                   ? aCamera->Scale()
617                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
618     const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
619     myCameraScale *= aPixelSize;
620   }
621
622   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
623   {
624     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
625       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
626
627     if (mySelectableObjects.IsEmpty (aBVHSubset))
628     {
629       continue;
630     }
631
632     gp_GTrsf aTFrustum;
633
634     SelectMgr_SelectingVolumeManager aMgr (Standard_False);
635
636     // for 2D space selection transform selecting volumes to perform overap testing
637     // directly in camera's eye space omitting the camera position, which is not
638     // needed there at all
639     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
640     {
641       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
642       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
643       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
644       aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
645       aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
646       aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
647       aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
648       aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
649       aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
650       aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
651       aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
652
653       // define corresponding frustum builder parameters
654       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
655       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix(),
656                                      !aCamera.IsNull() && aCamera->IsZeroToOneDepth());
657       aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
658       aBuilder->SetWindowSize (aWidth, aHeight);
659       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
660     }
661     else
662     {
663       aMgr = mySelectingVolumeMgr;
664     }
665
666     const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
667     const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
668                                             ? mySelectingVolumeMgr.WorldViewMatrix()
669                                             : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
670
671     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
672
673     Standard_Integer aNode = 0;
674     if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
675     {
676       continue;
677     }
678
679     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
680     Standard_Integer aHead = -1;
681     for (;;)
682     {
683       if (!aBVHTree->IsOuter (aNode))
684       {
685         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
686         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
687         const Standard_Boolean isLeftChildIn  =
688           aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
689         const Standard_Boolean isRightChildIn =
690           aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
691         if (isLeftChildIn
692           && isRightChildIn)
693         {
694           aNode = aLeftChildIdx;
695           ++aHead;
696           aStack[aHead] = aRightChildIdx;
697         }
698         else if (isLeftChildIn
699           || isRightChildIn)
700         {
701           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
702         }
703         else
704         {
705           if (aHead < 0)
706           {
707             break;
708           }
709
710           aNode = aStack[aHead];
711           --aHead;
712         }
713       }
714       else
715       {
716         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
717         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
718         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
719         {
720           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
721             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
722
723           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
724         }
725         if (aHead < 0)
726         {
727           break;
728         }
729
730         aNode = aStack[aHead];
731         --aHead;
732       }
733     }
734   }
735
736   SortResult();
737 }
738
739 //==================================================
740 // Function: ClearPicked
741 // Purpose :
742 //==================================================
743 void SelectMgr_ViewerSelector::ClearPicked()
744 {
745   mystored.Clear();
746 }
747
748 //=======================================================================
749 //function : Picked
750 //purpose  :
751 //=======================================================================
752 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
753 {
754   if (theRank < 1 || theRank > NbPicked())
755   {
756     return Handle(SelectMgr_EntityOwner)();
757   }
758
759   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
760   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
761   return aStoredOwner;
762 }
763
764 //=======================================================================
765 //function : PickedData
766 //purpose  :
767 //=======================================================================
768 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
769 {
770   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
771   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
772   return mystored.FindFromIndex (anOwnerIdx);
773 }
774
775 //===================================================
776 //
777 //       INTERNAL METHODS ....
778 //
779 //==================================================
780
781 //==================================================
782 // Function: SetEntitySetBuilder
783 // Purpose :
784 //==================================================
785 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
786 {
787   myEntitySetBuilder = theBuilder;
788   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
789   {
790     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
791   }
792 }
793
794 //==================================================
795 // Function: Contains
796 // Purpose :
797 //==================================================
798 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
799 {
800   return mySelectableObjects.Contains (theObject);
801 }
802
803 //==================================================
804 // Function: ActiveModes
805 // Purpose : return all the  modes with a given state for an object
806 //==================================================
807 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
808                                                   TColStd_ListOfInteger& theModeList,
809                                                   const SelectMgr_StateOfSelection theWantedState) const
810 {
811   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
812   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
813   {
814     if (theWantedState == SelectMgr_SOS_Any)
815     {
816       theModeList.Append (aSelIter.Value()->Mode());
817     }
818     else if (theWantedState == aSelIter.Value()->GetSelectionState())
819     {
820       theModeList.Append (aSelIter.Value()->Mode());
821     }
822   }
823
824   return hasActivatedStates;
825 }
826
827 //==================================================
828 // Function: IsActive
829 // Purpose :
830 //==================================================
831 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
832                                                      const Standard_Integer theMode) const
833 {
834   if (!Contains (theSelectableObject))
835     return Standard_False;
836
837   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
838   return !aSel.IsNull()
839        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
840 }
841
842 //==================================================
843 // Function: IsInside
844 // Purpose :
845 //==================================================
846 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
847                                                      const Standard_Integer theMode) const
848 {
849   if (!Contains (theSelectableObject))
850     return Standard_False;
851
852   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
853   return !aSel.IsNull()
854        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
855 }
856
857
858 //=======================================================================
859 //function : Status
860 //purpose  :
861 //=======================================================================
862
863 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
864 {
865   return theSelection->GetSelectionState();
866 }
867
868 //==================================================
869 // Function: Status
870 // Purpose : gives Information about selectors
871 //==================================================
872
873 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
874 {
875   TCollection_AsciiString aStatus ("Status Object :\n\t");
876   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
877   {
878     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
879     {
880       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
881               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
882     }
883   }
884
885   if (!Contains (theSelectableObject))
886   {
887     aStatus = aStatus + "Not Present in the selector\n\n";
888   }
889
890   return aStatus;
891 }
892
893 //=======================================================================
894 //function : SortResult
895 //purpose  :
896 //=======================================================================
897 void SelectMgr_ViewerSelector::SortResult()
898 {
899   if (mystored.IsEmpty())
900   {
901     return;
902   }
903
904   const Standard_Integer anExtent = mystored.Extent();
905   if (myIndexes.IsNull() || anExtent != myIndexes->Length())
906   {
907     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
908   }
909
910   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
911   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
912   {
913     anIndexArray.SetValue (anIndexIter, anIndexIter);
914   }
915   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
916 }
917
918 //=======================================================================
919 // function : AddSelectableObject
920 // purpose  : Adds new object to the map of selectable objects
921 //=======================================================================
922 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
923 {
924   if (!myMapOfObjectSensitives.IsBound (theObject))
925   {
926     mySelectableObjects.Append (theObject);
927     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
928     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
929   }
930 }
931
932 //=======================================================================
933 // function : AddSelectionToObject
934 // purpose  : Adds new selection to the object and builds its BVH tree
935 //=======================================================================
936 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
937                                                      const Handle(SelectMgr_Selection)& theSelection)
938 {
939   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
940   {
941     (*anEntitySet)->Append (theSelection);
942     (*anEntitySet)->BVH();
943   }
944   else
945   {
946     AddSelectableObject (theObject);
947     AddSelectionToObject (theObject, theSelection);
948   }
949 }
950
951 //=======================================================================
952 // function : MoveSelectableObject
953 // purpose  :
954 //=======================================================================
955 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
956 {
957   mySelectableObjects.ChangeSubset (theObject);
958 }
959
960 //=======================================================================
961 // function : RemoveSelectableObject
962 // purpose  : Removes selectable object from map of selectable ones
963 //=======================================================================
964 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
965 {
966   Handle(SelectMgr_SelectableObject) anObj = theObject;
967   if (myMapOfObjectSensitives.UnBind (theObject))
968   {
969     mySelectableObjects.Remove (theObject);
970   }
971 }
972
973 //=======================================================================
974 // function : RemoveSelectionOfObject
975 // purpose  : Removes selection of the object and marks its BVH tree
976 //            for rebuild
977 //=======================================================================
978 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
979                                                         const Handle(SelectMgr_Selection)& theSelection)
980 {
981   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
982   {
983     (*anEntitySet)->Remove (theSelection);
984   }
985 }
986
987 //=======================================================================
988 // function : RebuildObjectsTree
989 // purpose  : Marks BVH of selectable objects for rebuild
990 //=======================================================================
991 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
992 {
993   mySelectableObjects.MarkDirty();
994
995   if (theIsForce)
996   {
997     Standard_Integer aViewportWidth, aViewportHeight;
998     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
999
1000     Standard_Integer aWidth;
1001     Standard_Integer aHeight;
1002     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
1003     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
1004                                    mySelectingVolumeMgr.ProjectionMatrix(),
1005                                    mySelectingVolumeMgr.WorldViewMatrix(),
1006                                    mySelectingVolumeMgr.WorldViewProjState(),
1007                                    aWidth, aHeight);
1008   }
1009 }
1010
1011 //=======================================================================
1012 // function : RebuildSensitivesTree
1013 // purpose  : Marks BVH of sensitive entities of particular selectable
1014 //            object for rebuild
1015 //=======================================================================
1016 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1017                                                       const Standard_Boolean theIsForce)
1018 {
1019   if (!Contains (theObject))
1020     return;
1021
1022   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1023   anEntitySet->MarkDirty();
1024
1025   if (theIsForce)
1026   {
1027     anEntitySet->BVH();
1028   }
1029 }
1030
1031 //=======================================================================
1032 // function : resetSelectionActivationStatus
1033 // purpose  : Marks all added sensitive entities of all objects as
1034 //            non-selectable
1035 //=======================================================================
1036 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1037 {
1038   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1039   {
1040     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1041     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1042     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1043     {
1044       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1045     }
1046   }
1047 }
1048
1049 //=======================================================================
1050 // function : ActiveOwners
1051 // purpose  : Returns the list of active entity owners
1052 //=======================================================================
1053 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1054 {
1055   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1056   {
1057     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1058     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1059     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1060     {
1061       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1062       if (aSensitive->IsActiveForSelection())
1063       {
1064         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1065       }
1066     }
1067   }
1068 }
1069
1070 //=======================================================================
1071 //function : AllowOverlapDetection
1072 //purpose  : Sets the detection type: if theIsToAllow is false,
1073 //           only fully included sensitives will be detected, otherwise
1074 //           the algorithm will mark both included and overlapped entities
1075 //           as matched
1076 //=======================================================================
1077 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1078 {
1079   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1080 }
1081
1082 //=======================================================================
1083 //function : DumpJson
1084 //purpose  : 
1085 //=======================================================================
1086 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const 
1087 {
1088   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1089
1090   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1091   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
1092   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1093
1094   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1095   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1096
1097   Standard_Integer aNbOfSelectableObjects = 0;
1098   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1099   {
1100     aNbOfSelectableObjects++;
1101   }
1102   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1103
1104   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1105   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1106   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1107
1108   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1109   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1110   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1111   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1112
1113   if (!myIndexes.IsNull())
1114     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1115
1116   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1117   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1118 }
1119
1120 //=======================================================================
1121 //function : SetToPrebuildBVH
1122 //purpose  : 
1123 //=======================================================================
1124 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1125 {
1126   if (!theToPrebuild && !myBVHThreadPool.IsNull())
1127   {
1128     myBVHThreadPool.Nullify();
1129   }
1130   else if (theToPrebuild)
1131   {
1132     myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1133   }
1134   myToPrebuildBVH = theToPrebuild;
1135 }
1136
1137 //=======================================================================
1138 //function : QueueBVHBuild
1139 //purpose  : 
1140 //=======================================================================
1141 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1142 {
1143   if (myToPrebuildBVH)
1144   {
1145     myBVHThreadPool->AddEntity (theEntity);
1146   }
1147 }
1148
1149 //=======================================================================
1150 //function : WaitForBVHBuild
1151 //purpose  : 
1152 //=======================================================================
1153 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1154 {
1155   if (myToPrebuildBVH)
1156   {
1157     myBVHThreadPool->WaitThreads();
1158   }
1159 }