0f162e9079cb7e8b8e20dd962d452a64882adbc5
[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 #include <SelectMgr_ViewerSelector.hxx>
18
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
21 #include <gp_Pnt.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <SelectBasics_EntityOwner.hxx>
25 #include <SelectBasics_SensitiveEntity.hxx>
26 #include <SelectBasics_PickResult.hxx>
27 #include <SelectMgr_EntityOwner.hxx>
28 #include <SelectMgr_SortCriterion.hxx>
29 #include <SelectMgr_SensitiveEntitySet.hxx>
30 #include <TColStd_Array1OfInteger.hxx>
31 #include <TCollection_AsciiString.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColStd_ListOfInteger.hxx>
34
35 #include <algorithm>
36
37 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector,MMgt_TShared)
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   //! Compute 3d position for detected entity.
63   inline void updatePoint3d (SelectMgr_SortCriterion& theCriterion,
64                              const gp_GTrsf& theInversedTrsf,
65                              SelectMgr_SelectingVolumeManager& theMgr)
66   {
67     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
68     gp_GTrsf anInvTrsf = theInversedTrsf;
69     if (theCriterion.Entity->HasInitLocation())
70     {
71       anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
72     }
73     if (anInvTrsf.Form() != gp_Identity)
74     {
75       anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
76     }
77   }
78
79   static const Graphic3d_Mat4d THE_IDENTITY_MAT;
80 }
81
82 //==================================================
83 // Function: Initialize
84 // Purpose :
85 //==================================================
86 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
87 preferclosest(Standard_True),
88 myToUpdateTolerance (Standard_True),
89 myCurRank (0),
90 myIsLeftChildQueuedFirst (Standard_False),
91 myEntityIdx (0)
92 {
93 }
94
95 //==================================================
96 // Function: Activate
97 // Purpose :
98 //==================================================
99 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
100 {
101   for (theSelection->Init(); theSelection->More(); theSelection->Next())
102   {
103     theSelection->Sensitive()->SetActiveForSelection();
104   }
105
106   theSelection->SetSelectionState (SelectMgr_SOS_Activated);
107
108   myTolerances.Add (theSelection->Sensitivity());
109   myToUpdateTolerance = Standard_True;
110 }
111
112 //==================================================
113 // Function: Deactivate
114 // Purpose :
115 //==================================================
116 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
117 {
118   for (theSelection->Init(); theSelection->More(); theSelection->Next())
119   {
120     theSelection->Sensitive()->ResetSelectionActiveStatus();
121   }
122
123   theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
124
125   myTolerances.Decrement (theSelection->Sensitivity());
126   myToUpdateTolerance = Standard_True;
127 }
128
129 //==================================================
130 // Function: Clear
131 // Purpose :
132 //==================================================
133 void SelectMgr_ViewerSelector::Clear()
134 {
135   mystored.Clear();
136 }
137
138 //=======================================================================
139 // function: isToScaleFrustum
140 // purpose : Checks if the entity given requires to scale current selecting frustum
141 //=======================================================================
142 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
143 {
144   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
145     && sensitivity (theEntity) < myTolerances.Tolerance();
146 }
147
148 //=======================================================================
149 // function: sensitivity
150 // purpose : In case if custom tolerance is set, this method will return sum of entity
151 //           sensitivity and custom tolerance.
152 //=======================================================================
153 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
154 {
155   return myTolerances.IsCustomTolSet() ?
156     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
157 }
158
159 //=======================================================================
160 // function: checkOverlap
161 // purpose : Internal function that checks if a particular sensitive
162 //           entity theEntity overlaps current selecting volume precisely
163 //=======================================================================
164 void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
165                                              const gp_GTrsf& theInversedTrsf,
166                                              SelectMgr_SelectingVolumeManager& theMgr)
167 {
168   Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
169   Handle(SelectMgr_SelectableObject) aSelectable;
170   Standard_Boolean toRestoresViewClipEnabled = Standard_False;
171   if (!anOwner.IsNull())
172   {
173     aSelectable = anOwner->Selectable();
174     if (aSelectable->TransformPersistence().Flags == Graphic3d_TMF_TriedronPers
175      || aSelectable->TransformPersistence().Flags == Graphic3d_TMF_2d
176      || (!aSelectable->ClipPlanes().IsNull() && aSelectable->ClipPlanes()->ToOverrideGlobal()))
177     {
178       theMgr.SetViewClippingEnabled (Standard_False);
179       toRestoresViewClipEnabled = Standard_True;
180     }
181   }
182
183   SelectBasics_PickResult aPickResult;
184   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
185   if (toRestoresViewClipEnabled)
186   {
187     theMgr.SetViewClippingEnabled (Standard_True);
188   }
189
190   if (!isMatched
191     || anOwner.IsNull())
192   {
193     return;
194   }
195
196   if (HasDepthClipping (anOwner)
197   &&  theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
198   {
199     Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
200                                                                   aPickResult.Depth());
201     if (isClipped)
202       return;
203   }
204
205   SelectMgr_SortCriterion aCriterion;
206   myZLayerOrderMap.Find (aSelectable->ZLayer(), aCriterion.ZLayerPosition);
207   aCriterion.Entity    = theEntity;
208   aCriterion.Priority  = anOwner->Priority();
209   aCriterion.Depth     = aPickResult.Depth();
210   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
211   aCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
212   aCriterion.ToPreferClosest = preferclosest;
213
214   const Standard_Integer aPrevStoredIndex = mystored.FindIndex (anOwner);
215   if (aPrevStoredIndex != 0)
216   {
217     if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
218     {
219       SelectMgr_SortCriterion& aPrevCriterion = mystored.ChangeFromIndex (aPrevStoredIndex);
220       if (aCriterion > aPrevCriterion)
221       {
222         updatePoint3d (aCriterion, theInversedTrsf, theMgr);
223         aPrevCriterion = aCriterion;
224       }
225     }
226   }
227   else
228   {
229     updatePoint3d (aCriterion, theInversedTrsf, theMgr);
230     mystored.Add (anOwner, aCriterion);
231   }
232 }
233
234 //=======================================================================
235 // function: computeFrustum
236 // purpose : Internal function that checks if a current selecting frustum
237 //           needs to be scaled and transformed for the entity and performs
238 //           necessary calculations
239 //=======================================================================
240 void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt,
241                                                const SelectMgr_SelectingVolumeManager&     theMgr,
242                                                const gp_GTrsf&                             theInvTrsf,
243                                                SelectMgr_FrustumCache&                     theCachedMgrs,
244                                                SelectMgr_SelectingVolumeManager&           theResMgr)
245 {
246   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
247   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
248   const Standard_Boolean toScale = aScale != 1;
249   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
250   if (toScale && toTransform)
251   {
252     theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
253   }
254   else if (toScale)
255   {
256     if (!theCachedMgrs.IsBound (aScale))
257     {
258       theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
259     }
260     theResMgr = theCachedMgrs.Find (aScale);
261   }
262   else if (toTransform)
263   {
264     theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
265   }
266 }
267
268 //=======================================================================
269 // function: traverseObject
270 // purpose : Internal function that checks if there is possible overlap
271 //           between some entity of selectable object theObject and
272 //           current selecting volume
273 //=======================================================================
274 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
275                                                const SelectMgr_SelectingVolumeManager& theMgr,
276                                                const Handle(Graphic3d_Camera)& theCamera,
277                                                const Graphic3d_Mat4d& theProjectionMat,
278                                                const Graphic3d_Mat4d& theWorldViewMat,
279                                                const Standard_Integer theViewportWidth,
280                                                const Standard_Integer theViewportHeight)
281 {
282   NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
283     myMapOfObjectSensitives.ChangeFind (theObject);
284
285   if (anEntitySet->Size() == 0)
286     return;
287
288   const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
289
290   gp_GTrsf aInversedTrsf;
291
292   if (theObject->HasTransformation() || theObject->TransformPersistence().Flags)
293   {
294     if (!theObject->TransformPersistence().Flags)
295     {
296       aInversedTrsf = theObject->InversedTransformation();
297     }
298     else
299     {
300       gp_GTrsf aTPers;
301       Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (
302         theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
303
304       aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
305       aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
306       aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
307       aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
308       aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
309       aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
310       aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
311       aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
312       aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
313       aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
314
315       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
316     }
317   }
318
319   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
320                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
321                                         : theMgr;
322
323   SelectMgr_FrustumCache aScaledTrnsfFrustums;
324
325   Standard_Integer aNode = 0; // a root node
326   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
327                       aSensitivesTree->MaxPoint (0)))
328   {
329     return;
330   }
331   Standard_Integer aStack[32];
332   Standard_Integer aHead = -1;
333   for (;;)
334   {
335     if (!aSensitivesTree->IsOuter (aNode))
336     {
337       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
338       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
339       const Standard_Boolean isLeftChildIn  =  aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
340                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
341       const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
342                                                              aSensitivesTree->MaxPoint (aRightChildIdx));
343       if (isLeftChildIn
344           && isRightChildIn)
345       {
346         aNode = aLeftChildIdx;
347         ++aHead;
348         aStack[aHead] = aRightChildIdx;
349       }
350       else if (isLeftChildIn
351         || isRightChildIn)
352       {
353         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
354       }
355       else
356       {
357         if (aHead < 0)
358         {
359           break;
360         }
361
362         aNode = aStack[aHead];
363         --aHead;
364       }
365     }
366     else
367     {
368       Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
369       Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
370       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
371       {
372         const Handle(SelectMgr_SensitiveEntity)& aSensitive =
373           anEntitySet->GetSensitiveById (anIdx);
374         if (aSensitive->IsActiveForSelection())
375         {
376           const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
377           SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
378           computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
379           checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
380         }
381       }
382       if (aHead < 0)
383       {
384         break;
385       }
386
387       aNode = aStack[aHead];
388       --aHead;
389     }
390   }
391 }
392
393 //=======================================================================
394 // function: TraverseSensitives
395 // purpose : Traverses BVH containing all added selectable objects and
396 //           finds candidates for further search of overlap
397 //=======================================================================
398 void SelectMgr_ViewerSelector::TraverseSensitives()
399 {
400   mystored.Clear();
401
402   Standard_Integer aWidth;
403   Standard_Integer aHeight;
404   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
405   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
406                                  mySelectingVolumeMgr.ProjectionMatrix(),
407                                  mySelectingVolumeMgr.WorldViewMatrix(),
408                                  mySelectingVolumeMgr.WorldViewProjState(),
409                                  aWidth, aHeight);
410
411   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
412   {
413     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
414       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
415
416     if (mySelectableObjects.IsEmpty (aBVHSubset))
417     {
418       continue;
419     }
420
421     gp_GTrsf aTFrustum;
422
423     SelectMgr_SelectingVolumeManager aMgr (Standard_False);
424
425     // for 2D space selection transform selecting volumes to perform overap testing
426     // directly in camera's eye space omitting the camera position, which is not
427     // needed there at all
428     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
429     {
430       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
431       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
432       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
433       aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
434       aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
435       aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
436       aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
437       aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
438       aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
439       aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
440       aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
441
442       // define corresponding frustum builder parameters
443       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
444       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
445       aBuilder->SetWorldViewMatrix (THE_IDENTITY_MAT);
446       aBuilder->SetWindowSize (aWidth, aHeight);
447       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
448     }
449     else
450     {
451       aMgr = mySelectingVolumeMgr;
452     }
453
454     const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
455     const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
456     const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
457                                             ? mySelectingVolumeMgr.WorldViewMatrix()
458                                             : THE_IDENTITY_MAT;
459
460     const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
461
462     Standard_Integer aNode = 0;
463     if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
464     {
465       continue;
466     }
467
468     Standard_Integer aStack[32];
469     Standard_Integer aHead = -1;
470     for (;;)
471     {
472       if (!aBVHTree->IsOuter (aNode))
473       {
474         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
475         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
476         const Standard_Boolean isLeftChildIn  =
477           aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
478         const Standard_Boolean isRightChildIn =
479           aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
480         if (isLeftChildIn
481           && isRightChildIn)
482         {
483           aNode = aLeftChildIdx;
484           ++aHead;
485           aStack[aHead] = aRightChildIdx;
486         }
487         else if (isLeftChildIn
488           || isRightChildIn)
489         {
490           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
491         }
492         else
493         {
494           if (aHead < 0)
495           {
496             break;
497           }
498
499           aNode = aStack[aHead];
500           --aHead;
501         }
502       }
503       else
504       {
505         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
506         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
507         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
508         {
509           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
510             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
511
512           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
513         }
514         if (aHead < 0)
515         {
516           break;
517         }
518
519         aNode = aStack[aHead];
520         --aHead;
521       }
522     }
523   }
524
525   SortResult();
526 }
527
528 //==================================================
529 // Function: Picked
530 // Purpose :
531 //==================================================
532 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
533 ::Picked() const
534 {
535   Standard_Integer RankInMap = myIndexes->Value (myCurRank);
536   const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
537   Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
538   return Ownr;
539 }
540
541 //=======================================================================
542 //function : Picked
543 //purpose  :
544 //=======================================================================
545 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
546 {
547   Handle(SelectMgr_EntityOwner) anOwner;
548   if (theRank < 1 || theRank > NbPicked())
549   {
550     return anOwner;
551   }
552
553   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
554   const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
555   anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
556   return anOwner;
557 }
558
559 //=======================================================================
560 //function : PickedData
561 //purpose  :
562 //=======================================================================
563 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
564 {
565   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
566   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
567   return mystored.FindFromIndex (anOwnerIdx);
568 }
569
570 //===================================================
571 //
572 //       INTERNAL METHODS ....
573 //
574 //==================================================
575
576 //==================================================
577 // Function: Contains
578 // Purpose :
579 //==================================================
580 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
581 {
582   return mySelectableObjects.Contains (theObject);
583 }
584
585 //==================================================
586 // Function: ActiveModes
587 // Purpose : return all the  modes with a given state for an object
588 //==================================================
589 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
590                                                   TColStd_ListOfInteger& theModeList,
591                                                   const SelectMgr_StateOfSelection theWantedState) const
592 {
593   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
594   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
595   {
596       if (theWantedState == SelectMgr_SOS_Any)
597       {
598         theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
599       }
600       else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
601       {
602         theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
603       }
604   }
605
606   return hasActivatedStates;
607 }
608
609 //==================================================
610 // Function: IsActive
611 // Purpose :
612 //==================================================
613 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
614                                                      const Standard_Integer theMode) const
615 {
616   if (!Contains (theSelectableObject))
617     return Standard_False;
618
619   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
620   {
621     if (theMode == theSelectableObject->CurrentSelection()->Mode())
622     {
623       return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated;
624     }
625   }
626
627   return Standard_False;
628 }
629
630 //==================================================
631 // Function: IsInside
632 // Purpose :
633 //==================================================
634 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
635                                                      const Standard_Integer theMode) const
636 {
637   if (!Contains (theSelectableObject))
638     return Standard_False;
639
640   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
641   {
642     if (theMode == theSelectableObject->CurrentSelection()->Mode())
643     {
644       return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
645     }
646   }
647
648   return Standard_False;
649 }
650
651
652 //=======================================================================
653 //function : Status
654 //purpose  :
655 //=======================================================================
656
657 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
658 {
659   return theSelection->GetSelectionState();
660 }
661
662 //==================================================
663 // Function: Status
664 // Purpose : gives Information about selectors
665 //==================================================
666
667 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
668 {
669   TCollection_AsciiString aStatus ("Status Object :\n\t");
670
671   for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
672   {
673     if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
674     {
675       aStatus = aStatus + "Mode " +
676         TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
677         " present - ";
678       if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
679       {
680         aStatus = aStatus + " Active \n\t";
681       }
682       else
683       {
684         aStatus = aStatus + " Inactive \n\t";
685       }
686     }
687   }
688
689   if (!Contains (theSelectableObject))
690   {
691     aStatus = aStatus + "Not Present in the selector\n\n";
692   }
693
694   return aStatus;
695 }
696
697 //=======================================================================
698 //function : SortResult
699 //purpose  :  there is a certain number of entities ranged by criteria
700 //            (depth, size, priority, mouse distance from borders or
701 //            CDG of the detected primitive. Parsing :
702 //             maximum priorities .
703 //             then a reasonable compromise between depth and distance...
704 // finally the ranges are stored in myindexes depending on the parsing.
705 // so, it is possible to only read
706 //=======================================================================
707 void SelectMgr_ViewerSelector::SortResult()
708 {
709   if(mystored.IsEmpty()) return;
710
711   const Standard_Integer anExtent = mystored.Extent();
712   if(myIndexes.IsNull() || anExtent != myIndexes->Length())
713     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
714
715   // to work faster...
716   TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
717
718   // indices from 1 to N are loaded
719   Standard_Integer I ;
720   for (I=1; I <= anExtent; I++)
721     thearr(I)=I;
722
723   std::sort (thearr.begin(), thearr.end(), CompareResults (mystored));
724
725 }
726
727 //=======================================================================
728 //function : HasDepthClipping
729 //purpose  : Stub
730 //=======================================================================
731 Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
732 {
733   return Standard_False;
734 }
735
736 //=======================================================================
737 // function : AddSelectableObject
738 // purpose  : Adds new object to the map of selectable objects
739 //=======================================================================
740 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
741 {
742   if (!myMapOfObjectSensitives.IsBound (theObject))
743   {
744     mySelectableObjects.Append (theObject);
745     NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
746     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
747   }
748 }
749
750 //=======================================================================
751 // function : AddSelectionToObject
752 // purpose  : Adds new selection to the object and builds its BVH tree
753 //=======================================================================
754 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
755                                                      const Handle(SelectMgr_Selection)& theSelection)
756 {
757   if (myMapOfObjectSensitives.IsBound (theObject))
758   {
759     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
760       myMapOfObjectSensitives.ChangeFind (theObject);
761     anEntitySet->Append (theSelection);
762     anEntitySet->BVH();
763   }
764   else
765   {
766     AddSelectableObject (theObject);
767     AddSelectionToObject (theObject, theSelection);
768   }
769 }
770
771 //=======================================================================
772 // function : MoveSelectableObject
773 // purpose  :
774 //=======================================================================
775 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
776 {
777   mySelectableObjects.ChangeSubset (theObject);
778 }
779
780 //=======================================================================
781 // function : RemoveSelectableObject
782 // purpose  : Removes selectable object from map of selectable ones
783 //=======================================================================
784 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
785 {
786   if (myMapOfObjectSensitives.IsBound (theObject))
787   {
788     mySelectableObjects.Remove (theObject);
789     myMapOfObjectSensitives.UnBind (theObject);
790   }
791 }
792
793 //=======================================================================
794 // function : RemoveSelectionOfObject
795 // purpose  : Removes selection of the object and marks its BVH tree
796 //            for rebuild
797 //=======================================================================
798 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
799                                                         const Handle(SelectMgr_Selection)& theSelection)
800 {
801   if (myMapOfObjectSensitives.IsBound (theObject))
802   {
803     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
804       myMapOfObjectSensitives.ChangeFind (theObject);
805     anEntitySet->Remove (theSelection);
806   }
807 }
808
809 //=======================================================================
810 // function : RebuildObjectsTree
811 // purpose  : Marks BVH of selectable objects for rebuild
812 //=======================================================================
813 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
814 {
815   mySelectableObjects.MarkDirty();
816
817   if (theIsForce)
818   {
819     Standard_Integer aViewportWidth, aViewportHeight;
820     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
821
822     Standard_Integer aWidth;
823     Standard_Integer aHeight;
824     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
825     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
826                                    mySelectingVolumeMgr.ProjectionMatrix(),
827                                    mySelectingVolumeMgr.WorldViewMatrix(),
828                                    mySelectingVolumeMgr.WorldViewProjState(),
829                                    aWidth, aHeight);
830   }
831 }
832
833 //=======================================================================
834 // function : RebuildSensitivesTree
835 // purpose  : Marks BVH of sensitive entities of particular selectable
836 //            object for rebuild
837 //=======================================================================
838 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
839                                                       const Standard_Boolean theIsForce)
840 {
841   if (!Contains (theObject))
842     return;
843
844   NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
845   anEntitySet->MarkDirty();
846
847   if (theIsForce)
848   {
849     anEntitySet->BVH();
850   }
851 }
852
853 //=======================================================================
854 // function : resetSelectionActivationStatus
855 // purpose  : Marks all added sensitive entities of all objects as
856 //            non-selectable
857 //=======================================================================
858 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
859 {
860   SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
861   for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
862   {
863     NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
864       aSensitivesIter.ChangeValue();
865     Standard_Integer anEntitiesNb = anEntitySet->Size();
866     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
867     {
868       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
869     }
870   }
871 }
872
873 //=======================================================================
874 // function : DetectedEntity
875 // purpose  : Returns sensitive entity that was detected during the
876 //            previous run of selection algorithm
877 //=======================================================================
878 const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
879 {
880   const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
881   return mystored.FindFromIndex (aRankInMap).Entity;
882 }
883
884 //=======================================================================
885 // function : ActiveOwners
886 // purpose  : Returns the list of active entity owners
887 //=======================================================================
888 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
889 {
890   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
891   {
892     const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
893     Standard_Integer anEntitiesNb = anEntitySet->Size();
894     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
895     {
896       if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
897       {
898         theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
899       }
900     }
901   }
902 }
903
904 //=======================================================================
905 //function : AllowOverlapDetection
906 //purpose  : Sets the detection type: if theIsToAllow is false,
907 //           only fully included sensitives will be detected, otherwise
908 //           the algorithm will mark both included and overlapped entities
909 //           as matched
910 //=======================================================================
911 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
912 {
913   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
914 }