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