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