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