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.hxx>
27 #include <SelectMgr_EntityOwner.hxx>
28 #include <SelectMgr_FrustumBuilder.hxx>
29 #include <SelectMgr_SelectionImageFiller.hxx>
30 #include <SelectMgr_SensitiveEntitySet.hxx>
31 #include <SelectMgr_SortCriterion.hxx>
32 #include <TColStd_Array1OfInteger.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <TColStd_HArray1OfInteger.hxx>
35 #include <TColStd_ListOfInteger.hxx>
36 #include <V3d_View.hxx>
37 
38 #include <algorithm>
39 
40 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
41 
42 namespace
43 {
44   //! Comparison operator for sorting selection results
45   class CompareResults
46   {
47   public:
48 
CompareResults(const SelectMgr_IndexedDataMapOfOwnerCriterion & theMapOfCriterion,bool theToPreferClosest)49     CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
50                     bool theToPreferClosest)
51     : myMapOfCriterion (&theMapOfCriterion),
52       myToPreferClosest (theToPreferClosest) {}
53 
operator ()(Standard_Integer theLeft,Standard_Integer theRight) const54     Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
55     {
56       const SelectMgr_SortCriterion& anElemLeft  = myMapOfCriterion->FindFromIndex (theLeft);
57       const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
58       if (myToPreferClosest)
59       {
60         return anElemLeft.IsCloserDepth (anElemRight);
61       }
62       else
63       {
64         return anElemLeft.IsHigherPriority (anElemRight);
65       }
66     }
67 
68   private:
69     const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
70     bool myToPreferClosest;
71   };
72 
73   static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
74 }
75 
76 //=======================================================================
77 // function : updatePoint3d
78 // purpose  :
79 //=======================================================================
updatePoint3d(SelectMgr_SortCriterion & theCriterion,const SelectBasics_PickResult & thePickResult,const Handle (Select3D_SensitiveEntity)& theEntity,const gp_GTrsf & theInversedTrsf,const SelectMgr_SelectingVolumeManager & theMgr) const80 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
81                                               const SelectBasics_PickResult& thePickResult,
82                                               const Handle(Select3D_SensitiveEntity)& theEntity,
83                                               const gp_GTrsf& theInversedTrsf,
84                                               const SelectMgr_SelectingVolumeManager& theMgr) const
85 {
86   if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
87   {
88     return;
89   }
90 
91   bool hasNormal = false;
92   if (thePickResult.HasPickedPoint())
93   {
94     theCriterion.Point  = thePickResult.PickedPoint();
95     theCriterion.Normal = thePickResult.SurfaceNormal();
96     const float aNormLen2 = theCriterion.Normal.SquareModulus();
97     if (aNormLen2 > ShortRealEpsilon())
98     {
99       hasNormal = true;
100       theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
101     }
102   }
103   else if (!thePickResult.IsValid())
104   {
105     theCriterion.Point = thePickResult.PickedPoint();
106     return;
107   }
108   else
109   {
110     theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
111   }
112 
113   gp_GTrsf anInvTrsf = theInversedTrsf;
114   if (theCriterion.Entity->HasInitLocation())
115   {
116     anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
117   }
118   if (anInvTrsf.Form() != gp_Identity)
119   {
120     const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
121     anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
122     if (hasNormal)
123     {
124       Graphic3d_Mat4d aMat4;
125       anInvInvTrsd.GetMat4 (aMat4);
126       const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
127       theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
128     }
129   }
130 
131   const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
132   switch (myDepthTolType)
133   {
134     case SelectMgr_TypeOfDepthTolerance_Uniform:
135     {
136       theCriterion.Tolerance = myDepthTolerance;
137       break;
138     }
139     case SelectMgr_TypeOfDepthTolerance_UniformPixels:
140     case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
141     {
142       if (mySelectingVolumeMgr.Camera().IsNull())
143       {
144         // fallback for an arbitrary projection matrix
145         theCriterion.Tolerance = aSensFactor / 33.0;
146       }
147       else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
148       {
149         theCriterion.Tolerance = myCameraScale * aSensFactor;
150       }
151       else
152       {
153         const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
154         theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
155       }
156       break;
157     }
158   }
159 }
160 
161 //==================================================
162 // Function: Initialize
163 // Purpose :
164 //==================================================
SelectMgr_ViewerSelector()165 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
166 : myDepthTolerance (0.0),
167   myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
168   myToPreferClosest (Standard_True),
169   myCameraScale (1.0),
170   myToPrebuildBVH (Standard_False),
171   myIsSorted (Standard_False),
172   myIsLeftChildQueuedFirst (Standard_False)
173 {
174   myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
175 }
176 
177 //=======================================================================
178 // Function: SetPixelTolerance
179 // Purpose :
180 //=======================================================================
SetPixelTolerance(const Standard_Integer theTolerance)181 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
182 {
183   if (myTolerances.Tolerance() == theTolerance)
184   {
185     return;
186   }
187   if (theTolerance < 0)
188   {
189     myTolerances.ResetDefaults();
190   }
191   else
192   {
193     myTolerances.SetCustomTolerance (theTolerance);
194   }
195 }
196 
197 //==================================================
198 // Function: Activate
199 // Purpose :
200 //==================================================
Activate(const Handle (SelectMgr_Selection)& theSelection)201 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
202 {
203   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
204   {
205     aSelEntIter.Value()->SetActiveForSelection();
206   }
207 
208   if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
209   {
210     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
211 
212     myTolerances.Add (theSelection->Sensitivity());
213   }
214 }
215 
216 //==================================================
217 // Function: Deactivate
218 // Purpose :
219 //==================================================
Deactivate(const Handle (SelectMgr_Selection)& theSelection)220 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
221 {
222   for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
223   {
224     aSelEntIter.Value()->ResetSelectionActiveStatus();
225   }
226 
227   if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
228   {
229     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
230 
231     myTolerances.Decrement (theSelection->Sensitivity());
232   }
233 }
234 
235 //=======================================================================
236 // function: isToScaleFrustum
237 // purpose : Checks if the entity given requires to scale current selecting frustum
238 //=======================================================================
isToScaleFrustum(const Handle (Select3D_SensitiveEntity)& theEntity)239 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
240 {
241   return mySelectingVolumeMgr.IsScalableActiveVolume()
242     && sensitivity (theEntity) < myTolerances.Tolerance();
243 }
244 
245 //=======================================================================
246 // function: sensitivity
247 // purpose : In case if custom tolerance is set, this method will return sum of entity
248 //           sensitivity and custom tolerance.
249 //=======================================================================
sensitivity(const Handle (Select3D_SensitiveEntity)& theEntity) const250 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
251 {
252   return myTolerances.IsCustomTolSet() ?
253     theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
254 }
255 
256 //=======================================================================
257 // function: checkOverlap
258 // purpose : Internal function that checks if a particular sensitive
259 //           entity theEntity overlaps current selecting volume precisely
260 //=======================================================================
checkOverlap(const Handle (Select3D_SensitiveEntity)& theEntity,const gp_GTrsf & theInversedTrsf,SelectMgr_SelectingVolumeManager & theMgr)261 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
262                                              const gp_GTrsf& theInversedTrsf,
263                                              SelectMgr_SelectingVolumeManager& theMgr)
264 {
265   const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
266   Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
267   SelectBasics_PickResult aPickResult;
268   const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
269   if (!isMatched
270     || anOwner.IsNull())
271   {
272     return;
273   }
274 
275   SelectMgr_SortCriterion aCriterion;
276   myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
277   aCriterion.Entity    = theEntity;
278   aCriterion.Priority  = anOwner->Priority();
279   aCriterion.Depth     = aPickResult.Depth();
280   aCriterion.MinDist   = aPickResult.DistToGeomCenter();
281 
282   if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
283   {
284     ++aPrevCriterion->NbOwnerMatches;
285     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
286     if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
287     {
288       if (aCriterion.IsCloserDepth (*aPrevCriterion))
289       {
290         updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
291         *aPrevCriterion = aCriterion;
292       }
293     }
294   }
295   else
296   {
297     aCriterion.NbOwnerMatches = 1;
298     updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
299     mystored.Add (anOwner, aCriterion);
300   }
301 }
302 
303 //=======================================================================
304 // Function: updateZLayers
305 // Purpose :
306 //=======================================================================
updateZLayers(const Handle (V3d_View)& theView)307 void SelectMgr_ViewerSelector::updateZLayers (const Handle(V3d_View)& theView)
308 {
309   myZLayerOrderMap.Clear();
310   TColStd_SequenceOfInteger aZLayers;
311   theView->Viewer()->GetAllZLayers (aZLayers);
312   Standard_Integer aPos = 0;
313   Standard_Boolean isPrevDepthWrite = true;
314   for (TColStd_SequenceOfInteger::Iterator aLayerIter (aZLayers); aLayerIter.More(); aLayerIter.Next())
315   {
316     Graphic3d_ZLayerSettings aSettings = theView->Viewer()->ZLayerSettings (aLayerIter.Value());
317     if (aSettings.ToClearDepth()
318      || isPrevDepthWrite != aSettings.ToEnableDepthWrite())
319     {
320       ++aPos;
321     }
322     isPrevDepthWrite = aSettings.ToEnableDepthWrite();
323     myZLayerOrderMap.Bind (aLayerIter.Value(), aPos);
324   }
325 }
326 
327 //=======================================================================
328 // function: computeFrustum
329 // purpose :
330 //=======================================================================
computeFrustum(const Handle (Select3D_SensitiveEntity)& theEnt,const SelectMgr_SelectingVolumeManager & theMgrGlobal,const SelectMgr_SelectingVolumeManager & theMgrObject,const gp_GTrsf & theInvTrsf,SelectMgr_FrustumCache & theCachedMgrs,SelectMgr_SelectingVolumeManager & theResMgr)331 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
332                                                const SelectMgr_SelectingVolumeManager& theMgrGlobal,
333                                                const SelectMgr_SelectingVolumeManager& theMgrObject,
334                                                const gp_GTrsf& theInvTrsf,
335                                                SelectMgr_FrustumCache& theCachedMgrs,
336                                                SelectMgr_SelectingVolumeManager& theResMgr)
337 {
338   Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
339   const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
340   const Standard_Boolean toScale = aScale != 1;
341   const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
342   if (toScale && toTransform)
343   {
344     theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
345     theResMgr.SetViewClipping (theMgrObject);
346   }
347   else if (toScale)
348   {
349     if (!theCachedMgrs.Find (aScale, theResMgr))
350     {
351       theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
352       theCachedMgrs.Bind (aScale, theResMgr);
353     }
354     theResMgr.SetViewClipping (theMgrObject);
355   }
356   else if (toTransform)
357   {
358     theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
359     theResMgr.SetViewClipping (theMgrObject);
360   }
361   else
362   {
363     theResMgr = theMgrObject;
364   }
365 }
366 
367 //=======================================================================
368 // function: traverseObject
369 // purpose : Internal function that checks if there is possible overlap
370 //           between some entity of selectable object theObject and
371 //           current selecting volume
372 //=======================================================================
traverseObject(const Handle (SelectMgr_SelectableObject)& theObject,const SelectMgr_SelectingVolumeManager & theMgr,const Handle (Graphic3d_Camera)& theCamera,const Graphic3d_Mat4d & theProjectionMat,const Graphic3d_Mat4d & theWorldViewMat,const Graphic3d_Vec2i & theWinSize)373 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
374                                                const SelectMgr_SelectingVolumeManager& theMgr,
375                                                const Handle(Graphic3d_Camera)& theCamera,
376                                                const Graphic3d_Mat4d& theProjectionMat,
377                                                const Graphic3d_Mat4d& theWorldViewMat,
378                                                const Graphic3d_Vec2i& theWinSize)
379 {
380   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
381   if (anEntitySet->Size() == 0)
382   {
383     return;
384   }
385 
386   const bool hasEntityTrsfPers = anEntitySet->HasEntityWithPersistence()
387                              && !theCamera.IsNull();
388   const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
389   gp_GTrsf aInversedTrsf;
390   if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
391   {
392     if (theObject->TransformPersistence().IsNull())
393     {
394       aInversedTrsf = theObject->InversedTransformation();
395     }
396     else
397     {
398       if (theCamera.IsNull())
399       {
400         return;
401       }
402 
403       const Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera,
404                                                                                theProjectionMat, theWorldViewMat,
405                                                                                theWinSize.x(), theWinSize.y());
406       gp_GTrsf aTPers;
407       aTPers.SetMat4 (aMat);
408       aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
409     }
410   }
411 
412   SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
413                                         ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
414                                         : theMgr;
415   if (!hasEntityTrsfPers
416    && !aMgr.OverlapsBox (aSensitivesTree->MinPoint (0),
417                          aSensitivesTree->MaxPoint (0)))
418   {
419     return;
420   }
421 
422   if (!theObject->ClipPlanes().IsNull()
423     && theObject->ClipPlanes()->ToOverrideGlobal())
424   {
425     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
426   }
427   else if (!theObject->TransformPersistence().IsNull())
428   {
429     if (theObject->TransformPersistence()->IsZoomOrRotate()
430     && !theMgr.ViewClipping().IsNull())
431     {
432       // Zoom/rotate persistence object lives in two worlds at the same time.
433       // Global clipping planes can not be trivially applied without being converted
434       // into local space of transformation persistence object.
435       // As more simple alternative - just clip entire object by its anchor point defined in the world space.
436       const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
437       for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
438       {
439         const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
440         if (!aPlane->IsOn())
441         {
442           continue;
443         }
444 
445         const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
446         if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
447         {
448           return;
449         }
450       }
451     }
452 
453     aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
454   }
455   else if (!theObject->ClipPlanes().IsNull()
456         && !theObject->ClipPlanes()->IsEmpty())
457   {
458     aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
459   }
460 
461   if (!theMgr.ViewClipping().IsNull() &&
462       theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
463   {
464     Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
465     // If box selection is active, and the whole sensitive tree is out of the clip planes
466     // selection is empty for this object
467     const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
468 
469     for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
470     {
471       const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
472       if (!aPlane->IsOn())
473       {
474         continue;
475       }
476 
477       Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
478       if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
479       {
480         return;
481       }
482     }
483   }
484 
485   const Standard_Integer aFirstStored = mystored.Extent() + 1;
486 
487   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
488   Standard_Integer aHead = -1;
489   Standard_Integer aNode = 0; // a root node
490   SelectMgr_FrustumCache aScaledTrnsfFrustums;
491   SelectMgr_SelectingVolumeManager aTmpMgr;
492   for (;;)
493   {
494     if (!aSensitivesTree->IsOuter (aNode))
495     {
496       const Standard_Integer aLeftChildIdx  = aSensitivesTree->Child<0> (aNode);
497       const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
498       const Standard_Boolean isLeftChildIn  = hasEntityTrsfPers
499                                            || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx),
500                                                                 aSensitivesTree->MaxPoint (aLeftChildIdx));
501       const Standard_Boolean isRightChildIn = hasEntityTrsfPers
502                                            || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx),
503                                                                 aSensitivesTree->MaxPoint (aRightChildIdx));
504       if (isLeftChildIn
505        && isRightChildIn)
506       {
507         aNode = aLeftChildIdx;
508         ++aHead;
509         aStack[aHead] = aRightChildIdx;
510       }
511       else if (isLeftChildIn
512         || isRightChildIn)
513       {
514         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
515       }
516       else
517       {
518         if (aHead < 0)
519         {
520           break;
521         }
522 
523         aNode = aStack[aHead];
524         --aHead;
525       }
526     }
527     else
528     {
529       bool aClipped = false;
530       if (!theMgr.ViewClipping().IsNull() &&
531           theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
532       {
533         Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
534         // If box selection is active, and the whole sensitive tree is out of the clip planes
535         // selection is empty for this object
536         const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
537 
538         for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
539         {
540           const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
541           if (!aPlane->IsOn())
542           {
543             continue;
544           }
545           Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
546           if (aState == Graphic3d_ClipState_Out)
547           {
548             aClipped = true;
549             break;
550           }
551           if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
552           {
553             if (aPlane->ProbeBoxTouch (aBBox))
554               continue;
555             aClipped = true;
556             break;
557           }
558         }
559       }
560       if (!aClipped)
561       {
562         const Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
563         const Standard_Integer anEndIdx  = aSensitivesTree->EndPrimitive (aNode);
564         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
565         {
566           const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
567           if (!aSensitive->IsActiveForSelection())
568           {
569             continue;
570           }
571 
572           const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
573 
574           gp_GTrsf aInvSensTrsf = aInversedTrsf;
575           if (!anEnt->TransformPersistence().IsNull())
576           {
577             if (theCamera.IsNull())
578             {
579               continue;
580             }
581             const Graphic3d_Mat4d aMat = anEnt->TransformPersistence()->Compute (theCamera,
582                                                                                  theProjectionMat, theWorldViewMat,
583                                                                                  theWinSize.x(), theWinSize.y());
584             gp_GTrsf aTPers;
585             aTPers.SetMat4 (aMat);
586             aInvSensTrsf = (aTPers * gp_GTrsf(theObject->Transformation())).Inverted();
587           }
588 
589           computeFrustum (anEnt, theMgr, aMgr, aInvSensTrsf, aScaledTrnsfFrustums, aTmpMgr);
590           checkOverlap (anEnt, aInvSensTrsf, aTmpMgr);
591         }
592       }
593       if (aHead < 0)
594       {
595         break;
596       }
597 
598       aNode = aStack[aHead];
599       --aHead;
600     }
601   }
602 
603   // in case of Box/Polyline selection - keep only Owners having all Entities detected
604   if (mySelectingVolumeMgr.IsOverlapAllowed()
605   || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
606    && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
607   {
608     return;
609   }
610 
611   for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
612   {
613     const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
614     const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
615     Standard_Integer aNbOwnerEntities = 0;
616     anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
617     if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
618     {
619       mystored.RemoveFromIndex (aStoredIter);
620     }
621   }
622 }
623 
624 //=======================================================================
625 // function: TraverseSensitives
626 // purpose : Traverses BVH containing all added selectable objects and
627 //           finds candidates for further search of overlap
628 //=======================================================================
TraverseSensitives()629 void SelectMgr_ViewerSelector::TraverseSensitives()
630 {
631   SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
632 
633   mystored.Clear();
634   myIsSorted = false;
635 
636   Graphic3d_Vec2i aWinSize;
637   mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y());
638 
639   const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
640   Graphic3d_Mat4d aProjectionMat, aWorldViewMat;
641   Graphic3d_WorldViewProjState aViewState;
642   if (!aCamera.IsNull())
643   {
644     aProjectionMat = aCamera->ProjectionMatrix();
645     aWorldViewMat = aCamera->OrientationMatrix();
646     aViewState = aCamera->WorldViewProjState();
647 
648     myCameraEye = aCamera->Eye().XYZ();
649     myCameraDir = aCamera->Direction().XYZ();
650     myCameraScale = aCamera->IsOrthographic()
651                   ? aCamera->Scale()
652                   : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
653     const double aPixelSize = Max (1.0 / aWinSize.x(), 1.0 / aWinSize.y());
654     myCameraScale *= aPixelSize;
655   }
656   mySelectableObjects.UpdateBVH (aCamera, aWinSize);
657 
658   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
659   {
660     const SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = (SelectMgr_SelectableObjectSet::BVHSubset )aBVHSetIt;
661     if (mySelectableObjects.IsEmpty (aBVHSubset))
662     {
663       continue;
664     }
665     if (aCamera.IsNull()
666      && aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_3d)
667     {
668       continue;
669     }
670 
671     SelectMgr_SelectingVolumeManager aMgr;
672 
673     // for 2D space selection transform selecting volumes to perform overlap testing
674     // directly in camera's eye space omitting the camera position, which is not
675     // needed there at all
676     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
677     {
678       gp_GTrsf aTFrustum;
679       aTFrustum.SetValue (1, 1, aWorldViewMat.GetValue (0, 0));
680       aTFrustum.SetValue (1, 2, aWorldViewMat.GetValue (0, 1));
681       aTFrustum.SetValue (1, 3, aWorldViewMat.GetValue (0, 2));
682       aTFrustum.SetValue (2, 1, aWorldViewMat.GetValue (1, 0));
683       aTFrustum.SetValue (2, 2, aWorldViewMat.GetValue (1, 1));
684       aTFrustum.SetValue (2, 3, aWorldViewMat.GetValue (1, 2));
685       aTFrustum.SetValue (3, 1, aWorldViewMat.GetValue (2, 0));
686       aTFrustum.SetValue (3, 2, aWorldViewMat.GetValue (2, 1));
687       aTFrustum.SetValue (3, 3, aWorldViewMat.GetValue (2, 2));
688       aTFrustum.SetTranslationPart (gp_XYZ (aWorldViewMat.GetValue (0, 3),
689                                             aWorldViewMat.GetValue (1, 3),
690                                             aWorldViewMat.GetValue (2, 3)));
691 
692       // define corresponding frustum builder parameters
693       Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
694       Handle(Graphic3d_Camera) aNewCamera = new Graphic3d_Camera();
695       aNewCamera->CopyMappingData (aCamera);
696       aNewCamera->SetIdentityOrientation();
697       aWorldViewMat = aNewCamera->OrientationMatrix(); // should be identity matrix
698       aProjectionMat = aNewCamera->ProjectionMatrix(); // should be the same to aProjectionMat
699       aBuilder->SetCamera (aNewCamera);
700       aBuilder->SetWindowSize (aWinSize.x(), aWinSize.y());
701       aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
702     }
703     else
704     {
705       aMgr = mySelectingVolumeMgr;
706     }
707 
708     const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
709 
710     Standard_Integer aNode = 0;
711     if (!aMgr.OverlapsBox (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
712     {
713       continue;
714     }
715 
716     Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
717     Standard_Integer aHead = -1;
718     for (;;)
719     {
720       if (!aBVHTree->IsOuter (aNode))
721       {
722         const Standard_Integer aLeftChildIdx  = aBVHTree->Child<0> (aNode);
723         const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
724         const Standard_Boolean isLeftChildIn  =
725           aMgr.OverlapsBox (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
726         const Standard_Boolean isRightChildIn =
727           aMgr.OverlapsBox (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
728         if (isLeftChildIn
729           && isRightChildIn)
730         {
731           aNode = aLeftChildIdx;
732           ++aHead;
733           aStack[aHead] = aRightChildIdx;
734         }
735         else if (isLeftChildIn
736           || isRightChildIn)
737         {
738           aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
739         }
740         else
741         {
742           if (aHead < 0)
743           {
744             break;
745           }
746 
747           aNode = aStack[aHead];
748           --aHead;
749         }
750       }
751       else
752       {
753         Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
754         Standard_Integer anEndIdx  = aBVHTree->EndPrimitive (aNode);
755         for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
756         {
757           const Handle(SelectMgr_SelectableObject)& aSelectableObject =
758             mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
759 
760           traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWinSize);
761         }
762         if (aHead < 0)
763         {
764           break;
765         }
766 
767         aNode = aStack[aHead];
768         --aHead;
769       }
770     }
771   }
772 
773   SortResult();
774 }
775 
776 //==================================================
777 // Function: ClearPicked
778 // Purpose :
779 //==================================================
ClearPicked()780 void SelectMgr_ViewerSelector::ClearPicked()
781 {
782   mystored.Clear();
783   myIsSorted = true;
784 }
785 
786 //==================================================
787 // Function: RemovePicked
788 // Purpose :
789 //==================================================
RemovePicked(const Handle (SelectMgr_SelectableObject)& theObject)790 bool SelectMgr_ViewerSelector::RemovePicked (const Handle(SelectMgr_SelectableObject)& theObject)
791 {
792   if (mystored.IsEmpty()
793   || !mySelectableObjects.Contains (theObject))
794   {
795     return false;
796   }
797 
798   bool isRemoved = false;
799   for (Standard_Integer aPickIter = 1; aPickIter <= mystored.Extent(); ++aPickIter)
800   {
801     const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (aPickIter);
802     if (!aStoredOwner.IsNull()
803       && aStoredOwner->IsSameSelectable (theObject))
804     {
805       mystored.RemoveFromIndex (aPickIter);
806       --aPickIter;
807       isRemoved = true;
808     }
809   }
810   if (isRemoved)
811   {
812     myIsSorted = false;
813   }
814   return isRemoved;
815 }
816 
817 //=======================================================================
818 //function : Picked
819 //purpose  :
820 //=======================================================================
Handle(SelectMgr_EntityOwner)821 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
822 {
823   if (theRank < 1 || theRank > NbPicked())
824   {
825     return Handle(SelectMgr_EntityOwner)();
826   }
827 
828   if (!myIsSorted)
829   {
830     SortResult();
831   }
832 
833   const Standard_Integer anOwnerIdx = myIndexes.Value (theRank);
834   const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
835   return aStoredOwner;
836 }
837 
838 //=======================================================================
839 //function : PickedData
840 //purpose  :
841 //=======================================================================
PickedData(const Standard_Integer theRank) const842 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
843 {
844   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
845   if (!myIsSorted)
846   {
847     SortResult();
848   }
849 
850   const Standard_Integer anOwnerIdx = myIndexes.Value (theRank);
851   return mystored.FindFromIndex (anOwnerIdx);
852 }
853 
854 //===================================================
855 //
856 //       INTERNAL METHODS ....
857 //
858 //==================================================
859 
860 //==================================================
861 // Function: SetEntitySetBuilder
862 // Purpose :
863 //==================================================
SetEntitySetBuilder(const Handle (Select3D_BVHBuilder3d)& theBuilder)864 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
865 {
866   myEntitySetBuilder = theBuilder;
867   for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
868   {
869     aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
870   }
871 }
872 
873 //==================================================
874 // Function: Contains
875 // Purpose :
876 //==================================================
Contains(const Handle (SelectMgr_SelectableObject)& theObject) const877 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
878 {
879   return mySelectableObjects.Contains (theObject);
880 }
881 
882 //==================================================
883 // Function: ActiveModes
884 // Purpose : return all the  modes with a given state for an object
885 //==================================================
Modes(const Handle (SelectMgr_SelectableObject)& theSelectableObject,TColStd_ListOfInteger & theModeList,const SelectMgr_StateOfSelection theWantedState) const886 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
887                                                   TColStd_ListOfInteger& theModeList,
888                                                   const SelectMgr_StateOfSelection theWantedState) const
889 {
890   Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
891   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
892   {
893     if (theWantedState == SelectMgr_SOS_Any)
894     {
895       theModeList.Append (aSelIter.Value()->Mode());
896     }
897     else if (theWantedState == aSelIter.Value()->GetSelectionState())
898     {
899       theModeList.Append (aSelIter.Value()->Mode());
900     }
901   }
902 
903   return hasActivatedStates;
904 }
905 
906 //==================================================
907 // Function: IsActive
908 // Purpose :
909 //==================================================
IsActive(const Handle (SelectMgr_SelectableObject)& theSelectableObject,const Standard_Integer theMode) const910 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
911                                                      const Standard_Integer theMode) const
912 {
913   if (!Contains (theSelectableObject))
914     return Standard_False;
915 
916   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
917   return !aSel.IsNull()
918        && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
919 }
920 
921 //==================================================
922 // Function: IsInside
923 // Purpose :
924 //==================================================
IsInside(const Handle (SelectMgr_SelectableObject)& theSelectableObject,const Standard_Integer theMode) const925 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
926                                                      const Standard_Integer theMode) const
927 {
928   if (!Contains (theSelectableObject))
929     return Standard_False;
930 
931   const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
932   return !aSel.IsNull()
933        && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
934 }
935 
936 
937 //=======================================================================
938 //function : Status
939 //purpose  :
940 //=======================================================================
941 
Status(const Handle (SelectMgr_Selection)& theSelection) const942 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
943 {
944   return theSelection->GetSelectionState();
945 }
946 
947 //==================================================
948 // Function: Status
949 // Purpose : gives Information about selectors
950 //==================================================
951 
Status(const Handle (SelectMgr_SelectableObject)& theSelectableObject) const952 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
953 {
954   TCollection_AsciiString aStatus ("Status Object :\n\t");
955   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
956   {
957     if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
958     {
959       aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
960               + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
961     }
962   }
963 
964   if (!Contains (theSelectableObject))
965   {
966     aStatus = aStatus + "Not Present in the selector\n\n";
967   }
968 
969   return aStatus;
970 }
971 
972 //=======================================================================
973 //function : SortResult
974 //purpose  :
975 //=======================================================================
SortResult() const976 void SelectMgr_ViewerSelector::SortResult() const
977 {
978   if (mystored.IsEmpty())
979   {
980     myIsSorted = true;
981     return;
982   }
983 
984   const Standard_Integer anExtent = mystored.Extent();
985   if (anExtent != myIndexes.Length())
986   {
987     myIndexes.Resize (1, anExtent, false);
988   }
989 
990   for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
991   {
992     myIndexes.SetValue (anIndexIter, anIndexIter);
993   }
994   std::sort (myIndexes.begin(), myIndexes.end(), CompareResults (mystored, myToPreferClosest));
995   myIsSorted = true;
996 }
997 
998 //=======================================================================
999 // function : AddSelectableObject
1000 // purpose  : Adds new object to the map of selectable objects
1001 //=======================================================================
AddSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1002 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1003 {
1004   if (!myMapOfObjectSensitives.IsBound (theObject))
1005   {
1006     mySelectableObjects.Append (theObject);
1007     Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
1008     myMapOfObjectSensitives.Bind (theObject, anEntitySet);
1009   }
1010 }
1011 
1012 //=======================================================================
1013 // function : AddSelectionToObject
1014 // purpose  : Adds new selection to the object and builds its BVH tree
1015 //=======================================================================
AddSelectionToObject(const Handle (SelectMgr_SelectableObject)& theObject,const Handle (SelectMgr_Selection)& theSelection)1016 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
1017                                                      const Handle(SelectMgr_Selection)& theSelection)
1018 {
1019   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
1020   {
1021     (*anEntitySet)->Append (theSelection);
1022     (*anEntitySet)->BVH();
1023   }
1024   else
1025   {
1026     AddSelectableObject (theObject);
1027     AddSelectionToObject (theObject, theSelection);
1028   }
1029 }
1030 
1031 //=======================================================================
1032 // function : MoveSelectableObject
1033 // purpose  :
1034 //=======================================================================
MoveSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1035 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1036 {
1037   mySelectableObjects.ChangeSubset (theObject);
1038 }
1039 
1040 //=======================================================================
1041 // function : RemoveSelectableObject
1042 // purpose  : Removes selectable object from map of selectable ones
1043 //=======================================================================
RemoveSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1044 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1045 {
1046   Handle(SelectMgr_SelectableObject) anObj = theObject;
1047   if (myMapOfObjectSensitives.UnBind (theObject))
1048   {
1049     RemovePicked (theObject);
1050     mySelectableObjects.Remove (theObject);
1051   }
1052 }
1053 
1054 //=======================================================================
1055 // function : RemoveSelectionOfObject
1056 // purpose  : Removes selection of the object and marks its BVH tree
1057 //            for rebuild
1058 //=======================================================================
RemoveSelectionOfObject(const Handle (SelectMgr_SelectableObject)& theObject,const Handle (SelectMgr_Selection)& theSelection)1059 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
1060                                                         const Handle(SelectMgr_Selection)& theSelection)
1061 {
1062   if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
1063   {
1064     (*anEntitySet)->Remove (theSelection);
1065   }
1066 }
1067 
1068 //=======================================================================
1069 // function : RebuildObjectsTree
1070 // purpose  : Marks BVH of selectable objects for rebuild
1071 //=======================================================================
RebuildObjectsTree(const Standard_Boolean theIsForce)1072 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
1073 {
1074   mySelectableObjects.MarkDirty();
1075 
1076   if (theIsForce)
1077   {
1078     Graphic3d_Vec2i aWinSize;
1079     mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y());
1080     mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), aWinSize);
1081   }
1082 }
1083 
1084 //=======================================================================
1085 // function : RebuildSensitivesTree
1086 // purpose  : Marks BVH of sensitive entities of particular selectable
1087 //            object for rebuild
1088 //=======================================================================
RebuildSensitivesTree(const Handle (SelectMgr_SelectableObject)& theObject,const Standard_Boolean theIsForce)1089 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1090                                                       const Standard_Boolean theIsForce)
1091 {
1092   if (!Contains (theObject))
1093     return;
1094 
1095   Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1096   anEntitySet->MarkDirty();
1097 
1098   if (theIsForce)
1099   {
1100     anEntitySet->BVH();
1101   }
1102 }
1103 
1104 //=======================================================================
1105 // function : resetSelectionActivationStatus
1106 // purpose  : Marks all added sensitive entities of all objects as
1107 //            non-selectable
1108 //=======================================================================
ResetSelectionActivationStatus()1109 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1110 {
1111   for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1112   {
1113     Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1114     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1115     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1116     {
1117       anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1118     }
1119   }
1120 }
1121 
1122 //=======================================================================
1123 // function : ActiveOwners
1124 // purpose  : Returns the list of active entity owners
1125 //=======================================================================
ActiveOwners(NCollection_List<Handle (SelectMgr_EntityOwner)> & theOwners) const1126 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1127 {
1128   for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1129   {
1130     const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1131     const Standard_Integer anEntitiesNb = anEntitySet->Size();
1132     for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1133     {
1134       const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1135       if (aSensitive->IsActiveForSelection())
1136       {
1137         theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1138       }
1139     }
1140   }
1141 }
1142 
1143 //=======================================================================
1144 //function : AllowOverlapDetection
1145 //purpose  : Sets the detection type: if theIsToAllow is false,
1146 //           only fully included sensitives will be detected, otherwise
1147 //           the algorithm will mark both included and overlapped entities
1148 //           as matched
1149 //=======================================================================
AllowOverlapDetection(const Standard_Boolean theIsToAllow)1150 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1151 {
1152   mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1153 }
1154 
1155 //=======================================================================
1156 // Function: Pick
1157 // Purpose :
1158 //=======================================================================
Pick(const Standard_Integer theXPix,const Standard_Integer theYPix,const Handle (V3d_View)& theView)1159 void SelectMgr_ViewerSelector::Pick (const Standard_Integer theXPix,
1160                                      const Standard_Integer theYPix,
1161                                      const Handle(V3d_View)& theView)
1162 {
1163   updateZLayers (theView);
1164 
1165   gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
1166                       static_cast<Standard_Real> (theYPix));
1167   mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos);
1168 
1169   mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
1170   mySelectingVolumeMgr.SetCamera (theView->Camera());
1171   Standard_Integer aWidth = 0, aHeight = 0;
1172   theView->Window()->Size (aWidth, aHeight);
1173   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1174 
1175   mySelectingVolumeMgr.BuildSelectingVolume();
1176   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1177 
1178   TraverseSensitives();
1179 }
1180 
1181 //=======================================================================
1182 // Function: Pick
1183 // Purpose :
1184 //=======================================================================
Pick(const Standard_Integer theXPMin,const Standard_Integer theYPMin,const Standard_Integer theXPMax,const Standard_Integer theYPMax,const Handle (V3d_View)& theView)1185 void SelectMgr_ViewerSelector::Pick (const Standard_Integer theXPMin,
1186                                      const Standard_Integer theYPMin,
1187                                      const Standard_Integer theXPMax,
1188                                      const Standard_Integer theYPMax,
1189                                      const Handle(V3d_View)& theView)
1190 {
1191   updateZLayers (theView);
1192 
1193   gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin),
1194                          static_cast<Standard_Real> (theYPMin));
1195   gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax),
1196                          static_cast<Standard_Real> (theYPMax));
1197   mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos,
1198                                                aMaxMousePos);
1199 
1200   mySelectingVolumeMgr.SetCamera (theView->Camera());
1201   Standard_Integer aWidth = 0, aHeight = 0;
1202   theView->Window()->Size (aWidth, aHeight);
1203   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1204 
1205   mySelectingVolumeMgr.BuildSelectingVolume();
1206   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1207   TraverseSensitives();
1208 }
1209 
1210 //=======================================================================
1211 // Function: Pick
1212 // Purpose : Selection using a polyline
1213 //=======================================================================
Pick(const TColgp_Array1OfPnt2d & thePolyline,const Handle (V3d_View)& theView)1214 void SelectMgr_ViewerSelector::Pick (const TColgp_Array1OfPnt2d& thePolyline,
1215                                      const Handle(V3d_View)& theView)
1216 {
1217   updateZLayers (theView);
1218 
1219   mySelectingVolumeMgr.InitPolylineSelectingVolume (thePolyline);
1220   mySelectingVolumeMgr.SetCamera (theView->Camera());
1221   Standard_Integer aWidth = 0, aHeight = 0;
1222   theView->Window()->Size (aWidth, aHeight);
1223   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1224   mySelectingVolumeMgr.BuildSelectingVolume();
1225   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1226 
1227   TraverseSensitives();
1228 }
1229 
1230 //=======================================================================
1231 // Function: Pick
1232 // Purpose :
1233 //=======================================================================
Pick(const gp_Ax1 & theAxis,const Handle (V3d_View)& theView)1234 void SelectMgr_ViewerSelector::Pick (const gp_Ax1& theAxis,
1235                                      const Handle(V3d_View)& theView)
1236 {
1237   updateZLayers (theView);
1238 
1239   mySelectingVolumeMgr.InitAxisSelectingVolume (theAxis);
1240   mySelectingVolumeMgr.BuildSelectingVolume();
1241   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1242 
1243   TraverseSensitives();
1244 }
1245 
1246 //=======================================================================
1247 //function : ToPixMap
1248 //purpose  :
1249 //=======================================================================
ToPixMap(Image_PixMap & theImage,const Handle (V3d_View)& theView,const StdSelect_TypeOfSelectionImage theType,const Standard_Integer thePickedIndex)1250 Standard_Boolean SelectMgr_ViewerSelector::ToPixMap (Image_PixMap& theImage,
1251                                                      const Handle(V3d_View)& theView,
1252                                                      const StdSelect_TypeOfSelectionImage theType,
1253                                                      const Standard_Integer               thePickedIndex)
1254 {
1255   if (theImage.IsEmpty())
1256   {
1257     throw Standard_ProgramError ("SelectMgr_ViewerSelector::ToPixMap() has been called with empty image");
1258   }
1259 
1260   Handle(SelectMgr_SelectionImageFiller) aFiller = SelectMgr_SelectionImageFiller::CreateFiller (theImage, this, theType);
1261   if (aFiller.IsNull())
1262   {
1263     return Standard_False;
1264   }
1265 
1266   const Standard_Integer aSizeX = static_cast<Standard_Integer> (theImage.SizeX());
1267   const Standard_Integer aSizeY = static_cast<Standard_Integer> (theImage.SizeY());
1268   for (Standard_Integer aRowIter = 0; aRowIter < aSizeY; ++aRowIter)
1269   {
1270     for (Standard_Integer aColIter = 0; aColIter < aSizeX; ++aColIter)
1271     {
1272       Pick (aColIter, aRowIter, theView);
1273       aFiller->Fill (aColIter, aRowIter, thePickedIndex);
1274     }
1275   }
1276   aFiller->Flush();
1277   return Standard_True;
1278 }
1279 
1280 //=======================================================================
1281 // Function: DisplaySensitive.
1282 // Purpose : Display active primitives.
1283 //=======================================================================
DisplaySensitive(const Handle (V3d_View)& theView)1284 void SelectMgr_ViewerSelector::DisplaySensitive (const Handle(V3d_View)& theView)
1285 {
1286   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1287   {
1288     Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
1289     const Handle (SelectMgr_SelectableObject)& anObj = aSelectableIt.Value();
1290     for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
1291     {
1292       if (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated)
1293       {
1294         SelectMgr::ComputeSensitivePrs (aStruct, aSelIter.Value(), anObj->Transformation(), anObj->TransformPersistence());
1295       }
1296     }
1297 
1298     myStructs.Append (aStruct);
1299   }
1300 
1301   for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructs); aStructIter.More(); aStructIter.Next())
1302   {
1303     Handle(Graphic3d_Structure)& aStruct = aStructIter.ChangeValue();
1304     aStruct->SetDisplayPriority (10);
1305     aStruct->Display();
1306   }
1307 
1308   theView->Update();
1309 }
1310 
1311 //=======================================================================
1312 // Function: ClearSensitive
1313 // Purpose :
1314 //=======================================================================
ClearSensitive(const Handle (V3d_View)& theView)1315 void SelectMgr_ViewerSelector::ClearSensitive (const Handle(V3d_View)& theView)
1316 {
1317   for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructs); aStructIter.More(); aStructIter.Next())
1318   {
1319     const Handle(Graphic3d_Structure)& aPrs = aStructIter.ChangeValue();
1320     aPrs->Erase();
1321     aPrs->Clear();
1322     aPrs->Remove();
1323   }
1324   myStructs.Clear();
1325 
1326   if (!theView.IsNull())
1327   {
1328     theView->Update();
1329   }
1330 }
1331 
1332 //=======================================================================
1333 //function : DisplaySenstive
1334 //purpose  :
1335 //=======================================================================
DisplaySensitive(const Handle (SelectMgr_Selection)& theSel,const gp_Trsf & theTrsf,const Handle (V3d_View)& theView,const Standard_Boolean theToClearOthers)1336 void SelectMgr_ViewerSelector::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
1337                                                  const gp_Trsf& theTrsf,
1338                                                  const Handle(V3d_View)& theView,
1339                                                  const Standard_Boolean theToClearOthers)
1340 {
1341   if (theToClearOthers)
1342   {
1343     ClearSensitive (theView);
1344   }
1345 
1346   Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
1347 
1348   SelectMgr::ComputeSensitivePrs (aStruct, theSel, theTrsf, Handle(Graphic3d_TransformPers)());
1349 
1350   myStructs.Append (aStruct);
1351   myStructs.Last()->SetDisplayPriority (10);
1352   myStructs.Last()->Display();
1353 
1354   theView->Update();
1355 }
1356 
1357 //=======================================================================
1358 //function : DumpJson
1359 //purpose  :
1360 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const1361 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1362 {
1363   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1364 
1365   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1366   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1367 
1368   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1369   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1370 
1371   Standard_Integer aNbOfSelectableObjects = 0;
1372   for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1373   {
1374     aNbOfSelectableObjects++;
1375   }
1376   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1377 
1378   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1379   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1380   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1381 
1382   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1383   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1384   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1385   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1386 
1387   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes.Size())
1388 
1389   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1390   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1391 
1392   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myStructs.Length())
1393   for (Graphic3d_SequenceOfStructure::Iterator aStructsIt (myStructs); aStructsIt.More(); aStructsIt.Next())
1394   {
1395     const Handle(Graphic3d_Structure)& aStructure = aStructsIt.Value();
1396     OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, aStructure)
1397   }
1398 }
1399 
1400 //=======================================================================
1401 //function : SetToPrebuildBVH
1402 //purpose  :
1403 //=======================================================================
SetToPrebuildBVH(Standard_Boolean theToPrebuild,Standard_Integer theThreadsNum)1404 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1405 {
1406   if (!theToPrebuild && !myBVHThreadPool.IsNull())
1407   {
1408     myBVHThreadPool.Nullify();
1409   }
1410   else if (theToPrebuild)
1411   {
1412     myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1413   }
1414   myToPrebuildBVH = theToPrebuild;
1415 }
1416 
1417 //=======================================================================
1418 //function : QueueBVHBuild
1419 //purpose  :
1420 //=======================================================================
QueueBVHBuild(const Handle (Select3D_SensitiveEntity)& theEntity)1421 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1422 {
1423   if (myToPrebuildBVH)
1424   {
1425     myBVHThreadPool->AddEntity (theEntity);
1426   }
1427 }
1428 
1429 //=======================================================================
1430 //function : WaitForBVHBuild
1431 //purpose  :
1432 //=======================================================================
WaitForBVHBuild()1433 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1434 {
1435   if (myToPrebuildBVH)
1436   {
1437     myBVHThreadPool->WaitThreads();
1438   }
1439 }
1440