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