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