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