1 // Created on: 1995-02-15
2 // Created by: Roberc Coublanc
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <SelectMgr_ViewerSelector.hxx>
18
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
21 #include <gp_Pnt.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_SensitiveEntity.hxx>
25 #include <SelectBasics_PickResult.hxx>
26 #include <SelectMgr.hxx>
27 #include <SelectMgr_EntityOwner.hxx>
28 #include <SelectMgr_FrustumBuilder.hxx>
29 #include <SelectMgr_SelectionImageFiller.hxx>
30 #include <SelectMgr_SensitiveEntitySet.hxx>
31 #include <SelectMgr_SortCriterion.hxx>
32 #include <TColStd_Array1OfInteger.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <TColStd_HArray1OfInteger.hxx>
35 #include <TColStd_ListOfInteger.hxx>
36 #include <V3d_View.hxx>
37
38 #include <algorithm>
39
40 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
41
42 namespace
43 {
44 //! Comparison operator for sorting selection results
45 class CompareResults
46 {
47 public:
48
CompareResults(const SelectMgr_IndexedDataMapOfOwnerCriterion & theMapOfCriterion,bool theToPreferClosest)49 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
50 bool theToPreferClosest)
51 : myMapOfCriterion (&theMapOfCriterion),
52 myToPreferClosest (theToPreferClosest) {}
53
operator ()(Standard_Integer theLeft,Standard_Integer theRight) const54 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
55 {
56 const SelectMgr_SortCriterion& anElemLeft = myMapOfCriterion->FindFromIndex (theLeft);
57 const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
58 if (myToPreferClosest)
59 {
60 return anElemLeft.IsCloserDepth (anElemRight);
61 }
62 else
63 {
64 return anElemLeft.IsHigherPriority (anElemRight);
65 }
66 }
67
68 private:
69 const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
70 bool myToPreferClosest;
71 };
72
73 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
74 }
75
76 //=======================================================================
77 // function : updatePoint3d
78 // purpose :
79 //=======================================================================
updatePoint3d(SelectMgr_SortCriterion & theCriterion,const SelectBasics_PickResult & thePickResult,const Handle (Select3D_SensitiveEntity)& theEntity,const gp_GTrsf & theInversedTrsf,const SelectMgr_SelectingVolumeManager & theMgr) const80 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
81 const SelectBasics_PickResult& thePickResult,
82 const Handle(Select3D_SensitiveEntity)& theEntity,
83 const gp_GTrsf& theInversedTrsf,
84 const SelectMgr_SelectingVolumeManager& theMgr) const
85 {
86 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
87 {
88 return;
89 }
90
91 bool hasNormal = false;
92 if (thePickResult.HasPickedPoint())
93 {
94 theCriterion.Point = thePickResult.PickedPoint();
95 theCriterion.Normal = thePickResult.SurfaceNormal();
96 const float aNormLen2 = theCriterion.Normal.SquareModulus();
97 if (aNormLen2 > ShortRealEpsilon())
98 {
99 hasNormal = true;
100 theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
101 }
102 }
103 else if (!thePickResult.IsValid())
104 {
105 theCriterion.Point = thePickResult.PickedPoint();
106 return;
107 }
108 else
109 {
110 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
111 }
112
113 gp_GTrsf anInvTrsf = theInversedTrsf;
114 if (theCriterion.Entity->HasInitLocation())
115 {
116 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
117 }
118 if (anInvTrsf.Form() != gp_Identity)
119 {
120 const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
121 anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
122 if (hasNormal)
123 {
124 Graphic3d_Mat4d aMat4;
125 anInvInvTrsd.GetMat4 (aMat4);
126 const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
127 theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
128 }
129 }
130
131 const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
132 switch (myDepthTolType)
133 {
134 case SelectMgr_TypeOfDepthTolerance_Uniform:
135 {
136 theCriterion.Tolerance = myDepthTolerance;
137 break;
138 }
139 case SelectMgr_TypeOfDepthTolerance_UniformPixels:
140 case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
141 {
142 if (mySelectingVolumeMgr.Camera().IsNull())
143 {
144 // fallback for an arbitrary projection matrix
145 theCriterion.Tolerance = aSensFactor / 33.0;
146 }
147 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
148 {
149 theCriterion.Tolerance = myCameraScale * aSensFactor;
150 }
151 else
152 {
153 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
154 theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
155 }
156 break;
157 }
158 }
159 }
160
161 //==================================================
162 // Function: Initialize
163 // Purpose :
164 //==================================================
SelectMgr_ViewerSelector()165 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
166 : myDepthTolerance (0.0),
167 myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
168 myToPreferClosest (Standard_True),
169 myCameraScale (1.0),
170 myToPrebuildBVH (Standard_False),
171 myIsSorted (Standard_False),
172 myIsLeftChildQueuedFirst (Standard_False)
173 {
174 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
175 }
176
177 //=======================================================================
178 // Function: SetPixelTolerance
179 // Purpose :
180 //=======================================================================
SetPixelTolerance(const Standard_Integer theTolerance)181 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
182 {
183 if (myTolerances.Tolerance() == theTolerance)
184 {
185 return;
186 }
187 if (theTolerance < 0)
188 {
189 myTolerances.ResetDefaults();
190 }
191 else
192 {
193 myTolerances.SetCustomTolerance (theTolerance);
194 }
195 }
196
197 //==================================================
198 // Function: Activate
199 // Purpose :
200 //==================================================
Activate(const Handle (SelectMgr_Selection)& theSelection)201 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
202 {
203 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
204 {
205 aSelEntIter.Value()->SetActiveForSelection();
206 }
207
208 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
209 {
210 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
211
212 myTolerances.Add (theSelection->Sensitivity());
213 }
214 }
215
216 //==================================================
217 // Function: Deactivate
218 // Purpose :
219 //==================================================
Deactivate(const Handle (SelectMgr_Selection)& theSelection)220 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
221 {
222 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
223 {
224 aSelEntIter.Value()->ResetSelectionActiveStatus();
225 }
226
227 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
228 {
229 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
230
231 myTolerances.Decrement (theSelection->Sensitivity());
232 }
233 }
234
235 //=======================================================================
236 // function: isToScaleFrustum
237 // purpose : Checks if the entity given requires to scale current selecting frustum
238 //=======================================================================
isToScaleFrustum(const Handle (Select3D_SensitiveEntity)& theEntity)239 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
240 {
241 return mySelectingVolumeMgr.IsScalableActiveVolume()
242 && sensitivity (theEntity) < myTolerances.Tolerance();
243 }
244
245 //=======================================================================
246 // function: sensitivity
247 // purpose : In case if custom tolerance is set, this method will return sum of entity
248 // sensitivity and custom tolerance.
249 //=======================================================================
sensitivity(const Handle (Select3D_SensitiveEntity)& theEntity) const250 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
251 {
252 return myTolerances.IsCustomTolSet() ?
253 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
254 }
255
256 //=======================================================================
257 // function: checkOverlap
258 // purpose : Internal function that checks if a particular sensitive
259 // entity theEntity overlaps current selecting volume precisely
260 //=======================================================================
checkOverlap(const Handle (Select3D_SensitiveEntity)& theEntity,const gp_GTrsf & theInversedTrsf,SelectMgr_SelectingVolumeManager & theMgr)261 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
262 const gp_GTrsf& theInversedTrsf,
263 SelectMgr_SelectingVolumeManager& theMgr)
264 {
265 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
266 Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
267 SelectBasics_PickResult aPickResult;
268 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
269 if (!isMatched
270 || anOwner.IsNull())
271 {
272 return;
273 }
274
275 SelectMgr_SortCriterion aCriterion;
276 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
277 aCriterion.Entity = theEntity;
278 aCriterion.Priority = anOwner->Priority();
279 aCriterion.Depth = aPickResult.Depth();
280 aCriterion.MinDist = aPickResult.DistToGeomCenter();
281
282 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
283 {
284 ++aPrevCriterion->NbOwnerMatches;
285 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
286 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
287 {
288 if (aCriterion.IsCloserDepth (*aPrevCriterion))
289 {
290 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
291 *aPrevCriterion = aCriterion;
292 }
293 }
294 }
295 else
296 {
297 aCriterion.NbOwnerMatches = 1;
298 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
299 mystored.Add (anOwner, aCriterion);
300 }
301 }
302
303 //=======================================================================
304 // Function: updateZLayers
305 // Purpose :
306 //=======================================================================
updateZLayers(const Handle (V3d_View)& theView)307 void SelectMgr_ViewerSelector::updateZLayers (const Handle(V3d_View)& theView)
308 {
309 myZLayerOrderMap.Clear();
310 TColStd_SequenceOfInteger aZLayers;
311 theView->Viewer()->GetAllZLayers (aZLayers);
312 Standard_Integer aPos = 0;
313 Standard_Boolean isPrevDepthWrite = true;
314 for (TColStd_SequenceOfInteger::Iterator aLayerIter (aZLayers); aLayerIter.More(); aLayerIter.Next())
315 {
316 Graphic3d_ZLayerSettings aSettings = theView->Viewer()->ZLayerSettings (aLayerIter.Value());
317 if (aSettings.ToClearDepth()
318 || isPrevDepthWrite != aSettings.ToEnableDepthWrite())
319 {
320 ++aPos;
321 }
322 isPrevDepthWrite = aSettings.ToEnableDepthWrite();
323 myZLayerOrderMap.Bind (aLayerIter.Value(), aPos);
324 }
325 }
326
327 //=======================================================================
328 // function: computeFrustum
329 // purpose :
330 //=======================================================================
computeFrustum(const Handle (Select3D_SensitiveEntity)& theEnt,const SelectMgr_SelectingVolumeManager & theMgrGlobal,const SelectMgr_SelectingVolumeManager & theMgrObject,const gp_GTrsf & theInvTrsf,SelectMgr_FrustumCache & theCachedMgrs,SelectMgr_SelectingVolumeManager & theResMgr)331 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
332 const SelectMgr_SelectingVolumeManager& theMgrGlobal,
333 const SelectMgr_SelectingVolumeManager& theMgrObject,
334 const gp_GTrsf& theInvTrsf,
335 SelectMgr_FrustumCache& theCachedMgrs,
336 SelectMgr_SelectingVolumeManager& theResMgr)
337 {
338 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
339 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
340 const Standard_Boolean toScale = aScale != 1;
341 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
342 if (toScale && toTransform)
343 {
344 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
345 theResMgr.SetViewClipping (theMgrObject);
346 }
347 else if (toScale)
348 {
349 if (!theCachedMgrs.Find (aScale, theResMgr))
350 {
351 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
352 theCachedMgrs.Bind (aScale, theResMgr);
353 }
354 theResMgr.SetViewClipping (theMgrObject);
355 }
356 else if (toTransform)
357 {
358 theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
359 theResMgr.SetViewClipping (theMgrObject);
360 }
361 else
362 {
363 theResMgr = theMgrObject;
364 }
365 }
366
367 //=======================================================================
368 // function: traverseObject
369 // purpose : Internal function that checks if there is possible overlap
370 // between some entity of selectable object theObject and
371 // current selecting volume
372 //=======================================================================
traverseObject(const Handle (SelectMgr_SelectableObject)& theObject,const SelectMgr_SelectingVolumeManager & theMgr,const Handle (Graphic3d_Camera)& theCamera,const Graphic3d_Mat4d & theProjectionMat,const Graphic3d_Mat4d & theWorldViewMat,const Graphic3d_Vec2i & theWinSize)373 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
374 const SelectMgr_SelectingVolumeManager& theMgr,
375 const Handle(Graphic3d_Camera)& theCamera,
376 const Graphic3d_Mat4d& theProjectionMat,
377 const Graphic3d_Mat4d& theWorldViewMat,
378 const Graphic3d_Vec2i& theWinSize)
379 {
380 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
381 if (anEntitySet->Size() == 0)
382 {
383 return;
384 }
385
386 const bool hasEntityTrsfPers = anEntitySet->HasEntityWithPersistence()
387 && !theCamera.IsNull();
388 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
389 gp_GTrsf aInversedTrsf;
390 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
391 {
392 if (theObject->TransformPersistence().IsNull())
393 {
394 aInversedTrsf = theObject->InversedTransformation();
395 }
396 else
397 {
398 if (theCamera.IsNull())
399 {
400 return;
401 }
402
403 const Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera,
404 theProjectionMat, theWorldViewMat,
405 theWinSize.x(), theWinSize.y());
406 gp_GTrsf aTPers;
407 aTPers.SetMat4 (aMat);
408 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
409 }
410 }
411
412 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
413 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
414 : theMgr;
415 if (!hasEntityTrsfPers
416 && !aMgr.OverlapsBox (aSensitivesTree->MinPoint (0),
417 aSensitivesTree->MaxPoint (0)))
418 {
419 return;
420 }
421
422 if (!theObject->ClipPlanes().IsNull()
423 && theObject->ClipPlanes()->ToOverrideGlobal())
424 {
425 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
426 }
427 else if (!theObject->TransformPersistence().IsNull())
428 {
429 if (theObject->TransformPersistence()->IsZoomOrRotate()
430 && !theMgr.ViewClipping().IsNull())
431 {
432 // Zoom/rotate persistence object lives in two worlds at the same time.
433 // Global clipping planes can not be trivially applied without being converted
434 // into local space of transformation persistence object.
435 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
436 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
437 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
438 {
439 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
440 if (!aPlane->IsOn())
441 {
442 continue;
443 }
444
445 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
446 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
447 {
448 return;
449 }
450 }
451 }
452
453 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
454 }
455 else if (!theObject->ClipPlanes().IsNull()
456 && !theObject->ClipPlanes()->IsEmpty())
457 {
458 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
459 }
460
461 if (!theMgr.ViewClipping().IsNull() &&
462 theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
463 {
464 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
465 // If box selection is active, and the whole sensitive tree is out of the clip planes
466 // selection is empty for this object
467 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
468
469 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
470 {
471 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
472 if (!aPlane->IsOn())
473 {
474 continue;
475 }
476
477 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
478 if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
479 {
480 return;
481 }
482 }
483 }
484
485 const Standard_Integer aFirstStored = mystored.Extent() + 1;
486
487 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
488 Standard_Integer aHead = -1;
489 Standard_Integer aNode = 0; // a root node
490 SelectMgr_FrustumCache aScaledTrnsfFrustums;
491 SelectMgr_SelectingVolumeManager aTmpMgr;
492 for (;;)
493 {
494 if (!aSensitivesTree->IsOuter (aNode))
495 {
496 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
497 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
498 const Standard_Boolean isLeftChildIn = hasEntityTrsfPers
499 || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx),
500 aSensitivesTree->MaxPoint (aLeftChildIdx));
501 const Standard_Boolean isRightChildIn = hasEntityTrsfPers
502 || aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx),
503 aSensitivesTree->MaxPoint (aRightChildIdx));
504 if (isLeftChildIn
505 && isRightChildIn)
506 {
507 aNode = aLeftChildIdx;
508 ++aHead;
509 aStack[aHead] = aRightChildIdx;
510 }
511 else if (isLeftChildIn
512 || isRightChildIn)
513 {
514 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
515 }
516 else
517 {
518 if (aHead < 0)
519 {
520 break;
521 }
522
523 aNode = aStack[aHead];
524 --aHead;
525 }
526 }
527 else
528 {
529 bool aClipped = false;
530 if (!theMgr.ViewClipping().IsNull() &&
531 theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
532 {
533 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
534 // If box selection is active, and the whole sensitive tree is out of the clip planes
535 // selection is empty for this object
536 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
537
538 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
539 {
540 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
541 if (!aPlane->IsOn())
542 {
543 continue;
544 }
545 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
546 if (aState == Graphic3d_ClipState_Out)
547 {
548 aClipped = true;
549 break;
550 }
551 if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
552 {
553 if (aPlane->ProbeBoxTouch (aBBox))
554 continue;
555 aClipped = true;
556 break;
557 }
558 }
559 }
560 if (!aClipped)
561 {
562 const Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
563 const Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
564 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
565 {
566 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
567 if (!aSensitive->IsActiveForSelection())
568 {
569 continue;
570 }
571
572 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
573
574 gp_GTrsf aInvSensTrsf = aInversedTrsf;
575 if (!anEnt->TransformPersistence().IsNull())
576 {
577 if (theCamera.IsNull())
578 {
579 continue;
580 }
581 const Graphic3d_Mat4d aMat = anEnt->TransformPersistence()->Compute (theCamera,
582 theProjectionMat, theWorldViewMat,
583 theWinSize.x(), theWinSize.y());
584 gp_GTrsf aTPers;
585 aTPers.SetMat4 (aMat);
586 aInvSensTrsf = (aTPers * gp_GTrsf(theObject->Transformation())).Inverted();
587 }
588
589 computeFrustum (anEnt, theMgr, aMgr, aInvSensTrsf, aScaledTrnsfFrustums, aTmpMgr);
590 checkOverlap (anEnt, aInvSensTrsf, aTmpMgr);
591 }
592 }
593 if (aHead < 0)
594 {
595 break;
596 }
597
598 aNode = aStack[aHead];
599 --aHead;
600 }
601 }
602
603 // in case of Box/Polyline selection - keep only Owners having all Entities detected
604 if (mySelectingVolumeMgr.IsOverlapAllowed()
605 || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
606 && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
607 {
608 return;
609 }
610
611 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
612 {
613 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
614 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
615 Standard_Integer aNbOwnerEntities = 0;
616 anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
617 if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
618 {
619 mystored.RemoveFromIndex (aStoredIter);
620 }
621 }
622 }
623
624 //=======================================================================
625 // function: TraverseSensitives
626 // purpose : Traverses BVH containing all added selectable objects and
627 // finds candidates for further search of overlap
628 //=======================================================================
TraverseSensitives()629 void SelectMgr_ViewerSelector::TraverseSensitives()
630 {
631 SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
632
633 mystored.Clear();
634 myIsSorted = false;
635
636 Graphic3d_Vec2i aWinSize;
637 mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y());
638
639 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
640 Graphic3d_Mat4d aProjectionMat, aWorldViewMat;
641 Graphic3d_WorldViewProjState aViewState;
642 if (!aCamera.IsNull())
643 {
644 aProjectionMat = aCamera->ProjectionMatrix();
645 aWorldViewMat = aCamera->OrientationMatrix();
646 aViewState = aCamera->WorldViewProjState();
647
648 myCameraEye = aCamera->Eye().XYZ();
649 myCameraDir = aCamera->Direction().XYZ();
650 myCameraScale = aCamera->IsOrthographic()
651 ? aCamera->Scale()
652 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
653 const double aPixelSize = Max (1.0 / aWinSize.x(), 1.0 / aWinSize.y());
654 myCameraScale *= aPixelSize;
655 }
656 mySelectableObjects.UpdateBVH (aCamera, aWinSize);
657
658 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
659 {
660 const SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = (SelectMgr_SelectableObjectSet::BVHSubset )aBVHSetIt;
661 if (mySelectableObjects.IsEmpty (aBVHSubset))
662 {
663 continue;
664 }
665 if (aCamera.IsNull()
666 && aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_3d)
667 {
668 continue;
669 }
670
671 SelectMgr_SelectingVolumeManager aMgr;
672
673 // for 2D space selection transform selecting volumes to perform overlap testing
674 // directly in camera's eye space omitting the camera position, which is not
675 // needed there at all
676 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
677 {
678 gp_GTrsf aTFrustum;
679 aTFrustum.SetValue (1, 1, aWorldViewMat.GetValue (0, 0));
680 aTFrustum.SetValue (1, 2, aWorldViewMat.GetValue (0, 1));
681 aTFrustum.SetValue (1, 3, aWorldViewMat.GetValue (0, 2));
682 aTFrustum.SetValue (2, 1, aWorldViewMat.GetValue (1, 0));
683 aTFrustum.SetValue (2, 2, aWorldViewMat.GetValue (1, 1));
684 aTFrustum.SetValue (2, 3, aWorldViewMat.GetValue (1, 2));
685 aTFrustum.SetValue (3, 1, aWorldViewMat.GetValue (2, 0));
686 aTFrustum.SetValue (3, 2, aWorldViewMat.GetValue (2, 1));
687 aTFrustum.SetValue (3, 3, aWorldViewMat.GetValue (2, 2));
688 aTFrustum.SetTranslationPart (gp_XYZ (aWorldViewMat.GetValue (0, 3),
689 aWorldViewMat.GetValue (1, 3),
690 aWorldViewMat.GetValue (2, 3)));
691
692 // define corresponding frustum builder parameters
693 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
694 Handle(Graphic3d_Camera) aNewCamera = new Graphic3d_Camera();
695 aNewCamera->CopyMappingData (aCamera);
696 aNewCamera->SetIdentityOrientation();
697 aWorldViewMat = aNewCamera->OrientationMatrix(); // should be identity matrix
698 aProjectionMat = aNewCamera->ProjectionMatrix(); // should be the same to aProjectionMat
699 aBuilder->SetCamera (aNewCamera);
700 aBuilder->SetWindowSize (aWinSize.x(), aWinSize.y());
701 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
702 }
703 else
704 {
705 aMgr = mySelectingVolumeMgr;
706 }
707
708 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
709
710 Standard_Integer aNode = 0;
711 if (!aMgr.OverlapsBox (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
712 {
713 continue;
714 }
715
716 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
717 Standard_Integer aHead = -1;
718 for (;;)
719 {
720 if (!aBVHTree->IsOuter (aNode))
721 {
722 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
723 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
724 const Standard_Boolean isLeftChildIn =
725 aMgr.OverlapsBox (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
726 const Standard_Boolean isRightChildIn =
727 aMgr.OverlapsBox (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
728 if (isLeftChildIn
729 && isRightChildIn)
730 {
731 aNode = aLeftChildIdx;
732 ++aHead;
733 aStack[aHead] = aRightChildIdx;
734 }
735 else if (isLeftChildIn
736 || isRightChildIn)
737 {
738 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
739 }
740 else
741 {
742 if (aHead < 0)
743 {
744 break;
745 }
746
747 aNode = aStack[aHead];
748 --aHead;
749 }
750 }
751 else
752 {
753 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
754 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
755 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
756 {
757 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
758 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
759
760 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWinSize);
761 }
762 if (aHead < 0)
763 {
764 break;
765 }
766
767 aNode = aStack[aHead];
768 --aHead;
769 }
770 }
771 }
772
773 SortResult();
774 }
775
776 //==================================================
777 // Function: ClearPicked
778 // Purpose :
779 //==================================================
ClearPicked()780 void SelectMgr_ViewerSelector::ClearPicked()
781 {
782 mystored.Clear();
783 myIsSorted = true;
784 }
785
786 //==================================================
787 // Function: RemovePicked
788 // Purpose :
789 //==================================================
RemovePicked(const Handle (SelectMgr_SelectableObject)& theObject)790 bool SelectMgr_ViewerSelector::RemovePicked (const Handle(SelectMgr_SelectableObject)& theObject)
791 {
792 if (mystored.IsEmpty()
793 || !mySelectableObjects.Contains (theObject))
794 {
795 return false;
796 }
797
798 bool isRemoved = false;
799 for (Standard_Integer aPickIter = 1; aPickIter <= mystored.Extent(); ++aPickIter)
800 {
801 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (aPickIter);
802 if (!aStoredOwner.IsNull()
803 && aStoredOwner->IsSameSelectable (theObject))
804 {
805 mystored.RemoveFromIndex (aPickIter);
806 --aPickIter;
807 isRemoved = true;
808 }
809 }
810 if (isRemoved)
811 {
812 myIsSorted = false;
813 }
814 return isRemoved;
815 }
816
817 //=======================================================================
818 //function : Picked
819 //purpose :
820 //=======================================================================
Handle(SelectMgr_EntityOwner)821 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
822 {
823 if (theRank < 1 || theRank > NbPicked())
824 {
825 return Handle(SelectMgr_EntityOwner)();
826 }
827
828 if (!myIsSorted)
829 {
830 SortResult();
831 }
832
833 const Standard_Integer anOwnerIdx = myIndexes.Value (theRank);
834 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
835 return aStoredOwner;
836 }
837
838 //=======================================================================
839 //function : PickedData
840 //purpose :
841 //=======================================================================
PickedData(const Standard_Integer theRank) const842 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
843 {
844 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
845 if (!myIsSorted)
846 {
847 SortResult();
848 }
849
850 const Standard_Integer anOwnerIdx = myIndexes.Value (theRank);
851 return mystored.FindFromIndex (anOwnerIdx);
852 }
853
854 //===================================================
855 //
856 // INTERNAL METHODS ....
857 //
858 //==================================================
859
860 //==================================================
861 // Function: SetEntitySetBuilder
862 // Purpose :
863 //==================================================
SetEntitySetBuilder(const Handle (Select3D_BVHBuilder3d)& theBuilder)864 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
865 {
866 myEntitySetBuilder = theBuilder;
867 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
868 {
869 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
870 }
871 }
872
873 //==================================================
874 // Function: Contains
875 // Purpose :
876 //==================================================
Contains(const Handle (SelectMgr_SelectableObject)& theObject) const877 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
878 {
879 return mySelectableObjects.Contains (theObject);
880 }
881
882 //==================================================
883 // Function: ActiveModes
884 // Purpose : return all the modes with a given state for an object
885 //==================================================
Modes(const Handle (SelectMgr_SelectableObject)& theSelectableObject,TColStd_ListOfInteger & theModeList,const SelectMgr_StateOfSelection theWantedState) const886 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
887 TColStd_ListOfInteger& theModeList,
888 const SelectMgr_StateOfSelection theWantedState) const
889 {
890 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
891 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
892 {
893 if (theWantedState == SelectMgr_SOS_Any)
894 {
895 theModeList.Append (aSelIter.Value()->Mode());
896 }
897 else if (theWantedState == aSelIter.Value()->GetSelectionState())
898 {
899 theModeList.Append (aSelIter.Value()->Mode());
900 }
901 }
902
903 return hasActivatedStates;
904 }
905
906 //==================================================
907 // Function: IsActive
908 // Purpose :
909 //==================================================
IsActive(const Handle (SelectMgr_SelectableObject)& theSelectableObject,const Standard_Integer theMode) const910 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
911 const Standard_Integer theMode) const
912 {
913 if (!Contains (theSelectableObject))
914 return Standard_False;
915
916 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
917 return !aSel.IsNull()
918 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
919 }
920
921 //==================================================
922 // Function: IsInside
923 // Purpose :
924 //==================================================
IsInside(const Handle (SelectMgr_SelectableObject)& theSelectableObject,const Standard_Integer theMode) const925 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
926 const Standard_Integer theMode) const
927 {
928 if (!Contains (theSelectableObject))
929 return Standard_False;
930
931 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
932 return !aSel.IsNull()
933 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
934 }
935
936
937 //=======================================================================
938 //function : Status
939 //purpose :
940 //=======================================================================
941
Status(const Handle (SelectMgr_Selection)& theSelection) const942 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
943 {
944 return theSelection->GetSelectionState();
945 }
946
947 //==================================================
948 // Function: Status
949 // Purpose : gives Information about selectors
950 //==================================================
951
Status(const Handle (SelectMgr_SelectableObject)& theSelectableObject) const952 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
953 {
954 TCollection_AsciiString aStatus ("Status Object :\n\t");
955 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
956 {
957 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
958 {
959 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
960 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
961 }
962 }
963
964 if (!Contains (theSelectableObject))
965 {
966 aStatus = aStatus + "Not Present in the selector\n\n";
967 }
968
969 return aStatus;
970 }
971
972 //=======================================================================
973 //function : SortResult
974 //purpose :
975 //=======================================================================
SortResult() const976 void SelectMgr_ViewerSelector::SortResult() const
977 {
978 if (mystored.IsEmpty())
979 {
980 myIsSorted = true;
981 return;
982 }
983
984 const Standard_Integer anExtent = mystored.Extent();
985 if (anExtent != myIndexes.Length())
986 {
987 myIndexes.Resize (1, anExtent, false);
988 }
989
990 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
991 {
992 myIndexes.SetValue (anIndexIter, anIndexIter);
993 }
994 std::sort (myIndexes.begin(), myIndexes.end(), CompareResults (mystored, myToPreferClosest));
995 myIsSorted = true;
996 }
997
998 //=======================================================================
999 // function : AddSelectableObject
1000 // purpose : Adds new object to the map of selectable objects
1001 //=======================================================================
AddSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1002 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1003 {
1004 if (!myMapOfObjectSensitives.IsBound (theObject))
1005 {
1006 mySelectableObjects.Append (theObject);
1007 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
1008 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
1009 }
1010 }
1011
1012 //=======================================================================
1013 // function : AddSelectionToObject
1014 // purpose : Adds new selection to the object and builds its BVH tree
1015 //=======================================================================
AddSelectionToObject(const Handle (SelectMgr_SelectableObject)& theObject,const Handle (SelectMgr_Selection)& theSelection)1016 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
1017 const Handle(SelectMgr_Selection)& theSelection)
1018 {
1019 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
1020 {
1021 (*anEntitySet)->Append (theSelection);
1022 (*anEntitySet)->BVH();
1023 }
1024 else
1025 {
1026 AddSelectableObject (theObject);
1027 AddSelectionToObject (theObject, theSelection);
1028 }
1029 }
1030
1031 //=======================================================================
1032 // function : MoveSelectableObject
1033 // purpose :
1034 //=======================================================================
MoveSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1035 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1036 {
1037 mySelectableObjects.ChangeSubset (theObject);
1038 }
1039
1040 //=======================================================================
1041 // function : RemoveSelectableObject
1042 // purpose : Removes selectable object from map of selectable ones
1043 //=======================================================================
RemoveSelectableObject(const Handle (SelectMgr_SelectableObject)& theObject)1044 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
1045 {
1046 Handle(SelectMgr_SelectableObject) anObj = theObject;
1047 if (myMapOfObjectSensitives.UnBind (theObject))
1048 {
1049 RemovePicked (theObject);
1050 mySelectableObjects.Remove (theObject);
1051 }
1052 }
1053
1054 //=======================================================================
1055 // function : RemoveSelectionOfObject
1056 // purpose : Removes selection of the object and marks its BVH tree
1057 // for rebuild
1058 //=======================================================================
RemoveSelectionOfObject(const Handle (SelectMgr_SelectableObject)& theObject,const Handle (SelectMgr_Selection)& theSelection)1059 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
1060 const Handle(SelectMgr_Selection)& theSelection)
1061 {
1062 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
1063 {
1064 (*anEntitySet)->Remove (theSelection);
1065 }
1066 }
1067
1068 //=======================================================================
1069 // function : RebuildObjectsTree
1070 // purpose : Marks BVH of selectable objects for rebuild
1071 //=======================================================================
RebuildObjectsTree(const Standard_Boolean theIsForce)1072 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
1073 {
1074 mySelectableObjects.MarkDirty();
1075
1076 if (theIsForce)
1077 {
1078 Graphic3d_Vec2i aWinSize;
1079 mySelectingVolumeMgr.WindowSize (aWinSize.x(), aWinSize.y());
1080 mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), aWinSize);
1081 }
1082 }
1083
1084 //=======================================================================
1085 // function : RebuildSensitivesTree
1086 // purpose : Marks BVH of sensitive entities of particular selectable
1087 // object for rebuild
1088 //=======================================================================
RebuildSensitivesTree(const Handle (SelectMgr_SelectableObject)& theObject,const Standard_Boolean theIsForce)1089 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1090 const Standard_Boolean theIsForce)
1091 {
1092 if (!Contains (theObject))
1093 return;
1094
1095 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1096 anEntitySet->MarkDirty();
1097
1098 if (theIsForce)
1099 {
1100 anEntitySet->BVH();
1101 }
1102 }
1103
1104 //=======================================================================
1105 // function : resetSelectionActivationStatus
1106 // purpose : Marks all added sensitive entities of all objects as
1107 // non-selectable
1108 //=======================================================================
ResetSelectionActivationStatus()1109 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1110 {
1111 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1112 {
1113 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1114 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1115 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1116 {
1117 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1118 }
1119 }
1120 }
1121
1122 //=======================================================================
1123 // function : ActiveOwners
1124 // purpose : Returns the list of active entity owners
1125 //=======================================================================
ActiveOwners(NCollection_List<Handle (SelectMgr_EntityOwner)> & theOwners) const1126 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1127 {
1128 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1129 {
1130 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1131 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1132 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1133 {
1134 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1135 if (aSensitive->IsActiveForSelection())
1136 {
1137 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1138 }
1139 }
1140 }
1141 }
1142
1143 //=======================================================================
1144 //function : AllowOverlapDetection
1145 //purpose : Sets the detection type: if theIsToAllow is false,
1146 // only fully included sensitives will be detected, otherwise
1147 // the algorithm will mark both included and overlapped entities
1148 // as matched
1149 //=======================================================================
AllowOverlapDetection(const Standard_Boolean theIsToAllow)1150 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1151 {
1152 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1153 }
1154
1155 //=======================================================================
1156 // Function: Pick
1157 // Purpose :
1158 //=======================================================================
Pick(const Standard_Integer theXPix,const Standard_Integer theYPix,const Handle (V3d_View)& theView)1159 void SelectMgr_ViewerSelector::Pick (const Standard_Integer theXPix,
1160 const Standard_Integer theYPix,
1161 const Handle(V3d_View)& theView)
1162 {
1163 updateZLayers (theView);
1164
1165 gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
1166 static_cast<Standard_Real> (theYPix));
1167 mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos);
1168
1169 mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
1170 mySelectingVolumeMgr.SetCamera (theView->Camera());
1171 Standard_Integer aWidth = 0, aHeight = 0;
1172 theView->Window()->Size (aWidth, aHeight);
1173 mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1174
1175 mySelectingVolumeMgr.BuildSelectingVolume();
1176 mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1177
1178 TraverseSensitives();
1179 }
1180
1181 //=======================================================================
1182 // Function: Pick
1183 // Purpose :
1184 //=======================================================================
Pick(const Standard_Integer theXPMin,const Standard_Integer theYPMin,const Standard_Integer theXPMax,const Standard_Integer theYPMax,const Handle (V3d_View)& theView)1185 void SelectMgr_ViewerSelector::Pick (const Standard_Integer theXPMin,
1186 const Standard_Integer theYPMin,
1187 const Standard_Integer theXPMax,
1188 const Standard_Integer theYPMax,
1189 const Handle(V3d_View)& theView)
1190 {
1191 updateZLayers (theView);
1192
1193 gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin),
1194 static_cast<Standard_Real> (theYPMin));
1195 gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax),
1196 static_cast<Standard_Real> (theYPMax));
1197 mySelectingVolumeMgr.InitBoxSelectingVolume (aMinMousePos,
1198 aMaxMousePos);
1199
1200 mySelectingVolumeMgr.SetCamera (theView->Camera());
1201 Standard_Integer aWidth = 0, aHeight = 0;
1202 theView->Window()->Size (aWidth, aHeight);
1203 mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1204
1205 mySelectingVolumeMgr.BuildSelectingVolume();
1206 mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1207 TraverseSensitives();
1208 }
1209
1210 //=======================================================================
1211 // Function: Pick
1212 // Purpose : Selection using a polyline
1213 //=======================================================================
Pick(const TColgp_Array1OfPnt2d & thePolyline,const Handle (V3d_View)& theView)1214 void SelectMgr_ViewerSelector::Pick (const TColgp_Array1OfPnt2d& thePolyline,
1215 const Handle(V3d_View)& theView)
1216 {
1217 updateZLayers (theView);
1218
1219 mySelectingVolumeMgr.InitPolylineSelectingVolume (thePolyline);
1220 mySelectingVolumeMgr.SetCamera (theView->Camera());
1221 Standard_Integer aWidth = 0, aHeight = 0;
1222 theView->Window()->Size (aWidth, aHeight);
1223 mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
1224 mySelectingVolumeMgr.BuildSelectingVolume();
1225 mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1226
1227 TraverseSensitives();
1228 }
1229
1230 //=======================================================================
1231 // Function: Pick
1232 // Purpose :
1233 //=======================================================================
Pick(const gp_Ax1 & theAxis,const Handle (V3d_View)& theView)1234 void SelectMgr_ViewerSelector::Pick (const gp_Ax1& theAxis,
1235 const Handle(V3d_View)& theView)
1236 {
1237 updateZLayers (theView);
1238
1239 mySelectingVolumeMgr.InitAxisSelectingVolume (theAxis);
1240 mySelectingVolumeMgr.BuildSelectingVolume();
1241 mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes(), Handle(Graphic3d_SequenceOfHClipPlane)(), NULL);
1242
1243 TraverseSensitives();
1244 }
1245
1246 //=======================================================================
1247 //function : ToPixMap
1248 //purpose :
1249 //=======================================================================
ToPixMap(Image_PixMap & theImage,const Handle (V3d_View)& theView,const StdSelect_TypeOfSelectionImage theType,const Standard_Integer thePickedIndex)1250 Standard_Boolean SelectMgr_ViewerSelector::ToPixMap (Image_PixMap& theImage,
1251 const Handle(V3d_View)& theView,
1252 const StdSelect_TypeOfSelectionImage theType,
1253 const Standard_Integer thePickedIndex)
1254 {
1255 if (theImage.IsEmpty())
1256 {
1257 throw Standard_ProgramError ("SelectMgr_ViewerSelector::ToPixMap() has been called with empty image");
1258 }
1259
1260 Handle(SelectMgr_SelectionImageFiller) aFiller = SelectMgr_SelectionImageFiller::CreateFiller (theImage, this, theType);
1261 if (aFiller.IsNull())
1262 {
1263 return Standard_False;
1264 }
1265
1266 const Standard_Integer aSizeX = static_cast<Standard_Integer> (theImage.SizeX());
1267 const Standard_Integer aSizeY = static_cast<Standard_Integer> (theImage.SizeY());
1268 for (Standard_Integer aRowIter = 0; aRowIter < aSizeY; ++aRowIter)
1269 {
1270 for (Standard_Integer aColIter = 0; aColIter < aSizeX; ++aColIter)
1271 {
1272 Pick (aColIter, aRowIter, theView);
1273 aFiller->Fill (aColIter, aRowIter, thePickedIndex);
1274 }
1275 }
1276 aFiller->Flush();
1277 return Standard_True;
1278 }
1279
1280 //=======================================================================
1281 // Function: DisplaySensitive.
1282 // Purpose : Display active primitives.
1283 //=======================================================================
DisplaySensitive(const Handle (V3d_View)& theView)1284 void SelectMgr_ViewerSelector::DisplaySensitive (const Handle(V3d_View)& theView)
1285 {
1286 for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1287 {
1288 Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
1289 const Handle (SelectMgr_SelectableObject)& anObj = aSelectableIt.Value();
1290 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
1291 {
1292 if (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated)
1293 {
1294 SelectMgr::ComputeSensitivePrs (aStruct, aSelIter.Value(), anObj->Transformation(), anObj->TransformPersistence());
1295 }
1296 }
1297
1298 myStructs.Append (aStruct);
1299 }
1300
1301 for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructs); aStructIter.More(); aStructIter.Next())
1302 {
1303 Handle(Graphic3d_Structure)& aStruct = aStructIter.ChangeValue();
1304 aStruct->SetDisplayPriority (10);
1305 aStruct->Display();
1306 }
1307
1308 theView->Update();
1309 }
1310
1311 //=======================================================================
1312 // Function: ClearSensitive
1313 // Purpose :
1314 //=======================================================================
ClearSensitive(const Handle (V3d_View)& theView)1315 void SelectMgr_ViewerSelector::ClearSensitive (const Handle(V3d_View)& theView)
1316 {
1317 for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructs); aStructIter.More(); aStructIter.Next())
1318 {
1319 const Handle(Graphic3d_Structure)& aPrs = aStructIter.ChangeValue();
1320 aPrs->Erase();
1321 aPrs->Clear();
1322 aPrs->Remove();
1323 }
1324 myStructs.Clear();
1325
1326 if (!theView.IsNull())
1327 {
1328 theView->Update();
1329 }
1330 }
1331
1332 //=======================================================================
1333 //function : DisplaySenstive
1334 //purpose :
1335 //=======================================================================
DisplaySensitive(const Handle (SelectMgr_Selection)& theSel,const gp_Trsf & theTrsf,const Handle (V3d_View)& theView,const Standard_Boolean theToClearOthers)1336 void SelectMgr_ViewerSelector::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
1337 const gp_Trsf& theTrsf,
1338 const Handle(V3d_View)& theView,
1339 const Standard_Boolean theToClearOthers)
1340 {
1341 if (theToClearOthers)
1342 {
1343 ClearSensitive (theView);
1344 }
1345
1346 Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
1347
1348 SelectMgr::ComputeSensitivePrs (aStruct, theSel, theTrsf, Handle(Graphic3d_TransformPers)());
1349
1350 myStructs.Append (aStruct);
1351 myStructs.Last()->SetDisplayPriority (10);
1352 myStructs.Last()->Display();
1353
1354 theView->Update();
1355 }
1356
1357 //=======================================================================
1358 //function : DumpJson
1359 //purpose :
1360 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const1361 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1362 {
1363 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1364
1365 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1366 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1367
1368 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1369 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1370
1371 Standard_Integer aNbOfSelectableObjects = 0;
1372 for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1373 {
1374 aNbOfSelectableObjects++;
1375 }
1376 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1377
1378 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1379 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1380 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1381
1382 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1383 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1384 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1385 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1386
1387 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes.Size())
1388
1389 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1390 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1391
1392 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myStructs.Length())
1393 for (Graphic3d_SequenceOfStructure::Iterator aStructsIt (myStructs); aStructsIt.More(); aStructsIt.Next())
1394 {
1395 const Handle(Graphic3d_Structure)& aStructure = aStructsIt.Value();
1396 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, aStructure)
1397 }
1398 }
1399
1400 //=======================================================================
1401 //function : SetToPrebuildBVH
1402 //purpose :
1403 //=======================================================================
SetToPrebuildBVH(Standard_Boolean theToPrebuild,Standard_Integer theThreadsNum)1404 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1405 {
1406 if (!theToPrebuild && !myBVHThreadPool.IsNull())
1407 {
1408 myBVHThreadPool.Nullify();
1409 }
1410 else if (theToPrebuild)
1411 {
1412 myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1413 }
1414 myToPrebuildBVH = theToPrebuild;
1415 }
1416
1417 //=======================================================================
1418 //function : QueueBVHBuild
1419 //purpose :
1420 //=======================================================================
QueueBVHBuild(const Handle (Select3D_SensitiveEntity)& theEntity)1421 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1422 {
1423 if (myToPrebuildBVH)
1424 {
1425 myBVHThreadPool->AddEntity (theEntity);
1426 }
1427 }
1428
1429 //=======================================================================
1430 //function : WaitForBVHBuild
1431 //purpose :
1432 //=======================================================================
WaitForBVHBuild()1433 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1434 {
1435 if (myToPrebuildBVH)
1436 {
1437 myBVHThreadPool->WaitThreads();
1438 }
1439 }
1440