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