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