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