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