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