a2d82dc953f960120de10b3ac200ac94d5b4bd58
[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 <SelectMgr_CompareResults.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 <SortTools_QuickSortOfInteger.hxx>
34 #include <TColStd_Array1OfInteger.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <TColStd_HArray1OfInteger.hxx>
37 #include <TColStd_ListOfInteger.hxx>
38
39 IMPLEMENT_STANDARD_HANDLE (SelectMgr_ViewerSelector, MMgt_TShared)
40 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, MMgt_TShared)
41
42 static Standard_Boolean SelectDebugModeOnVS()
43 {
44   static Standard_Integer isDebugMode( -1 );
45   if ( isDebugMode < 0 ) {
46     isDebugMode = 1;
47     OSD_Environment selectdb("SELDEBUGMODE");
48     if ( selectdb.Value().IsEmpty() )
49       isDebugMode = 0;
50   }
51   return ( isDebugMode != 0 );
52 }
53
54 SelectMgr_ToleranceMap::SelectMgr_ToleranceMap()
55 {
56   myLargestKey = -1;
57 }
58
59 SelectMgr_ToleranceMap::~SelectMgr_ToleranceMap()
60 {
61   myTolerances.Clear();
62 }
63
64 void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
65 {
66   if (myTolerances.IsBound (theTolerance))
67   {
68     Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
69     aFreq++;
70
71     if (theTolerance == myLargestKey)
72       return;
73
74     Standard_Integer aMaxFreq = myTolerances.Find (myLargestKey);
75     if (aFreq >= aMaxFreq)
76     {
77       myLargestKey = aFreq == aMaxFreq ? Max (myLargestKey, theTolerance) : theTolerance;
78     }
79   }
80   else
81   {
82     if (myTolerances.IsEmpty())
83     {
84       myTolerances.Bind (theTolerance, 1);
85       myLargestKey = theTolerance;
86       return;
87     }
88
89     myTolerances.Bind (theTolerance, 1);
90     Standard_Integer aMaxFreq = myTolerances.Find (myLargestKey);
91     if (aMaxFreq <= 1)
92     {
93       myLargestKey = aMaxFreq == 1 ? Max (myLargestKey, theTolerance) : theTolerance;
94     }
95   }
96 }
97
98 void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
99 {
100   if (myTolerances.IsBound (theTolerance))
101   {
102     Standard_Integer& aFreq = myTolerances.ChangeFind (theTolerance);
103     aFreq--;
104
105     if (theTolerance == myLargestKey)
106     {
107       Standard_Integer aMaxFreq = aFreq;
108       for (NCollection_DataMap<Standard_Real, Standard_Integer>::Iterator anIter (myTolerances); anIter.More(); anIter.Next())
109       {
110         if (aMaxFreq <= anIter.Value() && myLargestKey != anIter.Key())
111         {
112           aMaxFreq = anIter.Value();
113           myLargestKey = anIter.Key();
114         }
115       }
116     }
117   }
118 }
119
120 Standard_Real SelectMgr_ToleranceMap::Largest()
121 {
122   return myLargestKey;
123 }
124
125 //==================================================
126 // Function: Initialize
127 // Purpose :
128 //==================================================
129 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
130 preferclosest(Standard_True),
131 mytolerance(2.0),
132 myToUpdateTolerance (Standard_True),
133 myCurRank (0),
134 myIsLeftChildQueuedFirst (Standard_False),
135 myEntityIdx (0)
136 {
137   mySelectableObjects = new SelectMgr_SelectableObjectSet();
138 }
139
140
141 //==================================================
142 // Function: Activate
143 // Purpose :
144 //==================================================
145 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
146 {
147   for (theSelection->Init(); theSelection->More(); theSelection->Next())
148   {
149     theSelection->Sensitive()->SetActiveForSelection();
150   }
151
152   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
153
154   myTolerances.Add (theSelection->Sensitivity());
155   mytolerance = myTolerances.Largest();
156   myToUpdateTolerance = Standard_True;
157 }
158
159
160 //==================================================
161 // Function: Deactivate
162 // Purpose :
163 //==================================================
164 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
165 {
166   for (theSelection->Init(); theSelection->More(); theSelection->Next())
167   {
168     theSelection->Sensitive()->ResetSelectionActiveStatus();
169   }
170
171   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
172
173   myTolerances.Decrement (theSelection->Sensitivity());
174   mytolerance = myTolerances.Largest();
175   myToUpdateTolerance = Standard_True;
176 }
177
178 //==================================================
179 // Function: Clear
180 // Purpose :
181 //==================================================
182 void SelectMgr_ViewerSelector::Clear()
183 {
184   mystored.Clear();
185   myMapOfDetected.Clear();
186 }
187
188 //=======================================================================
189 // function: checkOverlap
190 // purpose : Internal function that checks if a particular sensitive
191 //           entity theEntity overlaps current selecting volume precisely
192 //=======================================================================
193 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
194                                              const Standard_Integer theEntityIdx,
195                                              SelectMgr_SelectingVolumeManager& theMgr)
196 {
197   const Handle(SelectMgr_EntityOwner)& anOwner =
198     Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId());
199
200   SelectBasics_PickResult aPickResult;
201   if (theEntity->Matches (theMgr, aPickResult))
202   {
203     if (!anOwner.IsNull())
204     {
205       Standard_Boolean isPointSelection =
206         theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point;
207       if (HasDepthClipping (anOwner) && isPointSelection)
208       {
209         Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
210                                                        aPickResult.Depth());
211         if (isClipped)
212           return;
213       }
214
215       Standard_Integer aPriority = anOwner->Priority();
216
217       SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33, preferclosest);
218       if (mystored.Contains (anOwner))
219       {
220         if (theMgr.GetActiveSelectionType() != 1)
221         {
222           SelectMgr_SortCriterion& aPrevCriterion = mystored.ChangeFromKey (anOwner);
223           if (aCriterion > aPrevCriterion)
224           {
225             aPrevCriterion = aCriterion;
226             myMapOfDetected.ChangeFind (anOwner) = theEntityIdx;
227           }
228         }
229       }
230       else
231       {
232         mystored.Add (anOwner, aCriterion);
233         myMapOfDetected.Bind (anOwner, theEntityIdx);
234       }
235     }
236   }
237 }
238
239 //=======================================================================
240 // function: traverseObject
241 // purpose : Internal function that checks if there is possible overlap
242 //           between some entity of selectable object theObject and
243 //           current selecting volume
244 //=======================================================================
245 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject)
246 {
247   NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
248     myMapOfObjectSensitives.ChangeFind (theObject);
249
250   if (anEntitySet->Size() == 0)
251     return;
252
253   const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
254
255   SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ?
256     mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr;
257
258   Standard_Integer aNode = 0; // a root node
259   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
260                       aSensitivesTree->MaxPoint (0)))
261   {
262     return;
263   }
264   Standard_Integer aStack[32];
265   Standard_Integer aHead = -1;
266   for (;;)
267   {
268     if (!aSensitivesTree->IsOuter (aNode))
269     {
270       const Standard_Integer aLeftChildIdx  = aSensitivesTree->LeftChild  (aNode);
271       const Standard_Integer aRightChildIdx = aSensitivesTree->RightChild (aNode);
272       const Standard_Boolean isLeftChildIn  =  aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
273                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
274       const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
275                                                              aSensitivesTree->MaxPoint (aRightChildIdx));
276       if (isLeftChildIn
277           && isRightChildIn)
278       {
279         aNode = aLeftChildIdx;
280         ++aHead;
281         aStack[aHead] = aRightChildIdx;
282       }
283       else if (isLeftChildIn
284         || isRightChildIn)
285       {
286         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
287       }
288       else
289       {
290         if (aHead < 0)
291         {
292           break;
293         }
294
295         aNode = aStack[aHead];
296         --aHead;
297       }
298     }
299     else
300     {
301       Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
302       Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
303       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
304       {
305         const Handle(SelectMgr_SensitiveEntity)& aSensitive =
306           anEntitySet->GetSensitiveById (anIdx);
307         if (aSensitive->IsActiveForSelection())
308         {
309           checkOverlap (aSensitive->BaseSensitive(), anIdx, aMgr);
310         }
311       }
312       if (aHead < 0)
313       {
314         break;
315       }
316
317       aNode = aStack[aHead];
318       --aHead;
319     }
320   }
321 }
322
323 //=======================================================================
324 // function: TraverseSensitives
325 // purpose : Traverses BVH containing all added selectable objects and
326 //           finds candidates for further search of overlap
327 //=======================================================================
328 void SelectMgr_ViewerSelector::TraverseSensitives()
329 {
330   mystored.Clear();
331   myMapOfDetected.Clear();
332
333   if (mySelectableObjects->Size() == 0)
334     return;
335
336   const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& anObjectsTree = mySelectableObjects->BVH();
337
338   Standard_Integer aNode = 0;
339   if (!mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (0),
340                                       anObjectsTree->MaxPoint (0)))
341   {
342     return;
343   }
344   Standard_Integer aStack[32];
345   Standard_Integer aHead = -1;
346   for (;;)
347   {
348     if (!anObjectsTree->IsOuter (aNode))
349     {
350       const Standard_Integer aLeftChildIdx  = anObjectsTree->LeftChild  (aNode);
351       const Standard_Integer aRightChildIdx = anObjectsTree->RightChild (aNode);
352       const Standard_Boolean isLeftChildIn  =
353         mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aLeftChildIdx),
354                                        anObjectsTree->MaxPoint (aLeftChildIdx));
355       const Standard_Boolean isRightChildIn =
356         mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aRightChildIdx),
357                                        anObjectsTree->MaxPoint (aRightChildIdx));
358       if (isLeftChildIn
359         && isRightChildIn)
360       {
361         aNode = aLeftChildIdx;
362         ++aHead;
363         aStack[aHead] = aRightChildIdx;
364       }
365       else if (isLeftChildIn
366         || isRightChildIn)
367       {
368         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
369       }
370       else
371       {
372         if (aHead < 0)
373         {
374           break;
375         }
376
377         aNode = aStack[aHead];
378         --aHead;
379       }
380     }
381     else
382     {
383       Standard_Integer aStartIdx = anObjectsTree->BegPrimitive (aNode);
384       Standard_Integer anEndIdx = anObjectsTree->EndPrimitive (aNode);
385       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
386       {
387         traverseObject (mySelectableObjects->GetObjectById (anIdx));
388       }
389       if (aHead < 0)
390       {
391         break;
392       }
393
394       aNode = aStack[aHead];
395       --aHead;
396     }
397   }
398
399   SortResult();
400
401   if (SelectDebugModeOnVS())
402   {
403     cout<<"\tSelectMgr_VS:: Resultat du move"<<endl;
404     cout<<"\tNb Detectes :"<<mystored.Extent()<<endl;
405
406     for(Standard_Integer i=1; i<=mystored.Extent(); i++)
407     {
408       const SelectMgr_SortCriterion& Crit = mystored (myIndexes->Value(i));
409       cout << "\t" << i << " - Prior" << Crit.Priority()
410            << " - prof :" << Crit.Depth()
411            << "  - Dist. :" << Crit.MinDist() << endl;
412     }
413   }
414 }
415
416 //==================================================
417 // Function: Picked
418 // Purpose :
419 //==================================================
420 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
421 ::Picked() const
422 {
423   Standard_Integer RankInMap = myIndexes->Value (myCurRank);
424   const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
425   Handle(SelectMgr_EntityOwner) Ownr = *((Handle(SelectMgr_EntityOwner)*) &toto);
426   return Ownr;
427 }
428
429
430
431 //=======================================================================
432 //function : More
433 //purpose  :
434 //=======================================================================
435 Standard_Boolean SelectMgr_ViewerSelector::More()
436 {
437   if(mystored.Extent()==0) return Standard_False;
438   if(myCurRank==0) return Standard_False;
439   return myCurRank <= myIndexes->Length();
440 }
441
442 //==================================================
443 // Function: OnePicked
444 // Purpose : only the best one is chosen
445 //           depend on priority and mindist...
446 //==================================================
447
448 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
449 ::OnePicked()
450 {
451
452   Init();
453   if(More()){
454     Standard_Integer RankInMap = myIndexes->Value (myIndexes->Lower());
455     const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
456     Handle(SelectMgr_EntityOwner) Ownr = *((Handle(SelectMgr_EntityOwner)*) &toto);
457     return Ownr;
458   }
459
460   Handle (SelectMgr_EntityOwner) NullObj; //returns a null Handle if there was not successfull pick...
461   return NullObj;
462 }
463
464
465 //=======================================================================
466 //function : NbPicked
467 //purpose  :
468 //=======================================================================
469
470 Standard_Integer SelectMgr_ViewerSelector::NbPicked() const
471 {
472   return mystored.Extent();
473 }
474 //=======================================================================
475 //function : Picked
476 //purpose  :
477 //=======================================================================
478 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_Integer aRank) const
479 {
480
481   Handle(SelectMgr_EntityOwner) anOwner;
482   if (aRank < 1 || aRank > NbPicked())
483     return anOwner;
484   Standard_Integer anOwnerIdx = myIndexes->Value (aRank);
485
486
487   const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
488   anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
489   return anOwner;
490 }
491
492 //===================================================
493 //
494 //       INTERNAL METHODS ....
495 //
496 //==================================================
497
498 //==================================================
499 // Function: Contains
500 // Purpose :
501 //==================================================
502 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
503 {
504   return mySelectableObjects->Contains (theObject);
505 }
506
507 //==================================================
508 // Function: ActiveModes
509 // Purpose : return all the  modes with a given state for an object
510 //==================================================
511 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
512                                                   TColStd_ListOfInteger& theModeList,
513                                                   const SelectMgr_StateOfSelection theWantedState) const
514 {
515   Standard_Boolean hasActivatedStates = mySelectableObjects->Contains (theSelectableObject);
516   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
517   {
518       if (theWantedState == SelectMgr_SOS_Any)
519       {
520         theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
521       }
522       else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
523       {
524         theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
525       }
526   }
527
528   return hasActivatedStates;
529 }
530
531 //==================================================
532 // Function: IsActive
533 // Purpose :
534 //==================================================
535 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
536                                                      const Standard_Integer theMode) const
537 {
538   if (!mySelectableObjects->Contains (theSelectableObject))
539     return Standard_False;
540
541   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
542   {
543     if (theMode == theSelectableObject->CurrentSelection()->Mode())
544     {
545       return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated;
546     }
547   }
548
549   return Standard_False;
550 }
551
552 //==================================================
553 // Function: IsInside
554 // Purpose :
555 //==================================================
556 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
557                                                      const Standard_Integer theMode) const
558 {
559   if (!mySelectableObjects->Contains (theSelectableObject))
560     return Standard_False;
561
562   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
563   {
564     if (theMode == theSelectableObject->CurrentSelection()->Mode())
565     {
566       return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
567     }
568   }
569
570   return Standard_False;
571 }
572
573
574 //=======================================================================
575 //function : Status
576 //purpose  :
577 //=======================================================================
578
579 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
580 {
581   return theSelection->GetSelectionState();
582 }
583
584 //==================================================
585 // Function: Status
586 // Purpose : gives Information about selectors
587 //==================================================
588
589 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
590 {
591   TCollection_AsciiString aStatus ("Status Object :\n\t");
592
593   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
594   {
595     if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
596     {
597       aStatus = aStatus + "Mode " +
598         TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
599         " present - ";
600       if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
601       {
602         aStatus = aStatus + " Active \n\t";
603       }
604       else
605       {
606         aStatus = aStatus + " Inactive \n\t";
607       }
608     }
609   }
610
611   if (mySelectableObjects->Contains (theSelectableObject))
612   {
613     aStatus = aStatus + "Not Present in the selector\n\n";
614   }
615
616   return aStatus;
617 }
618
619 //=======================================================================
620 //function : SortResult
621 //purpose  :  there is a certain number of entities ranged by criteria
622 //            (depth, size, priority, mouse distance from borders or
623 //            CDG of the detected primitive. Parsing :
624 //             maximum priorities .
625 //             then a reasonable compromise between depth and distance...
626 // finally the ranges are stored in myindexes depending on the parsing.
627 // so, it is possible to only read
628 //=======================================================================
629 void SelectMgr_ViewerSelector::SortResult()
630 {
631   if(mystored.IsEmpty()) return;
632
633   const Standard_Integer anExtent = mystored.Extent();
634   if(myIndexes.IsNull() || anExtent != myIndexes->Length())
635     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
636
637   // to work faster...
638   TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
639
640   // indices from 1 to N are loaded
641   Standard_Integer I ;
642   for (I=1; I <= anExtent; I++)
643     thearr(I)=I;
644
645   SortTools_QuickSortOfInteger::Sort (thearr,
646     SelectMgr_CompareResults(mystored));
647 }
648
649 //=======================================================================
650 //function : HasDepthClipping
651 //purpose  : Stub
652 //=======================================================================
653 Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
654 {
655   return Standard_False;
656 }
657
658 //=======================================================================
659 // function : AddSelectableObject
660 // purpose  : Adds new object to the map of selectable objects
661 //=======================================================================
662 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
663 {
664   if (!myMapOfObjectSensitives.IsBound (theObject))
665   {
666     mySelectableObjects->Append (theObject);
667     NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
668     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
669   }
670 }
671
672 //=======================================================================
673 // function : AddSelectionToObject
674 // purpose  : Adds new selection to the object and builds its BVH tree
675 //=======================================================================
676 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
677                                                      const Handle(SelectMgr_Selection)& theSelection)
678 {
679   if (myMapOfObjectSensitives.IsBound (theObject))
680   {
681     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
682       myMapOfObjectSensitives.ChangeFind (theObject);
683     anEntitySet->Append (theSelection);
684     anEntitySet->BVH();
685   }
686   else
687   {
688     AddSelectableObject (theObject);
689     AddSelectionToObject (theObject, theSelection);
690   }
691 }
692
693 //=======================================================================
694 // function : RemoveSelectableObject
695 // purpose  : Removes selectable object from map of selectable ones
696 //=======================================================================
697 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
698 {
699   if (myMapOfObjectSensitives.IsBound (theObject))
700   {
701     myMapOfObjectSensitives.UnBind (theObject);
702     mySelectableObjects->Remove (theObject);
703   }
704 }
705
706 //=======================================================================
707 // function : RemoveSelectionOfObject
708 // purpose  : Removes selection of the object and marks its BVH tree
709 //            for rebuild
710 //=======================================================================
711 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
712                                                         const Handle(SelectMgr_Selection)& theSelection)
713 {
714   if (myMapOfObjectSensitives.IsBound (theObject))
715   {
716     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
717       myMapOfObjectSensitives.ChangeFind (theObject);
718     anEntitySet->Remove (theSelection);
719   }
720 }
721
722 //=======================================================================
723 // function : RebuildObjectsTree
724 // purpose  : Marks BVH of selectable objects for rebuild
725 //=======================================================================
726 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
727 {
728   mySelectableObjects->MarkDirty();
729
730   if (theIsForce)
731   {
732     mySelectableObjects->BVH();
733   }
734 }
735
736 //=======================================================================
737 // function : RebuildSensitivesTree
738 // purpose  : Marks BVH of sensitive entities of particular selectable
739 //            object for rebuild
740 //=======================================================================
741 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
742                                                       const Standard_Boolean theIsForce)
743 {
744   if (!mySelectableObjects->Contains (theObject))
745     return;
746
747   NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
748   anEntitySet->MarkDirty();
749
750   if (theIsForce)
751   {
752     anEntitySet->BVH();
753   }
754 }
755
756 //=======================================================================
757 // function : resetSelectionActivationStatus
758 // purpose  : Marks all added sensitive entities of all objects as
759 //            non-selectable
760 //=======================================================================
761 void SelectMgr_ViewerSelector::resetSelectionActivationStatus()
762 {
763   SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
764   for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
765   {
766     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
767       aSensitivesIter.ChangeValue();
768     Standard_Integer anEntitiesNb = anEntitySet->Size();
769     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
770     {
771       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
772     }
773   }
774 }
775
776 //=======================================================================
777 // function : DetectedEntity
778 // purpose  : Returns sensitive entity that was detected during the
779 //            previous run of selection algorithm
780 //=======================================================================
781 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
782 {
783   const Handle(SelectMgr_EntityOwner)& anOwner = myDetectedIter.Key();
784   const Handle(SelectMgr_SelectableObject)& anObject = anOwner->Selectable();
785   const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
786     myMapOfObjectSensitives.Find (anObject);
787
788   return anEntitySet->GetSensitiveById (myDetectedIter.Value())->BaseSensitive();
789 }
790
791 //=======================================================================
792 // function : ActiveOwners
793 // purpose  : Returns the list of active entity owners
794 //=======================================================================
795 NCollection_List<Handle(SelectBasics_EntityOwner)> SelectMgr_ViewerSelector::ActiveOwners() const
796 {
797   NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
798   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
799   {
800     const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
801     Standard_Integer anEntitiesNb = anEntitySet->Size();
802     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
803     {
804       if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
805       {
806         anActiveOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
807       }
808     }
809   }
810
811   return anActiveOwners;
812 }