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