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