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