0031458: Visualization - refine classes across Prs3d and StdPrs packages
[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 <Select3D_SensitiveEntity.hxx>
25 #include <SelectBasics_PickResult.hxx>
26 #include <SelectMgr_EntityOwner.hxx>
27 #include <SelectMgr_SortCriterion.hxx>
28 #include <SelectMgr_SensitiveEntitySet.hxx>
29 #include <TColStd_Array1OfInteger.hxx>
30 #include <TCollection_AsciiString.hxx>
31 #include <TColStd_HArray1OfInteger.hxx>
32 #include <TColStd_ListOfInteger.hxx>
33
34 #include <algorithm>
35
36 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
37
38 namespace {
39   // Comparison operator for sorting selection results
40   class CompareResults
41   {
42   public:
43    
44     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
45       : myMapOfCriterion (aMapOfCriterion)
46     {
47     }
48
49     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
50     {
51       return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
52     }
53
54   private:
55     void operator = (const CompareResults&);
56
57   private:
58     const SelectMgr_IndexedDataMapOfOwnerCriterion&  myMapOfCriterion;
59   };
60
61   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
62 }
63
64 //=======================================================================
65 // function : updatePoint3d
66 // purpose  :
67 //=======================================================================
68 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
69                                               const SelectBasics_PickResult& thePickResult,
70                                               const Handle(Select3D_SensitiveEntity)& theEntity,
71                                               const gp_GTrsf& theInversedTrsf,
72                                               const SelectMgr_SelectingVolumeManager& theMgr) const
73 {
74   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
75   {
76     return;
77   }
78
79   if (thePickResult.HasPickedPoint())
80   {
81     theCriterion.Point = thePickResult.PickedPoint();
82   }
83   else if (!thePickResult.IsValid())
84   {
85     theCriterion.Point = thePickResult.PickedPoint();
86     return;
87   }
88   else
89   {
90     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
91   }
92
93   gp_GTrsf anInvTrsf = theInversedTrsf;
94   if (theCriterion.Entity->HasInitLocation())
95   {
96     anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
97   }
98   if (anInvTrsf.Form() != gp_Identity)
99   {
100     anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
101   }
102
103   if (mySelectingVolumeMgr.Camera().IsNull())
104   {
105     theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
106   }
107   else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
108   {
109     theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
110   }
111   else
112   {
113     const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
114     theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
115   }
116 }
117
118 //==================================================
119 // Function: Initialize
120 // Purpose :
121 //==================================================
122 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
123 preferclosest(Standard_True),
124 myToUpdateTolerance (Standard_True),
125 myCameraScale (1.0),
126 myCurRank (0),
127 myIsLeftChildQueuedFirst (Standard_False),
128 myEntityIdx (0)
129 {
130   myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
131 }
132
133 //=======================================================================
134 // Function: SetPixelTolerance
135 // Purpose :
136 //=======================================================================
137 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
138 {
139   if (myTolerances.Tolerance() == theTolerance)
140   {
141     return;
142   }
143
144   myToUpdateTolerance = Standard_True;
145   if (theTolerance < 0)
146   {
147     myTolerances.ResetDefaults();
148   }
149   else
150   {
151     myTolerances.SetCustomTolerance (theTolerance);
152   }
153 }
154
155 //==================================================
156 // Function: Activate
157 // Purpose :
158 //==================================================
159 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
160 {
161   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
162   {
163     aSelEntIter.Value()->SetActiveForSelection();
164   }
165
166   if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
167   {
168     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
169
170     myTolerances.Add (theSelection->Sensitivity());
171     myToUpdateTolerance = Standard_True;
172   }
173 }
174
175 //==================================================
176 // Function: Deactivate
177 // Purpose :
178 //==================================================
179 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
180 {
181   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
182   {
183     aSelEntIter.Value()->ResetSelectionActiveStatus();
184   }
185
186   if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
187   {
188     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
189
190     myTolerances.Decrement (theSelection->Sensitivity());
191     myToUpdateTolerance = Standard_True;
192   }
193 }
194
195 //==================================================
196 // Function: Clear
197 // Purpose :
198 //==================================================
199 void SelectMgr_ViewerSelector::Clear()
200 {
201   mystored.Clear();
202 }
203
204 //=======================================================================
205 // function: isToScaleFrustum
206 // purpose : Checks if the entity given requires to scale current selecting frustum
207 //=======================================================================
208 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
209 {
210   return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
211     && sensitivity (theEntity) < myTolerances.Tolerance();
212 }
213
214 //=======================================================================
215 // function: sensitivity
216 // purpose : In case if custom tolerance is set, this method will return sum of entity
217 //           sensitivity and custom tolerance.
218 //=======================================================================
219 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
220 {
221   return myTolerances.IsCustomTolSet() ?
222     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
223 }
224
225 //=======================================================================
226 // function: checkOverlap
227 // purpose : Internal function that checks if a particular sensitive
228 //           entity theEntity overlaps current selecting volume precisely
229 //=======================================================================
230 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
231                                              const gp_GTrsf& theInversedTrsf,
232                                              SelectMgr_SelectingVolumeManager& theMgr)
233 {
234   const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
235   Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
236   SelectBasics_PickResult aPickResult;
237   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
238   if (!isMatched
239     || anOwner.IsNull())
240   {
241     return;
242   }
243
244   SelectMgr_SortCriterion aCriterion;
245   myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
246   aCriterion.Entity    = theEntity;
247   aCriterion.Priority  = anOwner->Priority();
248   aCriterion.Depth     = aPickResult.Depth();
249   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
250   aCriterion.ToPreferClosest = preferclosest;
251
252   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
253   {
254     ++aPrevCriterion->NbOwnerMatches;
255     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
256     if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
257     {
258       if (aCriterion > *aPrevCriterion)
259       {
260         updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
261         *aPrevCriterion = aCriterion;
262       }
263     }
264   }
265   else
266   {
267     aCriterion.NbOwnerMatches = 1;
268     updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
269     mystored.Add (anOwner, aCriterion);
270   }
271 }
272
273 //=======================================================================
274 // function: computeFrustum
275 // purpose :
276 //=======================================================================
277 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
278                                                const SelectMgr_SelectingVolumeManager& theMgrGlobal,
279                                                const SelectMgr_SelectingVolumeManager& theMgrObject,
280                                                const gp_GTrsf& theInvTrsf,
281                                                SelectMgr_FrustumCache& theCachedMgrs,
282                                                SelectMgr_SelectingVolumeManager& theResMgr)
283 {
284   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
285   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
286   const Standard_Boolean toScale = aScale != 1;
287   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
288   if (toScale && toTransform)
289   {
290     theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
291     theResMgr.SetViewClipping (theMgrObject);
292   }
293   else if (toScale)
294   {
295     if (!theCachedMgrs.Find (aScale, theResMgr))
296     {
297       theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
298       theCachedMgrs.Bind (aScale, theResMgr);
299     }
300     theResMgr.SetViewClipping (theMgrObject);
301   }
302   else if (toTransform)
303   {
304     theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
305     theResMgr.SetViewClipping (theMgrObject);
306   }
307   else
308   {
309     theResMgr = theMgrObject;
310   }
311 }
312
313 //=======================================================================
314 // function: traverseObject
315 // purpose : Internal function that checks if there is possible overlap
316 //           between some entity of selectable object theObject and
317 //           current selecting volume
318 //=======================================================================
319 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
320                                                const SelectMgr_SelectingVolumeManager& theMgr,
321                                                const Handle(Graphic3d_Camera)& theCamera,
322                                                const Graphic3d_Mat4d& theProjectionMat,
323                                                const Graphic3d_Mat4d& theWorldViewMat,
324                                                const Standard_Integer theViewportWidth,
325                                                const Standard_Integer theViewportHeight)
326 {
327   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
328   if (anEntitySet->Size() == 0)
329   {
330     return;
331   }
332
333   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
334   gp_GTrsf aInversedTrsf;
335   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
336   {
337     if (theObject->TransformPersistence().IsNull())
338     {
339       aInversedTrsf = theObject->InversedTransformation();
340     }
341     else
342     {
343       gp_GTrsf aTPers;
344       Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
345
346       aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
347       aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
348       aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
349       aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
350       aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
351       aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
352       aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
353       aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
354       aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
355       aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
356
357       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
358     }
359   }
360
361   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
362                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
363                                         : theMgr;
364   if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
365                       aSensitivesTree->MaxPoint (0)))
366   {
367     return;
368   }
369
370   if (!theObject->ClipPlanes().IsNull()
371     && theObject->ClipPlanes()->ToOverrideGlobal())
372   {
373     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
374   }
375   else if (!theObject->TransformPersistence().IsNull())
376   {
377     if (theObject->TransformPersistence()->IsZoomOrRotate()
378     && !theMgr.ViewClipping().IsNull())
379     {
380       // Zoom/rotate persistence object lives in two worlds at the same time.
381       // Global clipping planes can not be trivially applied without being converted
382       // into local space of transformation persistence object.
383       // As more simple alternative - just clip entire object by its anchor point defined in the world space.
384       const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
385       for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
386       {
387         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
388         if (!aPlane->IsOn())
389         {
390           continue;
391         }
392
393         const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
394         if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
395         {
396           return;
397         }
398       }
399     }
400
401     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes());
402   }
403   else if (!theObject->ClipPlanes().IsNull()
404         && !theObject->ClipPlanes()->IsEmpty())
405   {
406     aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes());
407   }
408
409   if (!theMgr.ViewClipping().IsNull() &&
410       theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
411   {
412     Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
413     // If box selection is active, and the whole sensitive tree is out of the clip planes
414     // selection is empty for this object
415     const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
416
417     for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
418     {
419       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
420       if (!aPlane->IsOn())
421       {
422         continue;
423       }
424
425       Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
426       if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
427       {
428         return;
429       }
430     }
431   }
432
433   const Standard_Integer aFirstStored = mystored.Extent() + 1;
434
435   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
436   Standard_Integer aHead = -1;
437   Standard_Integer aNode = 0; // a root node
438   SelectMgr_FrustumCache aScaledTrnsfFrustums;
439   SelectMgr_SelectingVolumeManager aTmpMgr (false);
440   for (;;)
441   {
442     if (!aSensitivesTree->IsOuter (aNode))
443     {
444       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
445       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
446       const Standard_Boolean isLeftChildIn  =  aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
447                                                               aSensitivesTree->MaxPoint (aLeftChildIdx));
448       const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
449                                                              aSensitivesTree->MaxPoint (aRightChildIdx));
450       if (isLeftChildIn
451           && isRightChildIn)
452       {
453         aNode = aLeftChildIdx;
454         ++aHead;
455         aStack[aHead] = aRightChildIdx;
456       }
457       else if (isLeftChildIn
458         || isRightChildIn)
459       {
460         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
461       }
462       else
463       {
464         if (aHead < 0)
465         {
466           break;
467         }
468
469         aNode = aStack[aHead];
470         --aHead;
471       }
472     }
473     else
474     {
475       bool aClipped = false;
476       if (!theMgr.ViewClipping().IsNull() &&
477           theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Box)
478       {
479         Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
480         // If box selection is active, and the whole sensitive tree is out of the clip planes
481         // selection is empty for this object
482         const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
483
484         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
485         {
486           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
487           if (!aPlane->IsOn())
488           {
489             continue;
490           }
491           Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
492           if (aState == Graphic3d_ClipState_Out)
493           {
494             aClipped = true;
495             break;
496           }
497           if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
498           {
499             if (aPlane->ProbeBoxTouch (aBBox))
500               continue;
501             aClipped = true;
502             break;
503           }
504         }
505       }
506       if (!aClipped)
507       {
508         Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
509         Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
510         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
511         {
512           const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
513           if (aSensitive->IsActiveForSelection())
514           {
515             const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
516             computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
517             checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
518           }
519         }
520       }
521       if (aHead < 0)
522       {
523         break;
524       }
525
526       aNode = aStack[aHead];
527       --aHead;
528     }
529   }
530
531   // in case of Box/Polyline selection - keep only Owners having all Entities detected
532   if (mySelectingVolumeMgr.IsOverlapAllowed()
533   || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
534    && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
535   {
536     return;
537   }
538
539   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
540   {
541     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
542     const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
543     Standard_Integer aNbOwnerEntities = 0;
544     for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
545     {
546       if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
547       {
548         if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
549         {
550           // Remove from index map.
551           // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
552           // Hence, just keep iterating in backward direction.
553           mystored.RemoveFromIndex (aStoredIter);
554           break;
555         }
556       }
557     }
558   }
559 }
560
561 //=======================================================================
562 // function: TraverseSensitives
563 // purpose : Traverses BVH containing all added selectable objects and
564 //           finds candidates for further search of overlap
565 //=======================================================================
566 void SelectMgr_ViewerSelector::TraverseSensitives()
567 {
568   mystored.Clear();
569
570   Standard_Integer aWidth;
571   Standard_Integer aHeight;
572   mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
573   mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
574                                  mySelectingVolumeMgr.ProjectionMatrix(),
575                                  mySelectingVolumeMgr.WorldViewMatrix(),
576                                  mySelectingVolumeMgr.WorldViewProjState(),
577                                  aWidth, aHeight);
578   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
579   if (!aCamera.IsNull())
580   {
581     myCameraEye = aCamera->Eye().XYZ();
582     myCameraDir = aCamera->Direction().XYZ();
583     myCameraScale = aCamera->IsOrthographic()
584                   ? aCamera->Scale()
585                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
586     const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
587     myCameraScale *= aPixelSize;
588   }
589
590   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
591   {
592     SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
593       static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
594
595     if (mySelectableObjects.IsEmpty (aBVHSubset))
596     {
597       continue;
598     }
599
600     gp_GTrsf aTFrustum;
601
602     SelectMgr_SelectingVolumeManager aMgr (Standard_False);
603
604     // for 2D space selection transform selecting volumes to perform overap testing
605     // directly in camera's eye space omitting the camera position, which is not
606     // needed there at all
607     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
608     {
609       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
610       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
611       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
612       aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
613       aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
614       aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
615       aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
616       aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
617       aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
618       aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
619       aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
620
621       // define corresponding frustum builder parameters
622       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
623       aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
624       aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
625       aBuilder->SetWindowSize (aWidth, aHeight);
626       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
627     }
628     else
629     {
630       aMgr = mySelectingVolumeMgr;
631     }
632
633     const Graphic3d_Mat4d& aProjectionMat   = mySelectingVolumeMgr.ProjectionMatrix();
634     const Graphic3d_Mat4d& aWorldViewMat    = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
635                                             ? mySelectingVolumeMgr.WorldViewMatrix()
636                                             : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
637
638     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
639
640     Standard_Integer aNode = 0;
641     if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
642     {
643       continue;
644     }
645
646     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
647     Standard_Integer aHead = -1;
648     for (;;)
649     {
650       if (!aBVHTree->IsOuter (aNode))
651       {
652         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
653         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
654         const Standard_Boolean isLeftChildIn  =
655           aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
656         const Standard_Boolean isRightChildIn =
657           aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
658         if (isLeftChildIn
659           && isRightChildIn)
660         {
661           aNode = aLeftChildIdx;
662           ++aHead;
663           aStack[aHead] = aRightChildIdx;
664         }
665         else if (isLeftChildIn
666           || isRightChildIn)
667         {
668           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
669         }
670         else
671         {
672           if (aHead < 0)
673           {
674             break;
675           }
676
677           aNode = aStack[aHead];
678           --aHead;
679         }
680       }
681       else
682       {
683         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
684         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
685         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
686         {
687           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
688             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
689
690           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
691         }
692         if (aHead < 0)
693         {
694           break;
695         }
696
697         aNode = aStack[aHead];
698         --aHead;
699       }
700     }
701   }
702
703   SortResult();
704 }
705
706 //==================================================
707 // Function: ClearPicked
708 // Purpose :
709 //==================================================
710 void SelectMgr_ViewerSelector::ClearPicked()
711 {
712   mystored.Clear();
713 }
714
715 //==================================================
716 // Function: Picked
717 // Purpose :
718 //==================================================
719 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
720 {
721   const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
722   const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
723   return anOwner;
724 }
725
726 //=======================================================================
727 //function : Picked
728 //purpose  :
729 //=======================================================================
730 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
731 {
732   if (theRank < 1 || theRank > NbPicked())
733   {
734     return Handle(SelectMgr_EntityOwner)();
735   }
736
737   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
738   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
739   return aStoredOwner;
740 }
741
742 //=======================================================================
743 //function : PickedData
744 //purpose  :
745 //=======================================================================
746 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
747 {
748   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
749   const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
750   return mystored.FindFromIndex (anOwnerIdx);
751 }
752
753 //===================================================
754 //
755 //       INTERNAL METHODS ....
756 //
757 //==================================================
758
759 //==================================================
760 // Function: SetEntitySetBuilder
761 // Purpose :
762 //==================================================
763 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
764 {
765   myEntitySetBuilder = theBuilder;
766   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
767   {
768     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
769   }
770 }
771
772 //==================================================
773 // Function: Contains
774 // Purpose :
775 //==================================================
776 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
777 {
778   return mySelectableObjects.Contains (theObject);
779 }
780
781 //==================================================
782 // Function: ActiveModes
783 // Purpose : return all the  modes with a given state for an object
784 //==================================================
785 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
786                                                   TColStd_ListOfInteger& theModeList,
787                                                   const SelectMgr_StateOfSelection theWantedState) const
788 {
789   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
790   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
791   {
792     if (theWantedState == SelectMgr_SOS_Any)
793     {
794       theModeList.Append (aSelIter.Value()->Mode());
795     }
796     else if (theWantedState == aSelIter.Value()->GetSelectionState())
797     {
798       theModeList.Append (aSelIter.Value()->Mode());
799     }
800   }
801
802   return hasActivatedStates;
803 }
804
805 //==================================================
806 // Function: IsActive
807 // Purpose :
808 //==================================================
809 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
810                                                      const Standard_Integer theMode) const
811 {
812   if (!Contains (theSelectableObject))
813     return Standard_False;
814
815   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
816   return !aSel.IsNull()
817        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
818 }
819
820 //==================================================
821 // Function: IsInside
822 // Purpose :
823 //==================================================
824 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
825                                                      const Standard_Integer theMode) const
826 {
827   if (!Contains (theSelectableObject))
828     return Standard_False;
829
830   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
831   return !aSel.IsNull()
832        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
833 }
834
835
836 //=======================================================================
837 //function : Status
838 //purpose  :
839 //=======================================================================
840
841 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
842 {
843   return theSelection->GetSelectionState();
844 }
845
846 //==================================================
847 // Function: Status
848 // Purpose : gives Information about selectors
849 //==================================================
850
851 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
852 {
853   TCollection_AsciiString aStatus ("Status Object :\n\t");
854   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
855   {
856     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
857     {
858       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
859               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
860     }
861   }
862
863   if (!Contains (theSelectableObject))
864   {
865     aStatus = aStatus + "Not Present in the selector\n\n";
866   }
867
868   return aStatus;
869 }
870
871 //=======================================================================
872 //function : SortResult
873 //purpose  :  there is a certain number of entities ranged by criteria
874 //            (depth, size, priority, mouse distance from borders or
875 //            CDG of the detected primitive. Parsing :
876 //             maximum priorities .
877 //             then a reasonable compromise between depth and distance...
878 // finally the ranges are stored in myindexes depending on the parsing.
879 // so, it is possible to only read
880 //=======================================================================
881 void SelectMgr_ViewerSelector::SortResult()
882 {
883   if(mystored.IsEmpty()) return;
884
885   const Standard_Integer anExtent = mystored.Extent();
886   if(myIndexes.IsNull() || anExtent != myIndexes->Length())
887     myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
888
889   TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
890   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
891   {
892     anIndexArray.SetValue (anIndexIter, anIndexIter);
893   }
894   std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
895 }
896
897 //=======================================================================
898 // function : AddSelectableObject
899 // purpose  : Adds new object to the map of selectable objects
900 //=======================================================================
901 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
902 {
903   if (!myMapOfObjectSensitives.IsBound (theObject))
904   {
905     mySelectableObjects.Append (theObject);
906     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
907     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
908   }
909 }
910
911 //=======================================================================
912 // function : AddSelectionToObject
913 // purpose  : Adds new selection to the object and builds its BVH tree
914 //=======================================================================
915 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
916                                                      const Handle(SelectMgr_Selection)& theSelection)
917 {
918   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
919   {
920     (*anEntitySet)->Append (theSelection);
921     (*anEntitySet)->BVH();
922   }
923   else
924   {
925     AddSelectableObject (theObject);
926     AddSelectionToObject (theObject, theSelection);
927   }
928 }
929
930 //=======================================================================
931 // function : MoveSelectableObject
932 // purpose  :
933 //=======================================================================
934 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
935 {
936   mySelectableObjects.ChangeSubset (theObject);
937 }
938
939 //=======================================================================
940 // function : RemoveSelectableObject
941 // purpose  : Removes selectable object from map of selectable ones
942 //=======================================================================
943 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
944 {
945   Handle(SelectMgr_SelectableObject) anObj = theObject;
946   if (myMapOfObjectSensitives.UnBind (theObject))
947   {
948     mySelectableObjects.Remove (theObject);
949   }
950 }
951
952 //=======================================================================
953 // function : RemoveSelectionOfObject
954 // purpose  : Removes selection of the object and marks its BVH tree
955 //            for rebuild
956 //=======================================================================
957 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
958                                                         const Handle(SelectMgr_Selection)& theSelection)
959 {
960   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
961   {
962     (*anEntitySet)->Remove (theSelection);
963   }
964 }
965
966 //=======================================================================
967 // function : RebuildObjectsTree
968 // purpose  : Marks BVH of selectable objects for rebuild
969 //=======================================================================
970 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
971 {
972   mySelectableObjects.MarkDirty();
973
974   if (theIsForce)
975   {
976     Standard_Integer aViewportWidth, aViewportHeight;
977     mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
978
979     Standard_Integer aWidth;
980     Standard_Integer aHeight;
981     mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
982     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
983                                    mySelectingVolumeMgr.ProjectionMatrix(),
984                                    mySelectingVolumeMgr.WorldViewMatrix(),
985                                    mySelectingVolumeMgr.WorldViewProjState(),
986                                    aWidth, aHeight);
987   }
988 }
989
990 //=======================================================================
991 // function : RebuildSensitivesTree
992 // purpose  : Marks BVH of sensitive entities of particular selectable
993 //            object for rebuild
994 //=======================================================================
995 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
996                                                       const Standard_Boolean theIsForce)
997 {
998   if (!Contains (theObject))
999     return;
1000
1001   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1002   anEntitySet->MarkDirty();
1003
1004   if (theIsForce)
1005   {
1006     anEntitySet->BVH();
1007   }
1008 }
1009
1010 //=======================================================================
1011 // function : resetSelectionActivationStatus
1012 // purpose  : Marks all added sensitive entities of all objects as
1013 //            non-selectable
1014 //=======================================================================
1015 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1016 {
1017   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1018   {
1019     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1020     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1021     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1022     {
1023       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1024     }
1025   }
1026 }
1027
1028 //=======================================================================
1029 // function : DetectedEntity
1030 // purpose  : Returns sensitive entity that was detected during the
1031 //            previous run of selection algorithm
1032 //=======================================================================
1033 const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
1034 {
1035   const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
1036   return mystored.FindFromIndex (aRankInMap).Entity;
1037 }
1038
1039 //=======================================================================
1040 // function : ActiveOwners
1041 // purpose  : Returns the list of active entity owners
1042 //=======================================================================
1043 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1044 {
1045   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1046   {
1047     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1048     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1049     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1050     {
1051       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1052       if (aSensitive->IsActiveForSelection())
1053       {
1054         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1055       }
1056     }
1057   }
1058 }
1059
1060 //=======================================================================
1061 //function : AllowOverlapDetection
1062 //purpose  : Sets the detection type: if theIsToAllow is false,
1063 //           only fully included sensitives will be detected, otherwise
1064 //           the algorithm will mark both included and overlapped entities
1065 //           as matched
1066 //=======================================================================
1067 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1068 {
1069   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1070 }
1071
1072 //=======================================================================
1073 //function : DumpJson
1074 //purpose  : 
1075 //=======================================================================
1076 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const 
1077 {
1078   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1079
1080   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, preferclosest)
1081   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
1082   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1083
1084   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectingVolumeMgr)
1085   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1086
1087   Standard_Integer aNbOfSelectableObjects = 0;
1088   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1089   {
1090     aNbOfSelectableObjects++;
1091   }
1092   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1093
1094   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1095   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1096   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1097
1098   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1099   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1100   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1101   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1102
1103   if (!myIndexes.IsNull())
1104     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1105
1106   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurRank)
1107   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1108   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myEntityIdx)
1109   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1110 }