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 | { |
7479f643 |
272 | Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1; |
273 | const gp_Trsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf; |
274 | const Standard_Boolean toScale = aScale != 1; |
275 | const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity; |
276 | if (toScale && toTransform) |
3bf9a45f |
277 | { |
7479f643 |
278 | theResMgr = mySelectingVolumeMgr.ScaleAndTransform (aScale, aTrsfMtr); |
3bf9a45f |
279 | } |
280 | else if (toScale) |
281 | { |
282 | if (!theCachedMgrs.IsBound (aScale)) |
283 | { |
7479f643 |
284 | theCachedMgrs.Bind (aScale, mySelectingVolumeMgr.ScaleAndTransform (aScale, gp_Trsf())); |
3bf9a45f |
285 | } |
3bf9a45f |
286 | theResMgr = theCachedMgrs.Find (aScale); |
287 | } |
7479f643 |
288 | else if (toTransform) |
289 | { |
290 | theResMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTrsfMtr); |
291 | } |
3bf9a45f |
292 | } |
293 | |
f751596e |
294 | //======================================================================= |
295 | // function: traverseObject |
296 | // purpose : Internal function that checks if there is possible overlap |
297 | // between some entity of selectable object theObject and |
298 | // current selecting volume |
299 | //======================================================================= |
300 | void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject) |
7fd59977 |
301 | { |
f751596e |
302 | NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = |
303 | myMapOfObjectSensitives.ChangeFind (theObject); |
7fd59977 |
304 | |
f751596e |
305 | if (anEntitySet->Size() == 0) |
306 | return; |
7fd59977 |
307 | |
f751596e |
308 | const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH(); |
7fd59977 |
309 | |
825aa485 |
310 | gp_Trsf aInversedTrsf; |
311 | |
312 | if (theObject->HasTransformation() || theObject->TransformPersistence().Flags) |
313 | { |
314 | if (!theObject->TransformPersistence().Flags) |
315 | { |
316 | aInversedTrsf = theObject->InversedTransformation(); |
317 | } |
318 | else |
319 | { |
320 | const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); |
321 | const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); |
322 | |
323 | gp_Trsf aTPers; |
324 | Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (aProjection, aWorldView, 0, 0); |
325 | aTPers.SetValues (aMat.GetValue (0, 0), aMat.GetValue (0, 1), aMat.GetValue (0, 2), aMat.GetValue (0, 3), |
326 | aMat.GetValue (1, 0), aMat.GetValue (1, 1), aMat.GetValue (1, 2), aMat.GetValue (1, 3), |
327 | aMat.GetValue (2, 0), aMat.GetValue (2, 1), aMat.GetValue (2, 2), aMat.GetValue (2, 3)); |
328 | |
329 | aInversedTrsf = (aTPers * theObject->Transformation()).Inverted(); |
330 | } |
331 | } |
332 | |
333 | SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity |
3bf9a45f |
334 | ? mySelectingVolumeMgr.ScaleAndTransform (1, aInversedTrsf) |
825aa485 |
335 | : mySelectingVolumeMgr; |
7fd59977 |
336 | |
3bf9a45f |
337 | SelectMgr_FrustumCache aScaledTrnsfFrustums; |
28ee613b |
338 | |
f751596e |
339 | Standard_Integer aNode = 0; // a root node |
340 | if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0), |
341 | aSensitivesTree->MaxPoint (0))) |
342 | { |
343 | return; |
7fd59977 |
344 | } |
f751596e |
345 | Standard_Integer aStack[32]; |
346 | Standard_Integer aHead = -1; |
347 | for (;;) |
348 | { |
349 | if (!aSensitivesTree->IsOuter (aNode)) |
350 | { |
351 | const Standard_Integer aLeftChildIdx = aSensitivesTree->LeftChild (aNode); |
352 | const Standard_Integer aRightChildIdx = aSensitivesTree->RightChild (aNode); |
353 | const Standard_Boolean isLeftChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aLeftChildIdx), |
354 | aSensitivesTree->MaxPoint (aLeftChildIdx)); |
355 | const Standard_Boolean isRightChildIn = aMgr.Overlaps (aSensitivesTree->MinPoint (aRightChildIdx), |
356 | aSensitivesTree->MaxPoint (aRightChildIdx)); |
357 | if (isLeftChildIn |
358 | && isRightChildIn) |
359 | { |
360 | aNode = aLeftChildIdx; |
361 | ++aHead; |
362 | aStack[aHead] = aRightChildIdx; |
363 | } |
364 | else if (isLeftChildIn |
365 | || isRightChildIn) |
366 | { |
367 | aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; |
368 | } |
369 | else |
370 | { |
371 | if (aHead < 0) |
372 | { |
373 | break; |
374 | } |
7fd59977 |
375 | |
f751596e |
376 | aNode = aStack[aHead]; |
377 | --aHead; |
378 | } |
379 | } |
380 | else |
381 | { |
382 | Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode); |
383 | Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode); |
384 | for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) |
385 | { |
7ab15952 |
386 | const Handle(SelectMgr_SensitiveEntity)& aSensitive = |
f751596e |
387 | anEntitySet->GetSensitiveById (anIdx); |
388 | if (aSensitive->IsActiveForSelection()) |
389 | { |
28ee613b |
390 | const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); |
391 | SelectMgr_SelectingVolumeManager aTmpMgr = aMgr; |
3bf9a45f |
392 | computeFrustum (anEnt, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr); |
28ee613b |
393 | checkOverlap (anEnt, anIdx, aTmpMgr); |
f751596e |
394 | } |
395 | } |
396 | if (aHead < 0) |
397 | { |
398 | break; |
399 | } |
7fd59977 |
400 | |
f751596e |
401 | aNode = aStack[aHead]; |
402 | --aHead; |
403 | } |
7fd59977 |
404 | } |
405 | } |
406 | |
f751596e |
407 | //======================================================================= |
408 | // function: TraverseSensitives |
409 | // purpose : Traverses BVH containing all added selectable objects and |
410 | // finds candidates for further search of overlap |
411 | //======================================================================= |
412 | void SelectMgr_ViewerSelector::TraverseSensitives() |
7fd59977 |
413 | { |
414 | mystored.Clear(); |
f751596e |
415 | myMapOfDetected.Clear(); |
7fd59977 |
416 | |
825aa485 |
417 | NCollection_Handle<BVH_Tree<Standard_Real, 3> > aBVHTree; |
418 | for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) |
f751596e |
419 | { |
825aa485 |
420 | const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; |
421 | if (isTrsfPers) |
4269bd1b |
422 | { |
825aa485 |
423 | if (mySelectableObjectsTrsfPers.Size() == 0) |
4269bd1b |
424 | { |
825aa485 |
425 | continue; |
f751596e |
426 | } |
825aa485 |
427 | const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); |
428 | const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); |
429 | const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); |
430 | aBVHTree = mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState); |
431 | } |
432 | else |
433 | { |
434 | if (mySelectableObjects.Size() == 0) |
f751596e |
435 | { |
825aa485 |
436 | continue; |
437 | } |
438 | aBVHTree = mySelectableObjects.BVH(); |
439 | } |
440 | |
441 | Standard_Integer aNode = 0; |
442 | if (!mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (0), |
443 | aBVHTree->MaxPoint (0))) |
444 | { |
445 | continue; |
446 | } |
447 | |
448 | Standard_Integer aStack[32]; |
449 | Standard_Integer aHead = -1; |
450 | for (;;) |
451 | { |
452 | if (!aBVHTree->IsOuter (aNode)) |
453 | { |
454 | const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); |
455 | const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); |
456 | const Standard_Boolean isLeftChildIn = |
457 | mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), |
458 | aBVHTree->MaxPoint (aLeftChildIdx)); |
459 | const Standard_Boolean isRightChildIn = |
460 | mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), |
461 | aBVHTree->MaxPoint (aRightChildIdx)); |
462 | if (isLeftChildIn |
463 | && isRightChildIn) |
464 | { |
465 | aNode = aLeftChildIdx; |
466 | ++aHead; |
467 | aStack[aHead] = aRightChildIdx; |
468 | } |
469 | else if (isLeftChildIn |
470 | || isRightChildIn) |
471 | { |
472 | aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; |
473 | } |
474 | else |
475 | { |
476 | if (aHead < 0) |
477 | { |
478 | break; |
479 | } |
480 | |
481 | aNode = aStack[aHead]; |
482 | --aHead; |
483 | } |
f751596e |
484 | } |
485 | else |
486 | { |
825aa485 |
487 | Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode); |
488 | Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode); |
489 | for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) |
490 | { |
491 | Handle(SelectMgr_SelectableObject) aSelectableObject = |
492 | isTrsfPers ? mySelectableObjectsTrsfPers.GetObjectById (anIdx) |
493 | : mySelectableObjects.GetObjectById (anIdx); |
494 | |
495 | traverseObject (aSelectableObject); |
496 | } |
f751596e |
497 | if (aHead < 0) |
4269bd1b |
498 | { |
f751596e |
499 | break; |
4269bd1b |
500 | } |
7fd59977 |
501 | |
f751596e |
502 | aNode = aStack[aHead]; |
503 | --aHead; |
7fd59977 |
504 | } |
505 | } |
7fd59977 |
506 | } |
4269bd1b |
507 | |
f751596e |
508 | SortResult(); |
7fd59977 |
509 | } |
4269bd1b |
510 | |
7fd59977 |
511 | //================================================== |
512 | // Function: Picked |
513 | // Purpose : |
514 | //================================================== |
515 | Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector |
516 | ::Picked() const |
517 | { |
f751596e |
518 | Standard_Integer RankInMap = myIndexes->Value (myCurRank); |
7fd59977 |
519 | const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap); |
c5f3a425 |
520 | Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto); |
7fd59977 |
521 | return Ownr; |
522 | } |
523 | |
524 | |
525 | |
526 | //======================================================================= |
527 | //function : More |
4269bd1b |
528 | //purpose : |
7fd59977 |
529 | //======================================================================= |
4269bd1b |
530 | Standard_Boolean SelectMgr_ViewerSelector::More() |
7fd59977 |
531 | { |
532 | if(mystored.Extent()==0) return Standard_False; |
533 | if(myCurRank==0) return Standard_False; |
534 | return myCurRank <= myIndexes->Length(); |
535 | } |
536 | |
537 | //================================================== |
538 | // Function: OnePicked |
539 | // Purpose : only the best one is chosen |
540 | // depend on priority and mindist... |
541 | //================================================== |
542 | |
543 | Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector |
544 | ::OnePicked() |
545 | { |
546 | |
547 | Init(); |
548 | if(More()){ |
f751596e |
549 | Standard_Integer RankInMap = myIndexes->Value (myIndexes->Lower()); |
7fd59977 |
550 | const Handle(SelectBasics_EntityOwner)& toto = mystored.FindKey(RankInMap); |
c5f3a425 |
551 | Handle(SelectMgr_EntityOwner) Ownr = Handle(SelectMgr_EntityOwner)::DownCast (toto); |
7fd59977 |
552 | return Ownr; |
553 | } |
554 | |
555 | Handle (SelectMgr_EntityOwner) NullObj; //returns a null Handle if there was not successfull pick... |
556 | return NullObj; |
557 | } |
558 | |
559 | |
560 | //======================================================================= |
561 | //function : NbPicked |
4269bd1b |
562 | //purpose : |
7fd59977 |
563 | //======================================================================= |
564 | |
565 | Standard_Integer SelectMgr_ViewerSelector::NbPicked() const |
566 | { |
567 | return mystored.Extent(); |
568 | } |
569 | //======================================================================= |
570 | //function : Picked |
4269bd1b |
571 | //purpose : |
7fd59977 |
572 | //======================================================================= |
573 | Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked(const Standard_Integer aRank) const |
574 | { |
575 | |
f751596e |
576 | Handle(SelectMgr_EntityOwner) anOwner; |
577 | if (aRank < 1 || aRank > NbPicked()) |
578 | return anOwner; |
579 | Standard_Integer anOwnerIdx = myIndexes->Value (aRank); |
7fd59977 |
580 | |
581 | |
f751596e |
582 | const Handle(SelectBasics_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx); |
583 | anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aStoredOwner); |
584 | return anOwner; |
7fd59977 |
585 | } |
586 | |
7fd59977 |
587 | //=================================================== |
588 | // |
589 | // INTERNAL METHODS .... |
590 | // |
591 | //================================================== |
592 | |
7fd59977 |
593 | //================================================== |
594 | // Function: Contains |
4269bd1b |
595 | // Purpose : |
7fd59977 |
596 | //================================================== |
f751596e |
597 | Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const |
7fd59977 |
598 | { |
825aa485 |
599 | return mySelectableObjects.Contains (theObject) |
600 | || mySelectableObjectsTrsfPers.Contains (theObject); |
7fd59977 |
601 | } |
602 | |
7fd59977 |
603 | //================================================== |
604 | // Function: ActiveModes |
605 | // Purpose : return all the modes with a given state for an object |
606 | //================================================== |
f751596e |
607 | Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject, |
608 | TColStd_ListOfInteger& theModeList, |
609 | const SelectMgr_StateOfSelection theWantedState) const |
7fd59977 |
610 | { |
825aa485 |
611 | Standard_Boolean hasActivatedStates = Contains (theSelectableObject); |
f751596e |
612 | for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) |
613 | { |
614 | if (theWantedState == SelectMgr_SOS_Any) |
615 | { |
616 | theModeList.Append (theSelectableObject->CurrentSelection()->Mode()); |
617 | } |
618 | else if (theWantedState == theSelectableObject->CurrentSelection()->GetSelectionState()) |
619 | { |
620 | theModeList.Append (theSelectableObject->CurrentSelection()->Mode()); |
621 | } |
7fd59977 |
622 | } |
7fd59977 |
623 | |
f751596e |
624 | return hasActivatedStates; |
625 | } |
7fd59977 |
626 | |
f751596e |
627 | //================================================== |
628 | // Function: IsActive |
629 | // Purpose : |
630 | //================================================== |
631 | Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject, |
632 | const Standard_Integer theMode) const |
7fd59977 |
633 | { |
825aa485 |
634 | if (!Contains (theSelectableObject)) |
f751596e |
635 | return Standard_False; |
636 | |
637 | for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) |
638 | { |
639 | if (theMode == theSelectableObject->CurrentSelection()->Mode()) |
640 | { |
641 | return theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated; |
7fd59977 |
642 | } |
643 | } |
f751596e |
644 | |
7fd59977 |
645 | return Standard_False; |
646 | } |
647 | |
f751596e |
648 | //================================================== |
649 | // Function: IsInside |
650 | // Purpose : |
651 | //================================================== |
652 | Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject, |
653 | const Standard_Integer theMode) const |
7fd59977 |
654 | { |
825aa485 |
655 | if (!Contains (theSelectableObject)) |
f751596e |
656 | return Standard_False; |
7fd59977 |
657 | |
f751596e |
658 | for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) |
659 | { |
660 | if (theMode == theSelectableObject->CurrentSelection()->Mode()) |
661 | { |
662 | return theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown; |
7fd59977 |
663 | } |
664 | } |
f751596e |
665 | |
7fd59977 |
666 | return Standard_False; |
667 | } |
668 | |
669 | |
670 | //======================================================================= |
671 | //function : Status |
4269bd1b |
672 | //purpose : |
7fd59977 |
673 | //======================================================================= |
674 | |
f751596e |
675 | SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const |
7fd59977 |
676 | { |
f751596e |
677 | return theSelection->GetSelectionState(); |
7fd59977 |
678 | } |
679 | |
7fd59977 |
680 | //================================================== |
681 | // Function: Status |
682 | // Purpose : gives Information about selectors |
683 | //================================================== |
684 | |
f751596e |
685 | TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const |
7fd59977 |
686 | { |
f751596e |
687 | TCollection_AsciiString aStatus ("Status Object :\n\t"); |
688 | |
689 | for (theSelectableObject->Init(); theSelectableObject->More(); theSelectableObject->Next()) |
690 | { |
691 | if (theSelectableObject->CurrentSelection()->GetSelectionState() != SelectMgr_SOS_Unknown) |
7fd59977 |
692 | { |
f751596e |
693 | aStatus = aStatus + "Mode " + |
694 | TCollection_AsciiString (theSelectableObject->CurrentSelection()->Mode()) + |
695 | " present - "; |
696 | if (theSelectableObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated) |
697 | { |
698 | aStatus = aStatus + " Active \n\t"; |
699 | } |
7fd59977 |
700 | else |
f751596e |
701 | { |
702 | aStatus = aStatus + " Inactive \n\t"; |
703 | } |
7fd59977 |
704 | } |
705 | } |
706 | |
825aa485 |
707 | if (!Contains (theSelectableObject)) |
7fd59977 |
708 | { |
f751596e |
709 | aStatus = aStatus + "Not Present in the selector\n\n"; |
7fd59977 |
710 | } |
f751596e |
711 | |
712 | return aStatus; |
7fd59977 |
713 | } |
714 | |
715 | //======================================================================= |
716 | //function : SortResult |
4269bd1b |
717 | //purpose : there is a certain number of entities ranged by criteria |
81bba717 |
718 | // (depth, size, priority, mouse distance from borders or |
719 | // CDG of the detected primitive. Parsing : |
720 | // maximum priorities . |
721 | // then a reasonable compromise between depth and distance... |
722 | // finally the ranges are stored in myindexes depending on the parsing. |
4269bd1b |
723 | // so, it is possible to only read |
7fd59977 |
724 | //======================================================================= |
725 | void SelectMgr_ViewerSelector::SortResult() |
726 | { |
727 | if(mystored.IsEmpty()) return; |
728 | |
729 | const Standard_Integer anExtent = mystored.Extent(); |
730 | if(myIndexes.IsNull() || anExtent != myIndexes->Length()) |
731 | myIndexes = new TColStd_HArray1OfInteger (1, anExtent); |
732 | |
81bba717 |
733 | // to work faster... |
7fd59977 |
734 | TColStd_Array1OfInteger& thearr = myIndexes->ChangeArray1(); |
735 | |
81bba717 |
736 | // indices from 1 to N are loaded |
7fd59977 |
737 | Standard_Integer I ; |
738 | for (I=1; I <= anExtent; I++) |
739 | thearr(I)=I; |
740 | |
e35db416 |
741 | std::sort (thearr.begin(), thearr.end(), CompareResults (mystored)); |
742 | |
f751596e |
743 | } |
744 | |
745 | //======================================================================= |
746 | //function : HasDepthClipping |
747 | //purpose : Stub |
748 | //======================================================================= |
749 | Standard_Boolean SelectMgr_ViewerSelector::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& /*theOwner*/) const |
750 | { |
751 | return Standard_False; |
752 | } |
753 | |
754 | //======================================================================= |
755 | // function : AddSelectableObject |
756 | // purpose : Adds new object to the map of selectable objects |
757 | //======================================================================= |
758 | void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject) |
759 | { |
760 | if (!myMapOfObjectSensitives.IsBound (theObject)) |
761 | { |
825aa485 |
762 | if (!theObject->TransformPersistence().Flags) |
763 | { |
764 | mySelectableObjects.Append (theObject); |
765 | } |
766 | else |
767 | { |
768 | mySelectableObjectsTrsfPers.Append (theObject); |
769 | } |
770 | |
f751596e |
771 | NCollection_Handle<SelectMgr_SensitiveEntitySet> anEntitySet = new SelectMgr_SensitiveEntitySet(); |
772 | myMapOfObjectSensitives.Bind (theObject, anEntitySet); |
7fd59977 |
773 | } |
f751596e |
774 | } |
7fd59977 |
775 | |
f751596e |
776 | //======================================================================= |
777 | // function : AddSelectionToObject |
778 | // purpose : Adds new selection to the object and builds its BVH tree |
779 | //======================================================================= |
780 | void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject, |
781 | const Handle(SelectMgr_Selection)& theSelection) |
782 | { |
783 | if (myMapOfObjectSensitives.IsBound (theObject)) |
784 | { |
785 | NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = |
786 | myMapOfObjectSensitives.ChangeFind (theObject); |
787 | anEntitySet->Append (theSelection); |
788 | anEntitySet->BVH(); |
789 | } |
790 | else |
791 | { |
792 | AddSelectableObject (theObject); |
793 | AddSelectionToObject (theObject, theSelection); |
794 | } |
7fd59977 |
795 | } |
796 | |
f751596e |
797 | //======================================================================= |
798 | // function : RemoveSelectableObject |
799 | // purpose : Removes selectable object from map of selectable ones |
800 | //======================================================================= |
801 | void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject) |
802 | { |
803 | if (myMapOfObjectSensitives.IsBound (theObject)) |
804 | { |
825aa485 |
805 | if (!mySelectableObjects.Remove (theObject)) |
806 | { |
807 | mySelectableObjectsTrsfPers.Remove (theObject); |
808 | } |
f751596e |
809 | myMapOfObjectSensitives.UnBind (theObject); |
f751596e |
810 | } |
811 | } |
7fd59977 |
812 | |
813 | //======================================================================= |
f751596e |
814 | // function : RemoveSelectionOfObject |
815 | // purpose : Removes selection of the object and marks its BVH tree |
816 | // for rebuild |
7fd59977 |
817 | //======================================================================= |
f751596e |
818 | void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject, |
819 | const Handle(SelectMgr_Selection)& theSelection) |
7fd59977 |
820 | { |
f751596e |
821 | if (myMapOfObjectSensitives.IsBound (theObject)) |
822 | { |
823 | NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = |
824 | myMapOfObjectSensitives.ChangeFind (theObject); |
825 | anEntitySet->Remove (theSelection); |
826 | } |
7fd59977 |
827 | } |
828 | |
829 | //======================================================================= |
f751596e |
830 | // function : RebuildObjectsTree |
831 | // purpose : Marks BVH of selectable objects for rebuild |
7fd59977 |
832 | //======================================================================= |
f751596e |
833 | void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce) |
7fd59977 |
834 | { |
825aa485 |
835 | mySelectableObjects.MarkDirty(); |
836 | mySelectableObjectsTrsfPers.MarkDirty(); |
f751596e |
837 | |
838 | if (theIsForce) |
839 | { |
825aa485 |
840 | const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); |
841 | const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); |
842 | const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); |
843 | |
844 | mySelectableObjects.BVH(); |
845 | mySelectableObjectsTrsfPers.BVH (aProjection, aWorldView, aWVPState); |
f751596e |
846 | } |
7fd59977 |
847 | } |
4269bd1b |
848 | |
849 | //======================================================================= |
f751596e |
850 | // function : RebuildSensitivesTree |
851 | // purpose : Marks BVH of sensitive entities of particular selectable |
852 | // object for rebuild |
4269bd1b |
853 | //======================================================================= |
f751596e |
854 | void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject, |
855 | const Standard_Boolean theIsForce) |
4269bd1b |
856 | { |
825aa485 |
857 | if (!Contains (theObject)) |
f751596e |
858 | return; |
859 | |
860 | NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject); |
861 | anEntitySet->MarkDirty(); |
862 | |
863 | if (theIsForce) |
864 | { |
865 | anEntitySet->BVH(); |
866 | } |
4269bd1b |
867 | } |
868 | |
869 | //======================================================================= |
f751596e |
870 | // function : resetSelectionActivationStatus |
871 | // purpose : Marks all added sensitive entities of all objects as |
872 | // non-selectable |
4269bd1b |
873 | //======================================================================= |
29a4908e |
874 | void SelectMgr_ViewerSelector::ResetSelectionActivationStatus() |
4269bd1b |
875 | { |
f751596e |
876 | SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); |
877 | for ( ; aSensitivesIter.More(); aSensitivesIter.Next()) |
878 | { |
879 | NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = |
880 | aSensitivesIter.ChangeValue(); |
881 | Standard_Integer anEntitiesNb = anEntitySet->Size(); |
882 | for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx) |
883 | { |
884 | anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus(); |
885 | } |
886 | } |
4269bd1b |
887 | } |
888 | |
889 | //======================================================================= |
f751596e |
890 | // function : DetectedEntity |
891 | // purpose : Returns sensitive entity that was detected during the |
892 | // previous run of selection algorithm |
4269bd1b |
893 | //======================================================================= |
f751596e |
894 | const Handle(SelectBasics_SensitiveEntity)& SelectMgr_ViewerSelector::DetectedEntity() const |
4269bd1b |
895 | { |
f751596e |
896 | const Handle(SelectMgr_EntityOwner)& anOwner = myDetectedIter.Key(); |
897 | const Handle(SelectMgr_SelectableObject)& anObject = anOwner->Selectable(); |
898 | const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = |
899 | myMapOfObjectSensitives.Find (anObject); |
900 | |
901 | return anEntitySet->GetSensitiveById (myDetectedIter.Value())->BaseSensitive(); |
4269bd1b |
902 | } |
903 | |
904 | //======================================================================= |
f751596e |
905 | // function : ActiveOwners |
906 | // purpose : Returns the list of active entity owners |
4269bd1b |
907 | //======================================================================= |
751955d4 |
908 | void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectBasics_EntityOwner)>& theOwners) const |
4269bd1b |
909 | { |
f751596e |
910 | for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next()) |
911 | { |
912 | const NCollection_Handle<SelectMgr_SensitiveEntitySet>& anEntitySet = anIter.Value(); |
913 | Standard_Integer anEntitiesNb = anEntitySet->Size(); |
914 | for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx) |
915 | { |
916 | if (anEntitySet->GetSensitiveById (anIdx)->IsActiveForSelection()) |
917 | { |
751955d4 |
918 | theOwners.Append (anEntitySet->GetSensitiveById (anIdx)->BaseSensitive()->OwnerId()); |
f751596e |
919 | } |
920 | } |
921 | } |
4269bd1b |
922 | } |
29a4908e |
923 | |
924 | //======================================================================= |
925 | //function : AllowOverlapDetection |
926 | //purpose : Sets the detection type: if theIsToAllow is false, |
927 | // only fully included sensitives will be detected, otherwise |
928 | // the algorithm will mark both included and overlapped entities |
929 | // as matched |
930 | //======================================================================= |
931 | void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow) |
932 | { |
933 | mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow); |
934 | } |