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