913a4c4a |
1 | // Created on: 2011-10-14 |
2 | // Created by: Roman KOZLOV |
3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <IVtk_Types.hxx> |
17 | #include <IVtkOCC_ShapePickerAlgo.hxx> |
18 | #include <IVtkOCC_Shape.hxx> |
19 | #include <IVtkOCC_SelectableObject.hxx> |
20 | #include <Message.hxx> |
21 | #include <Message_Messenger.hxx> |
22 | #include <StdSelect_BRepOwner.hxx> |
23 | |
92efcf78 |
24 | IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapePickerAlgo,IVtk_IShapePickerAlgo) |
25 | |
913a4c4a |
26 | // Handle implementation |
ec357c5c |
27 | |
913a4c4a |
28 | |
29 | //================================================================ |
30 | // Function : Constructor |
31 | // Purpose : |
32 | //================================================================ |
33 | IVtkOCC_ShapePickerAlgo::IVtkOCC_ShapePickerAlgo() : |
34 | myViewerSelector (new IVtkOCC_ViewerSelector()) |
35 | { } |
36 | |
37 | //================================================================ |
38 | // Function : Destructor |
39 | // Purpose : |
40 | //================================================================ |
41 | IVtkOCC_ShapePickerAlgo::~IVtkOCC_ShapePickerAlgo() |
42 | { } |
43 | |
44 | //================================================================ |
45 | // Function : SetView |
46 | // Purpose : |
47 | //================================================================ |
48 | void IVtkOCC_ShapePickerAlgo::SetView (const IVtk_IView::Handle& theView) |
49 | { |
50 | myView = theView; |
913a4c4a |
51 | } |
52 | |
53 | //================================================================ |
54 | // Function : GetSelectionModes |
55 | // Purpose : |
56 | //================================================================ |
57 | IVtk_SelectionModeList IVtkOCC_ShapePickerAlgo::GetSelectionModes ( |
58 | const IVtk_IShape::Handle& theShape) const |
59 | { |
60 | IVtk_SelectionModeList aRes; |
61 | |
c04c30b3 |
62 | if (! theShape.IsNull()) |
913a4c4a |
63 | { |
64 | // Get shape implementation from shape interface. |
65 | Handle(IVtkOCC_Shape) aShapeImpl = Handle(IVtkOCC_Shape)::DownCast(theShape); |
66 | |
67 | // Get selectable object from the shape implementation. |
68 | Handle(IVtkOCC_SelectableObject) aSelObj = |
69 | Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject()); |
70 | |
71 | if (!aSelObj.IsNull()) |
72 | { |
73 | IVtk_SelectionMode aSelMode; |
74 | for (aSelMode = SM_Shape; aSelMode <= SM_Compound; aSelMode = (IVtk_SelectionMode)(aSelMode + 1)) |
75 | { |
76 | if (myViewerSelector->IsActive (aSelObj, aSelMode)) |
77 | { |
78 | aRes.Append (aSelMode); |
79 | } |
80 | } |
81 | } |
82 | } |
83 | |
84 | return aRes; |
85 | } |
86 | |
87 | //================================================================ |
88 | // Function : SetSelectionMode |
89 | // Purpose : |
90 | //================================================================ |
91 | void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_IShape::Handle& theShape, |
92 | const IVtk_SelectionMode theMode, |
93 | const bool theIsTurnOn) |
94 | { |
c04c30b3 |
95 | if (theShape.IsNull()) |
913a4c4a |
96 | { |
97 | return; |
98 | } |
99 | |
100 | // TODO: treatment for mode == -1 - deactivate the shape... |
101 | // Is this really needed? The picker and all selection classes |
102 | // are destroyed when shapes are deactivated... |
103 | |
104 | // Get shape implementation from shape interface. |
105 | Handle(IVtkOCC_Shape) aShapeImpl = |
106 | Handle(IVtkOCC_Shape)::DownCast(theShape); |
107 | |
108 | // Get selectable object from the shape implementation. |
109 | Handle(IVtkOCC_SelectableObject) aSelObj = |
110 | Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject()); |
111 | |
112 | if (theIsTurnOn) |
113 | { |
114 | // If there is no selectable object then create a new one for this shape. |
115 | if (aSelObj.IsNull()) |
116 | { |
117 | aSelObj = new IVtkOCC_SelectableObject (aShapeImpl); |
118 | } |
119 | |
120 | // If the selectable object has no selection in the given mode |
121 | if (!aSelObj->HasSelection (theMode)) |
122 | { |
123 | // then create a new selection in the given mode for this object (shape). |
124 | Handle(SelectMgr_Selection) aNewSelection = new SelectMgr_Selection (theMode); |
125 | aSelObj->AddSelection (aNewSelection, theMode); |
f751596e |
126 | myViewerSelector->AddSelectionToObject (aSelObj, aNewSelection); |
913a4c4a |
127 | } |
128 | |
129 | // Update the selection for the given mode according to its status. |
130 | const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode); |
913a4c4a |
131 | switch (aSel->UpdateStatus()) |
132 | { |
133 | case SelectMgr_TOU_Full: |
9df04979 |
134 | { |
913a4c4a |
135 | // Recompute the sensitive primitives which correspond to the mode. |
f751596e |
136 | myViewerSelector->RemoveSelectionOfObject (aSelObj, aSelObj->Selection (theMode)); |
137 | aSelObj->RecomputePrimitives (theMode); |
138 | myViewerSelector->AddSelectionToObject (aSelObj, aSelObj->Selection (theMode)); |
139 | myViewerSelector->RebuildObjectsTree(); |
140 | myViewerSelector->RebuildSensitivesTree (aSelObj); |
9df04979 |
141 | } |
142 | Standard_FALLTHROUGH |
913a4c4a |
143 | case SelectMgr_TOU_Partial: |
9df04979 |
144 | { |
145 | if (aSelObj->HasTransformation()) |
913a4c4a |
146 | { |
9df04979 |
147 | myViewerSelector->RebuildObjectsTree(); |
913a4c4a |
148 | } |
9df04979 |
149 | break; |
150 | } |
913a4c4a |
151 | default: |
152 | break; |
153 | } |
154 | // Set status of the selection to "nothing to update". |
155 | aSel->UpdateStatus (SelectMgr_TOU_None); |
156 | |
157 | // Activate the selection in the viewer selector. |
158 | myViewerSelector->Activate (aSelObj->Selection (theMode)); |
159 | |
160 | } |
161 | else |
162 | { // turn off the selection mode |
163 | |
164 | if (!aSelObj.IsNull()) |
165 | { |
166 | if (aSelObj->HasSelection (theMode)) |
167 | { |
168 | const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode); |
169 | myViewerSelector->Deactivate (aSel); |
170 | } |
171 | } |
172 | } |
173 | } |
174 | |
175 | //================================================================ |
176 | // Function : SetSelectionMode |
177 | // Purpose : |
178 | //================================================================ |
179 | void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_ShapePtrList& theShapes, |
180 | const IVtk_SelectionMode theMode, |
181 | const bool /*theIsTurnOn*/) |
182 | { |
183 | IVtk_IShape::Handle aShape; |
184 | IVtk_ShapePtrList::Iterator anIt (theShapes); |
185 | for (; anIt.More(); anIt.Next()) |
186 | { |
187 | aShape = anIt.Value(); |
188 | SetSelectionMode (aShape, theMode); |
189 | } |
190 | } |
191 | |
192 | //================================================================ |
193 | // Function : Pick |
194 | // Purpose : |
195 | //================================================================ |
196 | bool IVtkOCC_ShapePickerAlgo::Pick (const double theX, const double theY) |
197 | { |
198 | clearPicked(); |
199 | |
200 | // Calling OCCT algortihm |
201 | myViewerSelector->Pick ((Standard_Integer)theX, |
202 | (Standard_Integer)theY, |
203 | myView); |
204 | |
205 | // Fill the results |
206 | return processPicked(); |
207 | } |
208 | |
209 | //================================================================ |
210 | // Function : Pick |
211 | // Purpose : |
212 | //================================================================ |
213 | bool IVtkOCC_ShapePickerAlgo::Pick (const double theXMin, |
214 | const double theYMin, |
215 | const double theXMax, |
216 | const double theYMax) |
217 | { |
218 | clearPicked(); |
219 | |
220 | // Calling OCCT algortihm |
221 | myViewerSelector->Pick ((Standard_Integer)theXMin, |
222 | (Standard_Integer)theYMin, |
223 | (Standard_Integer)theXMax, |
224 | (Standard_Integer)theYMax, |
225 | myView); |
226 | |
227 | // Fill the results |
228 | return processPicked(); |
229 | } |
230 | |
231 | //================================================================ |
232 | // Function : Pick |
233 | // Purpose : |
234 | //================================================================ |
235 | bool IVtkOCC_ShapePickerAlgo::Pick (double** thePoly, |
236 | const int theNbPoints) |
237 | { |
238 | clearPicked(); |
239 | |
240 | // Calling OCCT algortihm |
241 | myViewerSelector->Pick (thePoly, theNbPoints, myView); |
242 | |
243 | // Fill the results |
244 | return processPicked(); |
245 | } |
246 | |
247 | //================================================================ |
248 | // Function : ShapesPicked |
249 | // Purpose : |
250 | //================================================================ |
251 | const IVtk_ShapeIdList& IVtkOCC_ShapePickerAlgo::ShapesPicked() const |
252 | { |
253 | return myShapesPicked; |
254 | } |
255 | |
256 | //================================================================ |
257 | // Function : SubShapesPicked |
258 | // Purpose : |
259 | //================================================================ |
260 | void IVtkOCC_ShapePickerAlgo::SubShapesPicked (const IVtk_IdType theId, IVtk_ShapeIdList& theShapeList) const |
261 | { |
262 | if (mySubShapesPicked.IsBound (theId)) |
263 | { |
a2f76b15 |
264 | theShapeList = mySubShapesPicked (theId); |
913a4c4a |
265 | } |
266 | } |
267 | |
268 | //================================================================ |
269 | // Function : clearPicked |
270 | // Purpose : Internal method, resets picked data |
271 | //================================================================ |
272 | void IVtkOCC_ShapePickerAlgo::clearPicked() |
273 | { |
1e756cb9 |
274 | myTopPickedPoint.SetCoord (RealLast(), RealLast(), RealLast()); |
913a4c4a |
275 | myShapesPicked.Clear(); |
276 | mySubShapesPicked.Clear(); |
277 | } |
278 | |
279 | //================================================================ |
280 | // Function : NbPicked |
281 | // Purpose : Get number of picked entities. |
282 | //================================================================ |
283 | int IVtkOCC_ShapePickerAlgo::NbPicked() |
284 | { |
285 | return myShapesPicked.Extent(); |
286 | } |
287 | |
288 | //================================================================ |
289 | // Function : processPicked |
290 | // Purpose : |
291 | //================================================================ |
292 | bool IVtkOCC_ShapePickerAlgo::processPicked() |
293 | { |
294 | Standard_Integer aNbPicked = myViewerSelector->NbPicked(); |
1e756cb9 |
295 | |
913a4c4a |
296 | Handle(StdSelect_BRepOwner) anEntityOwner; |
297 | Handle(Message_Messenger) anOutput = Message::DefaultMessenger(); |
298 | |
1e756cb9 |
299 | bool isTop = true; |
913a4c4a |
300 | for (Standard_Integer aDetectIt = 1; aDetectIt <= aNbPicked; aDetectIt++) |
301 | { |
302 | // ViewerSelector detects sensitive entities under the mouse |
303 | // and for each entity returns its entity owner. |
304 | // StdSelect_BRepOwner instance holds corresponding sub-shape (TopoDS_Shape) |
305 | // and in general entity owners have a pointer to SelectableObject that can tell us |
306 | // what is the top-level TopoDS_Shape. |
307 | anEntityOwner = Handle(StdSelect_BRepOwner)::DownCast (myViewerSelector->Picked (aDetectIt)); |
308 | if (!anEntityOwner.IsNull()) |
309 | { |
310 | Handle(IVtkOCC_SelectableObject) aSelectable = |
311 | Handle(IVtkOCC_SelectableObject)::DownCast (anEntityOwner->Selectable()); |
312 | |
c04c30b3 |
313 | if (aSelectable.IsNull()) |
913a4c4a |
314 | { |
0ebe5b0a |
315 | anOutput->SendAlarm() << "Error: EntityOwner having null SelectableObject picked!"; |
913a4c4a |
316 | continue; |
317 | } |
318 | |
319 | Handle(IVtkOCC_Shape) aSelShape = aSelectable->GetShape(); |
c04c30b3 |
320 | if (aSelShape.IsNull()) |
913a4c4a |
321 | { |
0ebe5b0a |
322 | anOutput->SendAlarm() << "Error: SelectableObject with null OccShape pointer picked!"; |
913a4c4a |
323 | continue; |
324 | } |
325 | |
326 | IVtk_IdType aTopLevelId = aSelShape->GetId(); |
327 | myShapesPicked.Append (aTopLevelId); |
1e756cb9 |
328 | if (isTop) |
329 | { |
330 | isTop = false; |
331 | myTopPickedPoint = myViewerSelector->PickedPoint (aDetectIt); |
332 | } |
913a4c4a |
333 | |
334 | // Now try to guess if it's the top-level shape itself or just a sub-shape picked |
335 | TopoDS_Shape aTopLevelShape = aSelShape->GetShape(); |
336 | TopoDS_Shape aSubShape = anEntityOwner->Shape(); |
337 | if (aTopLevelShape.IsNull()) |
338 | { |
0ebe5b0a |
339 | anOutput->SendAlarm() << "Error: OccShape with null top-level TopoDS_Shape picked!"; |
913a4c4a |
340 | continue; |
341 | } |
342 | if (aSubShape.IsNull()) |
343 | { |
0ebe5b0a |
344 | anOutput->SendAlarm() << "Error: EntityOwner with null TopoDS_Shape picked!"; |
913a4c4a |
345 | continue; |
346 | } |
347 | |
348 | if (!aSubShape.IsSame (aTopLevelShape)) |
349 | { |
350 | IVtk_IdType aSubId = aSelShape->GetSubShapeId (aSubShape); |
351 | |
352 | if (!mySubShapesPicked.IsBound (aTopLevelId)) |
353 | { |
354 | const IVtk_ShapeIdList aList; |
355 | mySubShapesPicked.Bind (aTopLevelId, aList); |
356 | } |
357 | // Order of selected sub-shapes |
358 | mySubShapesPicked (aTopLevelId).Append (aSubId); |
359 | } |
360 | } |
361 | } |
362 | |
363 | return !myShapesPicked.IsEmpty(); |
364 | } |
a2f76b15 |
365 | |
366 | //============================================================================ |
367 | // Method: RemoveSelectableActor |
368 | // Purpose: Remove selectable object from the picker (from internal maps). |
369 | //============================================================================ |
370 | void IVtkOCC_ShapePickerAlgo::RemoveSelectableObject(const IVtk_IShape::Handle& theShape) |
371 | { |
372 | clearPicked(); |
373 | // Get shape implementation from shape interface. |
374 | Handle(IVtkOCC_Shape) aShapeImpl = |
375 | Handle(IVtkOCC_Shape)::DownCast(theShape); |
376 | |
377 | // Get selectable object from the shape implementation. |
378 | Handle(IVtkOCC_SelectableObject) aSelObj = |
379 | Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject()); |
380 | |
381 | myViewerSelector->RemoveSelectableObject(aSelObj); |
382 | myViewerSelector->Clear(); |
383 | aShapeImpl->SetSelectableObject(NULL); |
384 | } |