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