0022632: Visualization - provide logarithmic scale for Aspect_ColorScale class
[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{
272 Standard_Integer aScale = 1;
273 const Standard_Boolean toScale = isToScaleFrustum (theEnt);
274 if (toScale)
275 {
276 aScale = sensitivity (theEnt);
277 }
278 if (theEnt->HasInitLocation())
279 {
280 theResMgr =
281 mySelectingVolumeMgr.ScaleAndTransform (aScale, theEnt->InvInitLocation() * theInvTrsf);
282 }
283 else if (toScale)
284 {
285 if (!theCachedMgrs.IsBound (aScale))
286 {
287 theCachedMgrs.Bind (aScale,
288 mySelectingVolumeMgr.ScaleAndTransform(aScale, theInvTrsf));
289 }
290
291 theResMgr = theCachedMgrs.Find (aScale);
292 }
293}
294
f751596e 295//=======================================================================
296// function: traverseObject
297// purpose : Internal function that checks if there is possible overlap
298// between some entity of selectable object theObject and
299// current selecting volume
300//=======================================================================
301void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject)
7fd59977 302{
f751596e 303 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
304 myMapOfObjectSensitives.ChangeFind (theObject);
7fd59977 305
f751596e 306 if (anEntitySet->Size() == 0)
307 return;
7fd59977 308
f751596e 309 const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
7fd59977 310
825aa485 311 gp_Trsf aInversedTrsf;
312
313 if (theObject->HasTransformation() || theObject->TransformPersistence().Flags)
314 {
315 if (!theObject->TransformPersistence().Flags)
316 {
317 aInversedTrsf = theObject->InversedTransformation();
318 }
319 else
320 {
321 const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix();
322 const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix();
323
324 gp_Trsf aTPers;
325 Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (aProjection, aWorldView, 0, 0);
326 aTPers.SetValues (aMat.GetValue (0, 0), aMat.GetValue (0, 1), aMat.GetValue (0, 2), aMat.GetValue (0, 3),
327 aMat.GetValue (1, 0), aMat.GetValue (1, 1), aMat.GetValue (1, 2), aMat.GetValue (1, 3),
328 aMat.GetValue (2, 0), aMat.GetValue (2, 1), aMat.GetValue (2, 2), aMat.GetValue (2, 3));
329
330 aInversedTrsf = (aTPers * theObject->Transformation()).Inverted();
331 }
332 }
333
334 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
3bf9a45f 335 ? mySelectingVolumeMgr.ScaleAndTransform (1, aInversedTrsf)
825aa485 336 : mySelectingVolumeMgr;
7fd59977 337
3bf9a45f 338 SelectMgr_FrustumCache aScaledTrnsfFrustums;
28ee613b 339
f751596e 340 Standard_Integer aNode = 0; // a root node
341 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
342 aSensitivesTree->MaxPoint (0)))
343 {
344 return;
7fd59977 345 }
f751596e 346 Standard_Integer aStack[32];
347 Standard_Integer aHead = -1;
348 for (;;)
349 {
350 if (!aSensitivesTree->IsOuter (aNode))
351 {
352 const Standard_Integer aLeftChildIdx = aSensitivesTree->LeftChild (aNode);
353 const Standard_Integer aRightChildIdx = aSensitivesTree->RightChild (aNode);
354 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
355 aSensitivesTree->MaxPoint (aLeftChildIdx));
356 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
357 aSensitivesTree->MaxPoint (aRightChildIdx));
358 if (isLeftChildIn
359 && isRightChildIn)
360 {
361 aNode = aLeftChildIdx;
362 ++aHead;
363 aStack[aHead] = aRightChildIdx;
364 }
365 else if (isLeftChildIn
366 || isRightChildIn)
367 {
368 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
369 }
370 else
371 {
372 if (aHead < 0)
373 {
374 break;
375 }
7fd59977 376
f751596e 377 aNode = aStack[aHead];
378 --aHead;
379 }
380 }
381 else
382 {
383 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
384 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
385 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
386 {
7ab15952 387 const Handle(SelectMgr_SensitiveEntity)& aSensitive =
f751596e 388 anEntitySet->GetSensitiveById (anIdx);
389 if (aSensitive->IsActiveForSelection())
390 {
28ee613b 391 const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
392 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
3bf9a45f 393 computeFrustum (anEnt, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
28ee613b 394 checkOverlap (anEnt, anIdx, aTmpMgr);
f751596e 395 }
396 }
397 if (aHead < 0)
398 {
399 break;
400 }
7fd59977 401
f751596e 402 aNode = aStack[aHead];
403 --aHead;
404 }
7fd59977 405 }
406}
407
f751596e 408//=======================================================================
409// function: TraverseSensitives
410// purpose : Traverses BVH containing all added selectable objects and
411// finds candidates for further search of overlap
412//=======================================================================
413void SelectMgr_ViewerSelector::TraverseSensitives()
7fd59977 414{
415 mystored.Clear();
f751596e 416 myMapOfDetected.Clear();
7fd59977 417
825aa485 418 NCollection_Handle<BVH_Tree<Standard_Real, 3> > aBVHTree;
419 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
f751596e 420 {
825aa485 421 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
422 if (isTrsfPers)
4269bd1b 423 {
825aa485 424 if (mySelectableObjectsTrsfPers.Size() == 0)
4269bd1b 425 {
825aa485 426 continue;
f751596e 427 }
825aa485 428 const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix();
429 const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix();
430 const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState();
431 aBVHTree = mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState);
432 }
433 else
434 {
435 if (mySelectableObjects.Size() == 0)
f751596e 436 {
825aa485 437 continue;
438 }
439 aBVHTree = mySelectableObjects.BVH();
440 }
441
442 Standard_Integer aNode = 0;
443 if (!mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (0),
444 aBVHTree->MaxPoint (0)))
445 {
446 continue;
447 }
448
449 Standard_Integer aStack[32];
450 Standard_Integer aHead = -1;
451 for (;;)
452 {
453 if (!aBVHTree->IsOuter (aNode))
454 {
455 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
456 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
457 const Standard_Boolean isLeftChildIn =
458 mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
459 aBVHTree->MaxPoint (aLeftChildIdx));
460 const Standard_Boolean isRightChildIn =
461 mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx),
462 aBVHTree->MaxPoint (aRightChildIdx));
463 if (isLeftChildIn
464 && isRightChildIn)
465 {
466 aNode = aLeftChildIdx;
467 ++aHead;
468 aStack[aHead] = aRightChildIdx;
469 }
470 else if (isLeftChildIn
471 || isRightChildIn)
472 {
473 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
474 }
475 else
476 {
477 if (aHead < 0)
478 {
479 break;
480 }
481
482 aNode = aStack[aHead];
483 --aHead;
484 }
f751596e 485 }
486 else
487 {
825aa485 488 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
489 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
490 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
491 {
492 Handle(SelectMgr_SelectableObject) aSelectableObject =
493 isTrsfPers ? mySelectableObjectsTrsfPers.GetObjectById (anIdx)
494 : mySelectableObjects.GetObjectById (anIdx);
495
496 traverseObject (aSelectableObject);
497 }
f751596e 498 if (aHead < 0)
4269bd1b 499 {
f751596e 500 break;
4269bd1b 501 }
7fd59977 502
f751596e 503 aNode = aStack[aHead];
504 --aHead;
7fd59977 505 }
506 }
7fd59977 507 }
4269bd1b 508
f751596e 509 SortResult();
7fd59977 510}
4269bd1b 511
7fd59977 512//==================================================
513// Function: Picked
514// Purpose :
515//==================================================
516Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
517::Picked() const
518{
f751596e 519 Standard_Integer RankInMap = myIndexes->Value (myCurRank);
7fd59977 520 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
c5f3a425 521 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
7fd59977 522 return Ownr;
523}
524
525
526
527//=======================================================================
528//function : More
4269bd1b 529//purpose :
7fd59977 530//=======================================================================
4269bd1b 531Standard_Boolean SelectMgr_ViewerSelector::More()
7fd59977 532{
533 if(mystored.Extent()==0) return Standard_False;
534 if(myCurRank==0) return Standard_False;
535 return myCurRank <= myIndexes->Length();
536}
537
538//==================================================
539// Function: OnePicked
540// Purpose : only the best one is chosen
541// depend on priority and mindist...
542//==================================================
543
544Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector
545::OnePicked()
546{
547
548 Init();
549 if(More()){
f751596e 550 Standard_Integer RankInMap = myIndexes->Value (myIndexes->Lower());
7fd59977 551 const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap);
c5f3a425 552 Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto);
7fd59977 553 return Ownr;
554 }
555
556 Handle (SelectMgr_EntityOwner) NullObj; //returns a null Handle if there was not successfull pick...
557 return NullObj;
558}
559
560
561//=======================================================================
562//function : NbPicked
4269bd1b 563//purpose :
7fd59977 564//=======================================================================
565
566Standard_Integer SelectMgr_ViewerSelector::NbPicked() const
567{
568 return mystored.Extent();
569}
570//=======================================================================
571//function : Picked
4269bd1b 572//purpose :
7fd59977 573//=======================================================================
574Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_Integer aRank) const
575{
576
f751596e 577 Handle(SelectMgr_EntityOwner) anOwner;
578 if (aRank < 1 || aRank > NbPicked())
579 return anOwner;
580 Standard_Integer anOwnerIdx = myIndexes->Value (aRank);
7fd59977 581
582
f751596e 583 const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
584 anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner);
585 return anOwner;
7fd59977 586}
587
7fd59977 588//===================================================
589//
590// INTERNAL METHODS ....
591//
592//==================================================
593
7fd59977 594//==================================================
595// Function: Contains
4269bd1b 596// Purpose :
7fd59977 597//==================================================
f751596e 598Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
7fd59977 599{
825aa485 600 return mySelectableObjects.Contains (theObject)
601 || mySelectableObjectsTrsfPers.Contains (theObject);
7fd59977 602}
603
7fd59977 604//==================================================
605// Function: ActiveModes
606// Purpose : return all the modes with a given state for an object
607//==================================================
f751596e 608Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
609 TColStd_ListOfInteger& theModeList,
610 const SelectMgr_StateOfSelection theWantedState) const
7fd59977 611{
825aa485 612 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
f751596e 613 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
614 {
615 if (theWantedState == SelectMgr_SOS_Any)
616 {
617 theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
618 }
619 else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState())
620 {
621 theModeList.Append (theSelectableObject->CurrentSelection()->Mode());
622 }
7fd59977 623 }
7fd59977 624
f751596e 625 return hasActivatedStates;
626}
7fd59977 627
f751596e 628//==================================================
629// Function: IsActive
630// Purpose :
631//==================================================
632Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
633 const Standard_Integer theMode) const
7fd59977 634{
825aa485 635 if (!Contains (theSelectableObject))
f751596e 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_Activated;
7fd59977 643 }
644 }
f751596e 645
7fd59977 646 return Standard_False;
647}
648
f751596e 649//==================================================
650// Function: IsInside
651// Purpose :
652//==================================================
653Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
654 const Standard_Integer theMode) const
7fd59977 655{
825aa485 656 if (!Contains (theSelectableObject))
f751596e 657 return Standard_False;
7fd59977 658
f751596e 659 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
660 {
661 if (theMode == theSelectableObject->CurrentSelection()->Mode())
662 {
663 return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown;
7fd59977 664 }
665 }
f751596e 666
7fd59977 667 return Standard_False;
668}
669
670
671//=======================================================================
672//function : Status
4269bd1b 673//purpose :
7fd59977 674//=======================================================================
675
f751596e 676SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
7fd59977 677{
f751596e 678 return theSelection->GetSelectionState();
7fd59977 679}
680
7fd59977 681//==================================================
682// Function: Status
683// Purpose : gives Information about selectors
684//==================================================
685
f751596e 686TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
7fd59977 687{
f751596e 688 TCollection_AsciiString aStatus ("Status Object :\n\t");
689
690 for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next())
691 {
692 if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown)
7fd59977 693 {
f751596e 694 aStatus = aStatus + "Mode " +
695 TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) +
696 " present - ";
697 if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
698 {
699 aStatus = aStatus + " Active \n\t";
700 }
7fd59977 701 else
f751596e 702 {
703 aStatus = aStatus + " Inactive \n\t";
704 }
7fd59977 705 }
706 }
707
825aa485 708 if (!Contains (theSelectableObject))
7fd59977 709 {
f751596e 710 aStatus = aStatus + "Not Present in the selector\n\n";
7fd59977 711 }
f751596e 712
713 return aStatus;
7fd59977 714}
715
716//=======================================================================
717//function : SortResult
4269bd1b 718//purpose : there is a certain number of entities ranged by criteria
81bba717 719// (depth, size, priority, mouse distance from borders or
720// CDG of the detected primitive. Parsing :
721// maximum priorities .
722// then a reasonable compromise between depth and distance...
723// finally the ranges are stored in myindexes depending on the parsing.
4269bd1b 724// so, it is possible to only read
7fd59977 725//=======================================================================
726void SelectMgr_ViewerSelector::SortResult()
727{
728 if(mystored.IsEmpty()) return;
729
730 const Standard_Integer anExtent = mystored.Extent();
731 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
732 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
733
81bba717 734 // to work faster...
7fd59977 735 TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1();
736
81bba717 737 // indices from 1 to N are loaded
7fd59977 738 Standard_Integer I ;
739 for (I=1; I <= anExtent; I++)
740 thearr(I)=I;
741
e35db416 742 std::sort (thearr.begin(), thearr.end(), CompareResults (mystored));
743
f751596e 744}
745
746//=======================================================================
747//function : HasDepthClipping
748//purpose : Stub
749//=======================================================================
750Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
751{
752 return Standard_False;
753}
754
755//=======================================================================
756// function : AddSelectableObject
757// purpose : Adds new object to the map of selectable objects
758//=======================================================================
759void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
760{
761 if (!myMapOfObjectSensitives.IsBound (theObject))
762 {
825aa485 763 if (!theObject->TransformPersistence().Flags)
764 {
765 mySelectableObjects.Append (theObject);
766 }
767 else
768 {
769 mySelectableObjectsTrsfPers.Append (theObject);
770 }
771
f751596e 772 NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet();
773 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
7fd59977 774 }
f751596e 775}
7fd59977 776
f751596e 777//=======================================================================
778// function : AddSelectionToObject
779// purpose : Adds new selection to the object and builds its BVH tree
780//=======================================================================
781void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
782 const Handle(SelectMgr_Selection)& theSelection)
783{
784 if (myMapOfObjectSensitives.IsBound (theObject))
785 {
786 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
787 myMapOfObjectSensitives.ChangeFind (theObject);
788 anEntitySet->Append (theSelection);
789 anEntitySet->BVH();
790 }
791 else
792 {
793 AddSelectableObject (theObject);
794 AddSelectionToObject (theObject, theSelection);
795 }
7fd59977 796}
797
f751596e 798//=======================================================================
799// function : RemoveSelectableObject
800// purpose : Removes selectable object from map of selectable ones
801//=======================================================================
802void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
803{
804 if (myMapOfObjectSensitives.IsBound (theObject))
805 {
825aa485 806 if (!mySelectableObjects.Remove (theObject))
807 {
808 mySelectableObjectsTrsfPers.Remove (theObject);
809 }
f751596e 810 myMapOfObjectSensitives.UnBind (theObject);
f751596e 811 }
812}
7fd59977 813
814//=======================================================================
f751596e 815// function : RemoveSelectionOfObject
816// purpose : Removes selection of the object and marks its BVH tree
817// for rebuild
7fd59977 818//=======================================================================
f751596e 819void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
820 const Handle(SelectMgr_Selection)& theSelection)
7fd59977 821{
f751596e 822 if (myMapOfObjectSensitives.IsBound (theObject))
823 {
824 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
825 myMapOfObjectSensitives.ChangeFind (theObject);
826 anEntitySet->Remove (theSelection);
827 }
7fd59977 828}
829
830//=======================================================================
f751596e 831// function : RebuildObjectsTree
832// purpose : Marks BVH of selectable objects for rebuild
7fd59977 833//=======================================================================
f751596e 834void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
7fd59977 835{
825aa485 836 mySelectableObjects.MarkDirty();
837 mySelectableObjectsTrsfPers.MarkDirty();
f751596e 838
839 if (theIsForce)
840 {
825aa485 841 const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix();
842 const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix();
843 const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState();
844
845 mySelectableObjects.BVH();
846 mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState);
f751596e 847 }
7fd59977 848}
4269bd1b 849
850//=======================================================================
f751596e 851// function : RebuildSensitivesTree
852// purpose : Marks BVH of sensitive entities of particular selectable
853// object for rebuild
4269bd1b 854//=======================================================================
f751596e 855void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
856 const Standard_Boolean theIsForce)
4269bd1b 857{
825aa485 858 if (!Contains (theObject))
f751596e 859 return;
860
861 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
862 anEntitySet->MarkDirty();
863
864 if (theIsForce)
865 {
866 anEntitySet->BVH();
867 }
4269bd1b 868}
869
870//=======================================================================
f751596e 871// function : resetSelectionActivationStatus
872// purpose : Marks all added sensitive entities of all objects as
873// non-selectable
4269bd1b 874//=======================================================================
29a4908e 875void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
4269bd1b 876{
f751596e 877 SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives);
878 for ( ; aSensitivesIter.More(); aSensitivesIter.Next())
879 {
880 NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
881 aSensitivesIter.ChangeValue();
882 Standard_Integer anEntitiesNb = anEntitySet->Size();
883 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
884 {
885 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
886 }
887 }
4269bd1b 888}
889
890//=======================================================================
f751596e 891// function : DetectedEntity
892// purpose : Returns sensitive entity that was detected during the
893// previous run of selection algorithm
4269bd1b 894//=======================================================================
f751596e 895const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
4269bd1b 896{
f751596e 897 const Handle(SelectMgr_EntityOwner)& anOwner = myDetectedIter.Key();
898 const Handle(SelectMgr_SelectableObject)& anObject = anOwner->Selectable();
899 const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet =
900 myMapOfObjectSensitives.Find (anObject);
901
902 return anEntitySet->GetSensitiveById (myDetectedIter.Value())->BaseSensitive();
4269bd1b 903}
904
905//=======================================================================
f751596e 906// function : ActiveOwners
907// purpose : Returns the list of active entity owners
4269bd1b 908//=======================================================================
751955d4 909void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const
4269bd1b 910{
f751596e 911 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
912 {
913 const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value();
914 Standard_Integer anEntitiesNb = anEntitySet->Size();
915 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
916 {
917 if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection())
918 {
751955d4 919 theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId());
f751596e 920 }
921 }
922 }
4269bd1b 923}
29a4908e 924
925//=======================================================================
926//function : AllowOverlapDetection
927//purpose : Sets the detection type: if theIsToAllow is false,
928// only fully included sensitives will be detected, otherwise
929// the algorithm will mark both included and overlapped entities
930// as matched
931//=======================================================================
932void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
933{
934 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
935}