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