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