0026413: Visualization, SelectMgr_ViewerSelector - Pixel tolerance is overridden...
[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{
28ee613b 69 myLargestKey = -1.0;
70 myCustomTolerance = -1.0;
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//=======================================================================
f751596e 87void SelectMgr_ToleranceMap::Add (const Standard_Real& theTolerance)
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//=======================================================================
f751596e 116void SelectMgr_ToleranceMap::Decrement (const Standard_Real& theTolerance)
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 {
28ee613b 125 myLargestKey = 0.0;
f751596e 126 for (NCollection_DataMap<Standard_Real, 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{
f751596e 146 mySelectableObjects = new SelectMgr_SelectableObjectSet();
7fd59977 147}
148
149
150//==================================================
151// Function: Activate
152// Purpose :
153//==================================================
f751596e 154void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
7fd59977 155{
f751596e 156 for (theSelection->Init(); theSelection->More(); theSelection->Next())
7fd59977 157 {
f751596e 158 theSelection->Sensitive()->SetActiveForSelection();
4269bd1b 159 }
7fd59977 160
f751596e 161 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
7fd59977 162
f751596e 163 myTolerances.Add (theSelection->Sensitivity());
f751596e 164 myToUpdateTolerance = Standard_True;
7fd59977 165}
166
167
7fd59977 168//==================================================
f751596e 169// Function: Deactivate
7fd59977 170// Purpose :
171//==================================================
f751596e 172void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
4269bd1b 173{
f751596e 174 for (theSelection->Init(); theSelection->More(); theSelection->Next())
175 {
176 theSelection->Sensitive()->ResetSelectionActiveStatus();
7fd59977 177 }
7fd59977 178
f751596e 179 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
7fd59977 180
f751596e 181 myTolerances.Decrement (theSelection->Sensitivity());
f751596e 182 myToUpdateTolerance = Standard_True;
7fd59977 183}
184
7fd59977 185//==================================================
186// Function: Clear
187// Purpose :
188//==================================================
189void SelectMgr_ViewerSelector::Clear()
190{
7fd59977 191 mystored.Clear();
f751596e 192 myMapOfDetected.Clear();
7fd59977 193}
194
28ee613b 195//=======================================================================
196// function: isToScaleFrustum
197// purpose : Checks if the entity given requires to scale current selecting frustum
198//=======================================================================
199Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(SelectBasics_SensitiveEntity)& theEntity)
200{
201 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
29a4908e 202 && sensitivity (theEntity) < myTolerances.Tolerance();
28ee613b 203}
204
205//=======================================================================
206// function: scaleAndTransform
207// purpose : Applies given scale and transformation matrices to the default selecting volume manager
208//=======================================================================
209SelectMgr_SelectingVolumeManager SelectMgr_ViewerSelector::scaleAndTransform (const Standard_Real theScale,
210 const gp_Trsf& theTrsf)
211{
212 SelectMgr_SelectingVolumeManager aMgr;
213
214 if (theScale > Precision::Angular())
215 {
216 aMgr = mySelectingVolumeMgr.Scale (theScale);
217 }
218
219 if (theTrsf.Form() != gp_Identity)
220 {
221 aMgr = aMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Unknown ?
222 mySelectingVolumeMgr.Transform (theTrsf) : aMgr.Transform (theTrsf);
223 }
224
225 return aMgr;
226}
227
29a4908e 228//=======================================================================
229// function: sensitivity
230// purpose : In case if custom tolerance is set, this method will return sum of entity
231// sensitivity and custom tolerance.
232//=======================================================================
233Standard_Real SelectMgr_ViewerSelector::sensitivity (const Handle(SelectBasics_SensitiveEntity)& theEntity) const
234{
235 return myTolerances.IsCustomTolSet() ?
236 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
237}
238
f751596e 239//=======================================================================
240// function: checkOverlap
241// purpose : Internal function that checks if a particular sensitive
242// entity theEntity overlaps current selecting volume precisely
243//=======================================================================
244void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_SensitiveEntity)& theEntity,
245 const Standard_Integer theEntityIdx,
246 SelectMgr_SelectingVolumeManager& theMgr)
7fd59977 247{
c5f3a425 248 Handle(SelectMgr_EntityOwner) anOwner (Handle(SelectMgr_EntityOwner)::DownCast (theEntity->OwnerId()));
7fd59977 249
f751596e 250 SelectBasics_PickResult aPickResult;
251 if (theEntity->Matches (theMgr, aPickResult))
252 {
253 if (!anOwner.IsNull())
254 {
28ee613b 255 if (HasDepthClipping (anOwner) && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
f751596e 256 {
257 Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
258 aPickResult.Depth());
259 if (isClipped)
260 return;
261 }
7fd59977 262
f751596e 263 Standard_Integer aPriority = anOwner->Priority();
7fd59977 264
f751596e 265 SelectMgr_SortCriterion aCriterion (aPriority, aPickResult.Depth(), aPickResult.DistToGeomCenter(), theEntity->SensitivityFactor() / 33, preferclosest);
266 if (mystored.Contains (anOwner))
4269bd1b 267 {
f751596e 268 if (theMgr.GetActiveSelectionType() != 1)
269 {
270 SelectMgr_SortCriterion& aPrevCriterion = mystored.ChangeFromKey (anOwner);
271 if (aCriterion > aPrevCriterion)
272 {
273 aPrevCriterion = aCriterion;
274 myMapOfDetected.ChangeFind (anOwner) = theEntityIdx;
7fd59977 275 }
276 }
277 }
f751596e 278 else
279 {
280 mystored.Add (anOwner, aCriterion);
281 myMapOfDetected.Bind (anOwner, theEntityIdx);
7fd59977 282 }
283 }
7fd59977 284 }
285}
286
f751596e 287//=======================================================================
288// function: traverseObject
289// purpose : Internal function that checks if there is possible overlap
290// between some entity of selectable object theObject and
291// current selecting volume
292//=======================================================================
293void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject)
7fd59977 294{
f751596e 295 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
296 myMapOfObjectSensitives.ChangeFind (theObject);
7fd59977 297
f751596e 298 if (anEntitySet->Size() == 0)
299 return;
7fd59977 300
f751596e 301 const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
7fd59977 302
f751596e 303 SelectMgr_SelectingVolumeManager aMgr = theObject->HasTransformation() ?
304 mySelectingVolumeMgr.Transform (theObject->InversedTransformation()) : mySelectingVolumeMgr;
7fd59977 305
28ee613b 306 NCollection_DataMap<Handle(Standard_Type), SelectMgr_SelectingVolumeManager> aScaledTrnsfFrustums;
307
f751596e 308 Standard_Integer aNode = 0; // a root node
309 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
310 aSensitivesTree->MaxPoint (0)))
311 {
312 return;
7fd59977 313 }
f751596e 314 Standard_Integer aStack[32];
315 Standard_Integer aHead = -1;
316 for (;;)
317 {
318 if (!aSensitivesTree->IsOuter (aNode))
319 {
320 const Standard_Integer aLeftChildIdx = aSensitivesTree->LeftChild (aNode);
321 const Standard_Integer aRightChildIdx = aSensitivesTree->RightChild (aNode);
322 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
323 aSensitivesTree->MaxPoint (aLeftChildIdx));
324 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
325 aSensitivesTree->MaxPoint (aRightChildIdx));
326 if (isLeftChildIn
327 && isRightChildIn)
328 {
329 aNode = aLeftChildIdx;
330 ++aHead;
331 aStack[aHead] = aRightChildIdx;
332 }
333 else if (isLeftChildIn
334 || isRightChildIn)
335 {
336 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
337 }
338 else
339 {
340 if (aHead < 0)
341 {
342 break;
343 }
7fd59977 344
f751596e 345 aNode = aStack[aHead];
346 --aHead;
347 }
348 }
349 else
350 {
351 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
352 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
353 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
354 {
7ab15952 355 const Handle(SelectMgr_SensitiveEntity)& aSensitive =
f751596e 356 anEntitySet->GetSensitiveById (anIdx);
357 if (aSensitive->IsActiveForSelection())
358 {
28ee613b 359 const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
360 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
361 if (isToScaleFrustum (anEnt))
362 {
363 if (!aScaledTrnsfFrustums.IsBound (anEnt->DynamicType()))
364 {
365 aScaledTrnsfFrustums.Bind (anEnt->DynamicType(),
29a4908e 366 scaleAndTransform (sensitivity (anEnt), theObject->InversedTransformation()));
28ee613b 367 }
368
369 aTmpMgr = aScaledTrnsfFrustums.Find (anEnt->DynamicType());
370 }
371 checkOverlap (anEnt, anIdx, aTmpMgr);
f751596e 372 }
373 }
374 if (aHead < 0)
375 {
376 break;
377 }
7fd59977 378
f751596e 379 aNode = aStack[aHead];
380 --aHead;
381 }
7fd59977 382 }
383}
384
f751596e 385//=======================================================================
386// function: TraverseSensitives
387// purpose : Traverses BVH containing all added selectable objects and
388// finds candidates for further search of overlap
389//=======================================================================
390void SelectMgr_ViewerSelector::TraverseSensitives()
7fd59977 391{
392 mystored.Clear();
f751596e 393 myMapOfDetected.Clear();
7fd59977 394
f751596e 395 if (mySelectableObjects->Size() == 0)
396 return;
7fd59977 397
f751596e 398 const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& anObjectsTree = mySelectableObjects->BVH();
7fd59977 399
f751596e 400 Standard_Integer aNode = 0;
401 if (!mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (0),
402 anObjectsTree->MaxPoint (0)))
7fd59977 403 {
f751596e 404 return;
405 }
406 Standard_Integer aStack[32];
407 Standard_Integer aHead = -1;
408 for (;;)
409 {
410 if (!anObjectsTree->IsOuter (aNode))
4269bd1b 411 {
f751596e 412 const Standard_Integer aLeftChildIdx = anObjectsTree->LeftChild (aNode);
413 const Standard_Integer aRightChildIdx = anObjectsTree->RightChild (aNode);
414 const Standard_Boolean isLeftChildIn =
415 mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aLeftChildIdx),
416 anObjectsTree->MaxPoint (aLeftChildIdx));
417 const Standard_Boolean isRightChildIn =
418 mySelectingVolumeMgr.Overlaps (anObjectsTree->MinPoint (aRightChildIdx),
419 anObjectsTree->MaxPoint (aRightChildIdx));
420 if (isLeftChildIn
421 && isRightChildIn)
4269bd1b 422 {
f751596e 423 aNode = aLeftChildIdx;
424 ++aHead;
425 aStack[aHead] = aRightChildIdx;
426 }
427 else if (isLeftChildIn
428 || isRightChildIn)
429 {
430 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
431 }
432 else
433 {
434 if (aHead < 0)
4269bd1b 435 {
f751596e 436 break;
4269bd1b 437 }
7fd59977 438
f751596e 439 aNode = aStack[aHead];
440 --aHead;
7fd59977 441 }
442 }
f751596e 443 else
444 {
445 Standard_Integer aStartIdx = anObjectsTree->BegPrimitive (aNode);
446 Standard_Integer anEndIdx = anObjectsTree->EndPrimitive (aNode);
447 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
448 {
449 traverseObject (mySelectableObjects->GetObjectById (anIdx));
450 }
451 if (aHead < 0)
452 {
453 break;
454 }
4269bd1b 455
f751596e 456 aNode = aStack[aHead];
457 --aHead;
458 }
7fd59977 459 }
4269bd1b 460
f751596e 461 SortResult();
7fd59977 462}
4269bd1b 463
7fd59977 464//==================================================
465// Function: Picked
466// Purpose :
467//==================================================
468Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
469::Picked() const
470{
f751596e 471 Standard_Integer RankInMap = myIndexes->Value (myCurRank);
7fd59977 472 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
c5f3a425 473 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
7fd59977 474 return Ownr;
475}
476
477
478
479//=======================================================================
480//function : More
4269bd1b 481//purpose :
7fd59977 482//=======================================================================
4269bd1b 483Standard_Boolean SelectMgr_ViewerSelector::More()
7fd59977 484{
485 if(mystored.Extent()==0) return Standard_False;
486 if(myCurRank==0) return Standard_False;
487 return myCurRank <= myIndexes->Length();
488}
489
490//==================================================
491// Function: OnePicked
492// Purpose : only the best one is chosen
493// depend on priority and mindist...
494//==================================================
495
496Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
497::OnePicked()
498{
499
500 Init();
501 if(More()){
f751596e 502 Standard_Integer RankInMap = myIndexes->Value (myIndexes->Lower());
7fd59977 503 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
c5f3a425 504 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
7fd59977 505 return Ownr;
506 }
507
508 Handle (SelectMgr_EntityOwner) NullObj; //returns a null Handle if there was not successfull pick...
509 return NullObj;
510}
511
512
513//=======================================================================
514//function : NbPicked
4269bd1b 515//purpose :
7fd59977 516//=======================================================================
517
518Standard_Integer SelectMgr_ViewerSelector::NbPicked() const
519{
520 return mystored.Extent();
521}
522//=======================================================================
523//function : Picked
4269bd1b 524//purpose :
7fd59977 525//=======================================================================
526Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_Integer aRank) const
527{
528
f751596e 529 Handle(SelectMgr_EntityOwner) anOwner;
530 if (aRank < 1 || aRank > NbPicked())
531 return anOwner;
532 Standard_Integer anOwnerIdx = myIndexes->Value (aRank);
7fd59977 533
534
f751596e 535 const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
536 anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
537 return anOwner;
7fd59977 538}
539
7fd59977 540//===================================================
541//
542// INTERNAL METHODS ....
543//
544//==================================================
545
7fd59977 546//==================================================
547// Function: Contains
4269bd1b 548// Purpose :
7fd59977 549//==================================================
f751596e 550Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
7fd59977 551{
f751596e 552 return mySelectableObjects->Contains (theObject);
7fd59977 553}
554
7fd59977 555//==================================================
556// Function: ActiveModes
557// Purpose : return all the modes with a given state for an object
558//==================================================
f751596e 559Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
560 TColStd_ListOfInteger& theModeList,
561 const SelectMgr_StateOfSelection theWantedState) const
7fd59977 562{
f751596e 563 Standard_Boolean hasActivatedStates = mySelectableObjects->Contains (theSelectableObject);
564 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
565 {
566 if (theWantedState == SelectMgr_SOS_Any)
567 {
568 theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
569 }
570 else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
571 {
572 theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
573 }
7fd59977 574 }
7fd59977 575
f751596e 576 return hasActivatedStates;
577}
7fd59977 578
f751596e 579//==================================================
580// Function: IsActive
581// Purpose :
582//==================================================
583Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
584 const Standard_Integer theMode) const
7fd59977 585{
f751596e 586 if (!mySelectableObjects->Contains (theSelectableObject))
587 return Standard_False;
588
589 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
590 {
591 if (theMode == theSelectableObject->CurrentSelection()->Mode())
592 {
593 return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated;
7fd59977 594 }
595 }
f751596e 596
7fd59977 597 return Standard_False;
598}
599
f751596e 600//==================================================
601// Function: IsInside
602// Purpose :
603//==================================================
604Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
605 const Standard_Integer theMode) const
7fd59977 606{
f751596e 607 if (!mySelectableObjects->Contains (theSelectableObject))
608 return Standard_False;
7fd59977 609
f751596e 610 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
611 {
612 if (theMode == theSelectableObject->CurrentSelection()->Mode())
613 {
614 return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
7fd59977 615 }
616 }
f751596e 617
7fd59977 618 return Standard_False;
619}
620
621
622//=======================================================================
623//function : Status
4269bd1b 624//purpose :
7fd59977 625//=======================================================================
626
f751596e 627SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
7fd59977 628{
f751596e 629 return theSelection->GetSelectionState();
7fd59977 630}
631
7fd59977 632//==================================================
633// Function: Status
634// Purpose : gives Information about selectors
635//==================================================
636
f751596e 637TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
7fd59977 638{
f751596e 639 TCollection_AsciiString aStatus ("Status Object :\n\t");
640
641 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
642 {
643 if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
7fd59977 644 {
f751596e 645 aStatus = aStatus + "Mode " +
646 TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
647 " present - ";
648 if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
649 {
650 aStatus = aStatus + " Active \n\t";
651 }
7fd59977 652 else
f751596e 653 {
654 aStatus = aStatus + " Inactive \n\t";
655 }
7fd59977 656 }
657 }
658
f751596e 659 if (mySelectableObjects->Contains (theSelectableObject))
7fd59977 660 {
f751596e 661 aStatus = aStatus + "Not Present in the selector\n\n";
7fd59977 662 }
f751596e 663
664 return aStatus;
7fd59977 665}
666
667//=======================================================================
668//function : SortResult
4269bd1b 669//purpose : there is a certain number of entities ranged by criteria
81bba717 670// (depth, size, priority, mouse distance from borders or
671// CDG of the detected primitive. Parsing :
672// maximum priorities .
673// then a reasonable compromise between depth and distance...
674// finally the ranges are stored in myindexes depending on the parsing.
4269bd1b 675// so, it is possible to only read
7fd59977 676//=======================================================================
677void SelectMgr_ViewerSelector::SortResult()
678{
679 if(mystored.IsEmpty()) return;
680
681 const Standard_Integer anExtent = mystored.Extent();
682 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
683 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
684
81bba717 685 // to work faster...
7fd59977 686 TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
687
81bba717 688 // indices from 1 to N are loaded
7fd59977 689 Standard_Integer I ;
690 for (I=1; I <= anExtent; I++)
691 thearr(I)=I;
692
e35db416 693 std::sort (thearr.begin(), thearr.end(), CompareResults (mystored));
694
f751596e 695}
696
697//=======================================================================
698//function : HasDepthClipping
699//purpose : Stub
700//=======================================================================
701Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
702{
703 return Standard_False;
704}
705
706//=======================================================================
707// function : AddSelectableObject
708// purpose : Adds new object to the map of selectable objects
709//=======================================================================
710void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
711{
712 if (!myMapOfObjectSensitives.IsBound (theObject))
713 {
714 mySelectableObjects->Append (theObject);
715 NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
716 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
7fd59977 717 }
f751596e 718}
7fd59977 719
f751596e 720//=======================================================================
721// function : AddSelectionToObject
722// purpose : Adds new selection to the object and builds its BVH tree
723//=======================================================================
724void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
725 const Handle(SelectMgr_Selection)& theSelection)
726{
727 if (myMapOfObjectSensitives.IsBound (theObject))
728 {
729 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
730 myMapOfObjectSensitives.ChangeFind (theObject);
731 anEntitySet->Append (theSelection);
732 anEntitySet->BVH();
733 }
734 else
735 {
736 AddSelectableObject (theObject);
737 AddSelectionToObject (theObject, theSelection);
738 }
7fd59977 739}
740
f751596e 741//=======================================================================
742// function : RemoveSelectableObject
743// purpose : Removes selectable object from map of selectable ones
744//=======================================================================
745void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
746{
747 if (myMapOfObjectSensitives.IsBound (theObject))
748 {
749 myMapOfObjectSensitives.UnBind (theObject);
750 mySelectableObjects->Remove (theObject);
751 }
752}
7fd59977 753
754//=======================================================================
f751596e 755// function : RemoveSelectionOfObject
756// purpose : Removes selection of the object and marks its BVH tree
757// for rebuild
7fd59977 758//=======================================================================
f751596e 759void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
760 const Handle(SelectMgr_Selection)& theSelection)
7fd59977 761{
f751596e 762 if (myMapOfObjectSensitives.IsBound (theObject))
763 {
764 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
765 myMapOfObjectSensitives.ChangeFind (theObject);
766 anEntitySet->Remove (theSelection);
767 }
7fd59977 768}
769
770//=======================================================================
f751596e 771// function : RebuildObjectsTree
772// purpose : Marks BVH of selectable objects for rebuild
7fd59977 773//=======================================================================
f751596e 774void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
7fd59977 775{
f751596e 776 mySelectableObjects->MarkDirty();
777
778 if (theIsForce)
779 {
780 mySelectableObjects->BVH();
781 }
7fd59977 782}
4269bd1b 783
784//=======================================================================
f751596e 785// function : RebuildSensitivesTree
786// purpose : Marks BVH of sensitive entities of particular selectable
787// object for rebuild
4269bd1b 788//=======================================================================
f751596e 789void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
790 const Standard_Boolean theIsForce)
4269bd1b 791{
f751596e 792 if (!mySelectableObjects->Contains (theObject))
793 return;
794
795 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
796 anEntitySet->MarkDirty();
797
798 if (theIsForce)
799 {
800 anEntitySet->BVH();
801 }
4269bd1b 802}
803
804//=======================================================================
f751596e 805// function : resetSelectionActivationStatus
806// purpose : Marks all added sensitive entities of all objects as
807// non-selectable
4269bd1b 808//=======================================================================
29a4908e 809void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
4269bd1b 810{
f751596e 811 SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
812 for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
813 {
814 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
815 aSensitivesIter.ChangeValue();
816 Standard_Integer anEntitiesNb = anEntitySet->Size();
817 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
818 {
819 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
820 }
821 }
4269bd1b 822}
823
824//=======================================================================
f751596e 825// function : DetectedEntity
826// purpose : Returns sensitive entity that was detected during the
827// previous run of selection algorithm
4269bd1b 828//=======================================================================
f751596e 829const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
4269bd1b 830{
f751596e 831 const Handle(SelectMgr_EntityOwner)& anOwner = myDetectedIter.Key();
832 const Handle(SelectMgr_SelectableObject)& anObject = anOwner->Selectable();
833 const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
834 myMapOfObjectSensitives.Find (anObject);
835
836 return anEntitySet->GetSensitiveById (myDetectedIter.Value())->BaseSensitive();
4269bd1b 837}
838
839//=======================================================================
f751596e 840// function : ActiveOwners
841// purpose : Returns the list of active entity owners
4269bd1b 842//=======================================================================
751955d4 843void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
4269bd1b 844{
f751596e 845 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
846 {
847 const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
848 Standard_Integer anEntitiesNb = anEntitySet->Size();
849 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
850 {
851 if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
852 {
751955d4 853 theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
f751596e 854 }
855 }
856 }
4269bd1b 857}
29a4908e 858
859//=======================================================================
860//function : AllowOverlapDetection
861//purpose : Sets the detection type: if theIsToAllow is false,
862// only fully included sensitives will be detected, otherwise
863// the algorithm will mark both included and overlapped entities
864// as matched
865//=======================================================================
866void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
867{
868 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
869}