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