0030687: Visualization - remove redundant interfaces SelectBasics_EntityOwner and...
[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
aa75c0cf 17#include <SelectMgr_ViewerSelector.hxx>
7fd59977 18
f751596e 19#include <BVH_Tree.hxx>
91d96372 20#include <gp_GTrsf.hxx>
7fd59977 21#include <gp_Pnt.hxx>
f751596e 22#include <OSD_Environment.hxx>
7fd59977 23#include <Precision.hxx>
0ef04197 24#include <Select3D_SensitiveEntity.hxx>
f751596e 25#include <SelectBasics_PickResult.hxx>
26#include <SelectMgr_EntityOwner.hxx>
7fd59977 27#include <SelectMgr_SortCriterion.hxx>
f751596e 28#include <SelectMgr_SensitiveEntitySet.hxx>
f751596e 29#include <TColStd_Array1OfInteger.hxx>
30#include <TCollection_AsciiString.hxx>
31#include <TColStd_HArray1OfInteger.hxx>
32#include <TColStd_ListOfInteger.hxx>
33
e35db416 34#include <algorithm>
35
f5b72419 36IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
92efcf78 37
e35db416 38namespace {
39 // Comparison operator for sorting selection results
40 class CompareResults
41 {
42 public:
43
44 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& aMapOfCriterion)
45 : myMapOfCriterion (aMapOfCriterion)
46 {
47 }
48
49 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
50 {
51 return myMapOfCriterion.FindFromIndex(theLeft) > myMapOfCriterion.FindFromIndex(theRight);
52 }
53
54 private:
55 void operator = (const CompareResults&);
56
57 private:
58 const SelectMgr_IndexedDataMapOfOwnerCriterion& myMapOfCriterion;
59 };
f751596e 60
fe76088c 61 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
62}
63
64//=======================================================================
65// function : updatePoint3d
66// purpose :
67//=======================================================================
68void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
17017555 69 const SelectBasics_PickResult& thePickResult,
0ef04197 70 const Handle(Select3D_SensitiveEntity)& theEntity,
fe76088c 71 const gp_GTrsf& theInversedTrsf,
72 const SelectMgr_SelectingVolumeManager& theMgr) const
73{
74 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectingVolumeManager::Point)
4269bd1b 75 {
fe76088c 76 return;
77 }
949c9b7f 78
17017555 79 if (thePickResult.HasPickedPoint())
80 {
81 theCriterion.Point = thePickResult.PickedPoint();
82 }
b44bf0f8 83 else if (!thePickResult.IsValid())
84 {
85 theCriterion.Point = thePickResult.PickedPoint();
86 return;
87 }
17017555 88 else
89 {
90 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
91 }
92
fe76088c 93 gp_GTrsf anInvTrsf = theInversedTrsf;
94 if (theCriterion.Entity->HasInitLocation())
95 {
96 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
97 }
98 if (anInvTrsf.Form() != gp_Identity)
99 {
100 anInvTrsf.Inverted().Transforms (theCriterion.Point.ChangeCoord());
f751596e 101 }
aa75c0cf 102
fe76088c 103 if (mySelectingVolumeMgr.Camera().IsNull())
104 {
105 theCriterion.Tolerance = theEntity->SensitivityFactor() / 33.0;
106 }
107 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
108 {
109 theCriterion.Tolerance = myCameraScale * theEntity->SensitivityFactor();
110 }
111 else
112 {
b44bf0f8 113 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
fe76088c 114 theCriterion.Tolerance = aDistFromEye * myCameraScale * theEntity->SensitivityFactor();
115 }
f751596e 116}
117
7fd59977 118//==================================================
119// Function: Initialize
120// Purpose :
121//==================================================
122SelectMgr_ViewerSelector::SelectMgr_ViewerSelector():
7fd59977 123preferclosest(Standard_True),
f751596e 124myToUpdateTolerance (Standard_True),
fe76088c 125myCameraScale (1.0),
f751596e 126myCurRank (0),
127myIsLeftChildQueuedFirst (Standard_False),
128myEntityIdx (0)
7fd59977 129{
f5b72419 130 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
7fd59977 131}
132
7fd59977 133//==================================================
134// Function: Activate
135// Purpose :
136//==================================================
f751596e 137void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
7fd59977 138{
b5cce1ab 139 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
7fd59977 140 {
b5cce1ab 141 aSelEntIter.Value()->SetActiveForSelection();
4269bd1b 142 }
7fd59977 143
82d23ad5 144 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
145 {
146 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
7fd59977 147
82d23ad5 148 myTolerances.Add (theSelection->Sensitivity());
149 myToUpdateTolerance = Standard_True;
150 }
7fd59977 151}
152
7fd59977 153//==================================================
f751596e 154// Function: Deactivate
7fd59977 155// Purpose :
156//==================================================
f751596e 157void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
4269bd1b 158{
b5cce1ab 159 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
f751596e 160 {
b5cce1ab 161 aSelEntIter.Value()->ResetSelectionActiveStatus();
7fd59977 162 }
7fd59977 163
82d23ad5 164 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
165 {
166 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
7fd59977 167
82d23ad5 168 myTolerances.Decrement (theSelection->Sensitivity());
169 myToUpdateTolerance = Standard_True;
170 }
7fd59977 171}
172
7fd59977 173//==================================================
174// Function: Clear
175// Purpose :
176//==================================================
177void SelectMgr_ViewerSelector::Clear()
178{
7fd59977 179 mystored.Clear();
7fd59977 180}
181
28ee613b 182//=======================================================================
183// function: isToScaleFrustum
184// purpose : Checks if the entity given requires to scale current selecting frustum
185//=======================================================================
0ef04197 186Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
28ee613b 187{
188 return mySelectingVolumeMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point
29a4908e 189 && sensitivity (theEntity) < myTolerances.Tolerance();
28ee613b 190}
191
29a4908e 192//=======================================================================
193// function: sensitivity
194// purpose : In case if custom tolerance is set, this method will return sum of entity
195// sensitivity and custom tolerance.
196//=======================================================================
0ef04197 197Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
29a4908e 198{
199 return myTolerances.IsCustomTolSet() ?
200 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
201}
202
f751596e 203//=======================================================================
204// function: checkOverlap
205// purpose : Internal function that checks if a particular sensitive
206// entity theEntity overlaps current selecting volume precisely
207//=======================================================================
0ef04197 208void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
aa75c0cf 209 const gp_GTrsf& theInversedTrsf,
f751596e 210 SelectMgr_SelectingVolumeManager& theMgr)
7fd59977 211{
0ef04197 212 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
3202bf1e 213 Handle(SelectMgr_SelectableObject) aSelectable;
214 Standard_Boolean toRestoresViewClipEnabled = Standard_False;
215 if (!anOwner.IsNull())
216 {
217 aSelectable = anOwner->Selectable();
b1c235df 218 }
219 if (!aSelectable.IsNull())
220 {
8b1441e3 221 if (!aSelectable->ClipPlanes().IsNull()
222 && aSelectable->ClipPlanes()->ToOverrideGlobal())
3202bf1e 223 {
224 theMgr.SetViewClippingEnabled (Standard_False);
225 toRestoresViewClipEnabled = Standard_True;
226 }
8b1441e3 227 else if (!aSelectable->TransformPersistence().IsNull())
228 {
229 if (aSelectable->TransformPersistence()->IsZoomOrRotate()
230 && !theMgr.ViewClipping().IsNull())
231 {
232 // Zoom/rotate persistence object lives in two worlds at the same time.
233 // Global clipping planes can not be trivially applied without being converted
234 // into local space of transformation persistence object.
235 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
236 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
237
238 const gp_Pnt anAnchor = aSelectable->TransformPersistence()->AnchorPoint();
239 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
240 {
241 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
242 if (!aPlane->IsOn())
243 {
244 continue;
245 }
246
25c35042 247 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
248 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
8b1441e3 249 {
250 return;
251 }
252 }
253 }
254
255 theMgr.SetViewClippingEnabled (Standard_False);
256 toRestoresViewClipEnabled = Standard_True;
257 }
3202bf1e 258 }
7fd59977 259
f751596e 260 SelectBasics_PickResult aPickResult;
3202bf1e 261 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
262 if (toRestoresViewClipEnabled)
f751596e 263 {
3202bf1e 264 theMgr.SetViewClippingEnabled (Standard_True);
265 }
7fd59977 266
3202bf1e 267 if (!isMatched
268 || anOwner.IsNull())
269 {
270 return;
271 }
272
273 if (HasDepthClipping (anOwner)
b1c235df 274 && !aSelectable.IsNull()
3202bf1e 275 && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
276 {
277 Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (*aSelectable->ClipPlanes(),
278 aPickResult.Depth());
279 if (isClipped)
280 return;
281 }
282
283 SelectMgr_SortCriterion aCriterion;
b1c235df 284 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
3202bf1e 285 aCriterion.Entity = theEntity;
286 aCriterion.Priority = anOwner->Priority();
287 aCriterion.Depth = aPickResult.Depth();
288 aCriterion.MinDist = aPickResult.DistToGeomCenter();
3202bf1e 289 aCriterion.ToPreferClosest = preferclosest;
290
be7fc29e 291 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
3202bf1e 292 {
be7fc29e 293 ++aPrevCriterion->NbOwnerMatches;
294 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
3202bf1e 295 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box)
296 {
be7fc29e 297 if (aCriterion > *aPrevCriterion)
f751596e 298 {
17017555 299 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
be7fc29e 300 *aPrevCriterion = aCriterion;
7fd59977 301 }
302 }
7fd59977 303 }
3202bf1e 304 else
305 {
be7fc29e 306 aCriterion.NbOwnerMatches = 1;
17017555 307 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
3202bf1e 308 mystored.Add (anOwner, aCriterion);
309 }
7fd59977 310}
311
3bf9a45f 312//=======================================================================
313// function: computeFrustum
314// purpose : Internal function that checks if a current selecting frustum
315// needs to be scaled and transformed for the entity and performs
316// necessary calculations
317//=======================================================================
0ef04197 318void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
099f3513 319 const SelectMgr_SelectingVolumeManager& theMgr,
91d96372 320 const gp_GTrsf& theInvTrsf,
3bf9a45f 321 SelectMgr_FrustumCache& theCachedMgrs,
322 SelectMgr_SelectingVolumeManager& theResMgr)
323{
7479f643 324 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
91d96372 325 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
7479f643 326 const Standard_Boolean toScale = aScale != 1;
327 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
328 if (toScale && toTransform)
3bf9a45f 329 {
099f3513 330 theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL);
3bf9a45f 331 }
332 else if (toScale)
333 {
334 if (!theCachedMgrs.IsBound (aScale))
335 {
099f3513 336 theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL));
3bf9a45f 337 }
3bf9a45f 338 theResMgr = theCachedMgrs.Find (aScale);
339 }
7479f643 340 else if (toTransform)
341 {
099f3513 342 theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL);
7479f643 343 }
3bf9a45f 344}
345
f751596e 346//=======================================================================
347// function: traverseObject
348// purpose : Internal function that checks if there is possible overlap
349// between some entity of selectable object theObject and
350// current selecting volume
351//=======================================================================
099f3513 352void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
353 const SelectMgr_SelectingVolumeManager& theMgr,
354 const Handle(Graphic3d_Camera)& theCamera,
355 const Graphic3d_Mat4d& theProjectionMat,
356 const Graphic3d_Mat4d& theWorldViewMat,
357 const Standard_Integer theViewportWidth,
358 const Standard_Integer theViewportHeight)
7fd59977 359{
f5b72419 360 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
f751596e 361 if (anEntitySet->Size() == 0)
f5b72419 362 {
f751596e 363 return;
f5b72419 364 }
7fd59977 365
f5b72419 366 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
91d96372 367 gp_GTrsf aInversedTrsf;
778cd667 368 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
825aa485 369 {
778cd667 370 if (theObject->TransformPersistence().IsNull())
825aa485 371 {
372 aInversedTrsf = theObject->InversedTransformation();
373 }
374 else
375 {
91d96372 376 gp_GTrsf aTPers;
778cd667 377 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
099f3513 378
91d96372 379 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
380 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
381 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
382 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
383 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
384 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
385 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
386 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
387 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
388 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
389
390 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
825aa485 391 }
392 }
393
394 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
099f3513 395 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
396 : theMgr;
7fd59977 397
3bf9a45f 398 SelectMgr_FrustumCache aScaledTrnsfFrustums;
28ee613b 399
f751596e 400 Standard_Integer aNode = 0; // a root node
401 if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
402 aSensitivesTree->MaxPoint (0)))
403 {
404 return;
7fd59977 405 }
be7fc29e 406
407 const Standard_Integer aFirstStored = mystored.Extent() + 1;
408
f5b72419 409 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
f751596e 410 Standard_Integer aHead = -1;
411 for (;;)
412 {
413 if (!aSensitivesTree->IsOuter (aNode))
414 {
f2474958 415 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
416 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
f751596e 417 const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx),
418 aSensitivesTree->MaxPoint (aLeftChildIdx));
419 const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx),
420 aSensitivesTree->MaxPoint (aRightChildIdx));
421 if (isLeftChildIn
422 && isRightChildIn)
423 {
424 aNode = aLeftChildIdx;
425 ++aHead;
426 aStack[aHead] = aRightChildIdx;
427 }
428 else if (isLeftChildIn
429 || isRightChildIn)
430 {
431 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
432 }
433 else
434 {
435 if (aHead < 0)
436 {
437 break;
438 }
7fd59977 439
f751596e 440 aNode = aStack[aHead];
441 --aHead;
442 }
443 }
444 else
445 {
446 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
447 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
448 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
449 {
be7fc29e 450 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
f751596e 451 if (aSensitive->IsActiveForSelection())
452 {
0ef04197 453 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
28ee613b 454 SelectMgr_SelectingVolumeManager aTmpMgr = aMgr;
099f3513 455 computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
aa75c0cf 456 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
f751596e 457 }
458 }
459 if (aHead < 0)
460 {
461 break;
462 }
7fd59977 463
f751596e 464 aNode = aStack[aHead];
465 --aHead;
466 }
7fd59977 467 }
be7fc29e 468
469 // in case of Box/Polyline selection - keep only Owners having all Entities detected
470 if (mySelectingVolumeMgr.IsOverlapAllowed()
471 || (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Box
472 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Polyline))
473 {
474 return;
475 }
476
477 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
478 {
479 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
0ef04197 480 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
be7fc29e 481 Standard_Integer aNbOwnerEntities = 0;
482 for (SelectMgr_IndexedMapOfHSensitive::Iterator aSensIter (anEntitySet->Sensitives()); aSensIter.More(); aSensIter.Next())
483 {
484 if (aSensIter.Value()->BaseSensitive()->OwnerId() == anOwner)
485 {
486 if (++aNbOwnerEntities > aCriterion.NbOwnerMatches)
487 {
488 // Remove from index map.
489 // Considering NCollection_IndexedDataMap implementation, the values for lower indexes will not be modified.
490 // Hence, just keep iterating in backward direction.
491 mystored.RemoveFromIndex (aStoredIter);
492 break;
493 }
494 }
495 }
496 }
7fd59977 497}
498
f751596e 499//=======================================================================
500// function: TraverseSensitives
501// purpose : Traverses BVH containing all added selectable objects and
502// finds candidates for further search of overlap
503//=======================================================================
504void SelectMgr_ViewerSelector::TraverseSensitives()
7fd59977 505{
506 mystored.Clear();
507
099f3513 508 Standard_Integer aWidth;
509 Standard_Integer aHeight;
510 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
511 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
512 mySelectingVolumeMgr.ProjectionMatrix(),
513 mySelectingVolumeMgr.WorldViewMatrix(),
514 mySelectingVolumeMgr.WorldViewProjState(),
515 aWidth, aHeight);
fe76088c 516 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
517 if (!aCamera.IsNull())
518 {
519 myCameraEye = aCamera->Eye().XYZ();
520 myCameraDir = aCamera->Direction().XYZ();
521 myCameraScale = aCamera->IsOrthographic()
522 ? aCamera->Scale()
523 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
524 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
525 myCameraScale *= aPixelSize;
526 }
099f3513 527
528 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
f751596e 529 {
099f3513 530 SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
531 static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
532
533 if (mySelectableObjects.IsEmpty (aBVHSubset))
4269bd1b 534 {
099f3513 535 continue;
536 }
537
538 gp_GTrsf aTFrustum;
539
540 SelectMgr_SelectingVolumeManager aMgr (Standard_False);
541
542 // for 2D space selection transform selecting volumes to perform overap testing
543 // directly in camera's eye space omitting the camera position, which is not
544 // needed there at all
545 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
546 {
547 const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
548 aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
549 aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
550 aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2));
551 aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0));
552 aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1));
553 aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2));
554 aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0));
555 aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1));
556 aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2));
557 aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
558
559 // define corresponding frustum builder parameters
560 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
561 aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix());
896faa72 562 aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT);
099f3513 563 aBuilder->SetWindowSize (aWidth, aHeight);
564 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
825aa485 565 }
566 else
567 {
099f3513 568 aMgr = mySelectingVolumeMgr;
825aa485 569 }
570
099f3513 571 const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix();
572 const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent
573 ? mySelectingVolumeMgr.WorldViewMatrix()
896faa72 574 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
099f3513 575
f5b72419 576 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
099f3513 577
825aa485 578 Standard_Integer aNode = 0;
099f3513 579 if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
825aa485 580 {
581 continue;
582 }
583
f5b72419 584 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
825aa485 585 Standard_Integer aHead = -1;
586 for (;;)
587 {
588 if (!aBVHTree->IsOuter (aNode))
589 {
f2474958 590 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
591 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
825aa485 592 const Standard_Boolean isLeftChildIn =
099f3513 593 aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
825aa485 594 const Standard_Boolean isRightChildIn =
099f3513 595 aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
825aa485 596 if (isLeftChildIn
597 && isRightChildIn)
598 {
599 aNode = aLeftChildIdx;
600 ++aHead;
601 aStack[aHead] = aRightChildIdx;
602 }
603 else if (isLeftChildIn
604 || isRightChildIn)
605 {
606 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
607 }
608 else
609 {
610 if (aHead < 0)
611 {
612 break;
613 }
614
615 aNode = aStack[aHead];
616 --aHead;
617 }
f751596e 618 }
619 else
620 {
825aa485 621 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
622 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
623 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
624 {
099f3513 625 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
626 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
825aa485 627
099f3513 628 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
825aa485 629 }
f751596e 630 if (aHead < 0)
4269bd1b 631 {
f751596e 632 break;
4269bd1b 633 }
7fd59977 634
f751596e 635 aNode = aStack[aHead];
636 --aHead;
7fd59977 637 }
638 }
7fd59977 639 }
4269bd1b 640
f751596e 641 SortResult();
7fd59977 642}
4269bd1b 643
8a590580 644//==================================================
645// Function: ClearPicked
646// Purpose :
647//==================================================
648void SelectMgr_ViewerSelector::ClearPicked()
649{
650 mystored.Clear();
651}
652
7fd59977 653//==================================================
654// Function: Picked
655// Purpose :
656//==================================================
0ef04197 657Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked() const
7fd59977 658{
0ef04197 659 const Standard_Integer aRankInMap = myIndexes->Value (myCurRank);
660 const Handle(SelectMgr_EntityOwner)& anOwner = mystored.FindKey (aRankInMap);
661 return anOwner;
7fd59977 662}
663
7fd59977 664//=======================================================================
aa75c0cf 665//function : Picked
4269bd1b 666//purpose :
7fd59977 667//=======================================================================
aa75c0cf 668Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
7fd59977 669{
aa75c0cf 670 if (theRank < 1 || theRank > NbPicked())
671 {
0ef04197 672 return Handle(SelectMgr_EntityOwner)();
7fd59977 673 }
674
aa75c0cf 675 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
0ef04197 676 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
677 return aStoredOwner;
7fd59977 678}
679
7fd59977 680//=======================================================================
aa75c0cf 681//function : PickedData
4269bd1b 682//purpose :
7fd59977 683//=======================================================================
aa75c0cf 684const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
7fd59977 685{
aa75c0cf 686 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
687 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
688 return mystored.FindFromIndex (anOwnerIdx);
7fd59977 689}
690
7fd59977 691//===================================================
692//
693// INTERNAL METHODS ....
694//
695//==================================================
696
f5b72419 697//==================================================
698// Function: SetEntitySetBuilder
699// Purpose :
700//==================================================
701void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
702{
703 myEntitySetBuilder = theBuilder;
704 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
705 {
706 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
707 }
708}
709
7fd59977 710//==================================================
711// Function: Contains
4269bd1b 712// Purpose :
7fd59977 713//==================================================
f751596e 714Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
7fd59977 715{
099f3513 716 return mySelectableObjects.Contains (theObject);
7fd59977 717}
718
7fd59977 719//==================================================
720// Function: ActiveModes
721// Purpose : return all the modes with a given state for an object
722//==================================================
f751596e 723Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
724 TColStd_ListOfInteger& theModeList,
725 const SelectMgr_StateOfSelection theWantedState) const
7fd59977 726{
825aa485 727 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
b5cce1ab 728 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
f751596e 729 {
82d23ad5 730 if (theWantedState == SelectMgr_SOS_Any)
731 {
732 theModeList.Append (aSelIter.Value()->Mode());
733 }
734 else if (theWantedState == aSelIter.Value()->GetSelectionState())
735 {
736 theModeList.Append (aSelIter.Value()->Mode());
737 }
7fd59977 738 }
7fd59977 739
f751596e 740 return hasActivatedStates;
741}
7fd59977 742
f751596e 743//==================================================
744// Function: IsActive
745// Purpose :
746//==================================================
747Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
748 const Standard_Integer theMode) const
7fd59977 749{
825aa485 750 if (!Contains (theSelectableObject))
f751596e 751 return Standard_False;
752
b5cce1ab 753 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
754 return !aSel.IsNull()
755 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
7fd59977 756}
757
f751596e 758//==================================================
759// Function: IsInside
760// Purpose :
761//==================================================
762Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
763 const Standard_Integer theMode) const
7fd59977 764{
825aa485 765 if (!Contains (theSelectableObject))
f751596e 766 return Standard_False;
7fd59977 767
b5cce1ab 768 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
769 return !aSel.IsNull()
770 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
7fd59977 771}
772
773
774//=======================================================================
775//function : Status
4269bd1b 776//purpose :
7fd59977 777//=======================================================================
778
f751596e 779SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
7fd59977 780{
f751596e 781 return theSelection->GetSelectionState();
7fd59977 782}
783
7fd59977 784//==================================================
785// Function: Status
786// Purpose : gives Information about selectors
787//==================================================
788
f751596e 789TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
7fd59977 790{
f751596e 791 TCollection_AsciiString aStatus ("Status Object :\n\t");
b5cce1ab 792 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
f751596e 793 {
b5cce1ab 794 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
7fd59977 795 {
b5cce1ab 796 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
797 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
7fd59977 798 }
799 }
800
825aa485 801 if (!Contains (theSelectableObject))
7fd59977 802 {
f751596e 803 aStatus = aStatus + "Not Present in the selector\n\n";
7fd59977 804 }
f751596e 805
806 return aStatus;
7fd59977 807}
808
809//=======================================================================
810//function : SortResult
4269bd1b 811//purpose : there is a certain number of entities ranged by criteria
81bba717 812// (depth, size, priority, mouse distance from borders or
813// CDG of the detected primitive. Parsing :
814// maximum priorities .
815// then a reasonable compromise between depth and distance...
816// finally the ranges are stored in myindexes depending on the parsing.
4269bd1b 817// so, it is possible to only read
7fd59977 818//=======================================================================
819void SelectMgr_ViewerSelector::SortResult()
820{
821 if(mystored.IsEmpty()) return;
822
823 const Standard_Integer anExtent = mystored.Extent();
824 if(myIndexes.IsNull() || anExtent != myIndexes->Length())
825 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
826
f5b72419 827 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
828 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
829 {
830 anIndexArray.SetValue (anIndexIter, anIndexIter);
831 }
832 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored));
f751596e 833}
834
835//=======================================================================
836//function : HasDepthClipping
837//purpose : Stub
838//=======================================================================
839Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const
840{
841 return Standard_False;
842}
843
844//=======================================================================
845// function : AddSelectableObject
846// purpose : Adds new object to the map of selectable objects
847//=======================================================================
848void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
849{
850 if (!myMapOfObjectSensitives.IsBound (theObject))
851 {
099f3513 852 mySelectableObjects.Append (theObject);
f5b72419 853 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
f751596e 854 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
7fd59977 855 }
f751596e 856}
7fd59977 857
f751596e 858//=======================================================================
859// function : AddSelectionToObject
860// purpose : Adds new selection to the object and builds its BVH tree
861//=======================================================================
862void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
863 const Handle(SelectMgr_Selection)& theSelection)
864{
f5b72419 865 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
f751596e 866 {
f5b72419 867 (*anEntitySet)->Append (theSelection);
868 (*anEntitySet)->BVH();
f751596e 869 }
870 else
871 {
872 AddSelectableObject (theObject);
873 AddSelectionToObject (theObject, theSelection);
874 }
7fd59977 875}
876
1d92133e 877//=======================================================================
878// function : MoveSelectableObject
879// purpose :
880//=======================================================================
881void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
882{
099f3513 883 mySelectableObjects.ChangeSubset (theObject);
1d92133e 884}
885
f751596e 886//=======================================================================
887// function : RemoveSelectableObject
888// purpose : Removes selectable object from map of selectable ones
889//=======================================================================
890void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
891{
f5b72419 892 Handle(SelectMgr_SelectableObject) anObj = theObject;
893 if (myMapOfObjectSensitives.UnBind (theObject))
f751596e 894 {
099f3513 895 mySelectableObjects.Remove (theObject);
f751596e 896 }
897}
7fd59977 898
899//=======================================================================
f751596e 900// function : RemoveSelectionOfObject
901// purpose : Removes selection of the object and marks its BVH tree
902// for rebuild
7fd59977 903//=======================================================================
f751596e 904void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
905 const Handle(SelectMgr_Selection)& theSelection)
7fd59977 906{
f5b72419 907 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
f751596e 908 {
f5b72419 909 (*anEntitySet)->Remove (theSelection);
f751596e 910 }
7fd59977 911}
912
913//=======================================================================
f751596e 914// function : RebuildObjectsTree
915// purpose : Marks BVH of selectable objects for rebuild
7fd59977 916//=======================================================================
f751596e 917void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
7fd59977 918{
825aa485 919 mySelectableObjects.MarkDirty();
f751596e 920
921 if (theIsForce)
922 {
099f3513 923 Standard_Integer aViewportWidth, aViewportHeight;
91d96372 924 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
825aa485 925
099f3513 926 Standard_Integer aWidth;
927 Standard_Integer aHeight;
928 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
929 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(),
930 mySelectingVolumeMgr.ProjectionMatrix(),
931 mySelectingVolumeMgr.WorldViewMatrix(),
932 mySelectingVolumeMgr.WorldViewProjState(),
933 aWidth, aHeight);
f751596e 934 }
7fd59977 935}
4269bd1b 936
937//=======================================================================
f751596e 938// function : RebuildSensitivesTree
939// purpose : Marks BVH of sensitive entities of particular selectable
940// object for rebuild
4269bd1b 941//=======================================================================
f751596e 942void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
943 const Standard_Boolean theIsForce)
4269bd1b 944{
825aa485 945 if (!Contains (theObject))
f751596e 946 return;
947
f5b72419 948 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
f751596e 949 anEntitySet->MarkDirty();
950
951 if (theIsForce)
952 {
953 anEntitySet->BVH();
954 }
4269bd1b 955}
956
957//=======================================================================
f751596e 958// function : resetSelectionActivationStatus
959// purpose : Marks all added sensitive entities of all objects as
960// non-selectable
4269bd1b 961//=======================================================================
29a4908e 962void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
4269bd1b 963{
f5b72419 964 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
f751596e 965 {
f5b72419 966 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
967 const Standard_Integer anEntitiesNb = anEntitySet->Size();
f751596e 968 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
969 {
970 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
971 }
972 }
4269bd1b 973}
974
975//=======================================================================
f751596e 976// function : DetectedEntity
977// purpose : Returns sensitive entity that was detected during the
978// previous run of selection algorithm
4269bd1b 979//=======================================================================
0ef04197 980const Handle(Select3D_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const
4269bd1b 981{
aa75c0cf 982 const Standard_Integer aRankInMap = myIndexes->Value(myCurRank);
983 return mystored.FindFromIndex (aRankInMap).Entity;
4269bd1b 984}
985
986//=======================================================================
f751596e 987// function : ActiveOwners
988// purpose : Returns the list of active entity owners
4269bd1b 989//=======================================================================
0ef04197 990void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
4269bd1b 991{
f751596e 992 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
993 {
f5b72419 994 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
995 const Standard_Integer anEntitiesNb = anEntitySet->Size();
f751596e 996 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
997 {
f5b72419 998 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
999 if (aSensitive->IsActiveForSelection())
f751596e 1000 {
f5b72419 1001 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
f751596e 1002 }
1003 }
1004 }
4269bd1b 1005}
29a4908e 1006
1007//=======================================================================
1008//function : AllowOverlapDetection
1009//purpose : Sets the detection type: if theIsToAllow is false,
1010// only fully included sensitives will be detected, otherwise
1011// the algorithm will mark both included and overlapped entities
1012// as matched
1013//=======================================================================
1014void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1015{
1016 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1017}