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