Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2007-07-06 |
2 | // Created by: Alexander GRIGORIEV | |
973c2be1 | 3 | // Copyright (c) 2007-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
16 | #include <NIS_View.hxx> | |
17 | #include <NIS_InteractiveContext.hxx> | |
18 | #include <NIS_InteractiveObject.hxx> | |
19 | #include <gp_Ax1.hxx> | |
20 | #include <Visual3d_View.hxx> | |
ffe2bea7 A |
21 | #include <Bnd_B2f.hxx> |
22 | #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx> | |
cfd5fa01 | 23 | |
24 | #include <OpenGl_GlCore11.hxx> | |
7fd59977 | 25 | |
b5ac8292 | 26 | IMPLEMENT_STANDARD_HANDLE (NIS_View, V3d_View) |
27 | IMPLEMENT_STANDARD_RTTIEXT (NIS_View, V3d_View) | |
7fd59977 | 28 | |
29 | //======================================================================= | |
30 | //function : NIS_View() | |
31 | //purpose : Constructor | |
32 | //======================================================================= | |
33 | ||
34 | NIS_View::NIS_View (const Handle(V3d_Viewer)& theViewer, | |
35 | const Handle(Aspect_Window)& theWindow) | |
b5ac8292 | 36 | : V3d_View (theViewer), |
ffe2bea7 A |
37 | myIsTopHilight(Standard_False), |
38 | myDoHilightSelected(Standard_True) | |
7fd59977 | 39 | { |
ffe2bea7 A |
40 | if (!theWindow.IsNull()) |
41 | V3d_View::SetWindow (theWindow, NULL, &MyCallback, this); | |
7fd59977 | 42 | } |
43 | ||
44 | //======================================================================= | |
45 | //function : SetWindow | |
cfd5fa01 | 46 | //purpose : |
7fd59977 | 47 | //======================================================================= |
48 | ||
49 | void NIS_View::SetWindow(const Handle(Aspect_Window) &theWindow) | |
50 | { | |
ffe2bea7 | 51 | V3d_View::SetWindow (theWindow, NULL, &MyCallback, this); |
7fd59977 | 52 | } |
53 | ||
54 | // //======================================================================= | |
55 | // //function : ~NIS_View | |
56 | // //purpose : Destructor | |
57 | // //======================================================================= | |
58 | ||
59 | // NIS_View::~NIS_View() | |
60 | // {} | |
61 | ||
62 | ||
63 | //======================================================================= | |
64 | //function : AddContext | |
cfd5fa01 | 65 | //purpose : |
7fd59977 | 66 | //======================================================================= |
67 | ||
68 | void NIS_View::AddContext (NIS_InteractiveContext * theCtx) | |
69 | { | |
70 | // Check that the given context is not among already attached contexts | |
71 | NCollection_List<NIS_InteractiveContext *>::Iterator anIter (myContexts); | |
72 | for (; anIter.More(); anIter.Next()) | |
73 | if (anIter.Value() == theCtx) | |
74 | break; | |
75 | if (anIter.More() == Standard_False) | |
76 | myContexts.Append (theCtx); | |
77 | } | |
78 | ||
79 | //======================================================================= | |
80 | //function : RemoveContext | |
cfd5fa01 | 81 | //purpose : |
7fd59977 | 82 | //======================================================================= |
83 | ||
84 | void NIS_View::RemoveContext (NIS_InteractiveContext * theCtx) | |
85 | { | |
86 | NCollection_List<NIS_InteractiveContext *>::Iterator anIter (myContexts); | |
87 | for (; anIter.More(); anIter.Next()) | |
88 | if (anIter.Value() == theCtx) { | |
89 | myContexts.Remove (anIter); | |
90 | break; | |
91 | } | |
ffe2bea7 | 92 | |
857ffd5e | 93 | NCollection_Map<Handle(NIS_Drawer)>::Iterator anIterD (theCtx->GetDrawers ()); |
ffe2bea7 A |
94 | for (; anIterD.More(); anIterD.Next()) { |
95 | const Handle(NIS_Drawer)& aDrawer = anIterD.Value(); | |
96 | if (aDrawer.IsNull() == Standard_False) { | |
97 | aDrawer->UpdateExListId(this); | |
98 | } | |
99 | } | |
7fd59977 | 100 | } |
101 | ||
102 | //======================================================================= | |
103 | //function : FitAll3d | |
cfd5fa01 | 104 | //purpose : |
7fd59977 | 105 | //======================================================================= |
106 | ||
ffe2bea7 A |
107 | Standard_Boolean NIS_View::FitAll3d (const Quantity_Coefficient theCoef) |
108 | { | |
ed063270 | 109 | Bnd_B3f aB3fBox = GetBndBox(); |
ffe2bea7 | 110 | |
ed063270 | 111 | if (aB3fBox.IsVoid() || MyView->IsDefined() == Standard_False) |
b5ac8292 | 112 | { |
197ac94e | 113 | return Standard_False; |
114 | } | |
ffe2bea7 | 115 | |
ed063270 | 116 | Bnd_Box aBox; |
117 | aBox.Add (gp_Pnt (aB3fBox.CornerMin())); | |
118 | aBox.Add (gp_Pnt (aB3fBox.CornerMax())); | |
197ac94e | 119 | |
ed063270 | 120 | if (!FitMinMax (myCamera, aBox, theCoef, 0.0, Standard_False)) |
197ac94e | 121 | { |
122 | return Standard_False; | |
ffe2bea7 A |
123 | } |
124 | ||
6bc6a6fc | 125 | View()->AutoZFit(); |
197ac94e | 126 | |
127 | ImmediateUpdate(); | |
128 | ||
129 | return Standard_True; | |
ffe2bea7 A |
130 | } |
131 | ||
132 | //======================================================================= | |
133 | //function : GetBndBox | |
cfd5fa01 | 134 | //purpose : |
ffe2bea7 A |
135 | //======================================================================= |
136 | ||
137 | Bnd_B3f NIS_View::GetBndBox() const | |
7fd59977 | 138 | { |
139 | // Calculate the 3D bounding box of visible objects | |
140 | // in all interactive contexts | |
141 | Bnd_B3f aBox; | |
142 | NCollection_List<NIS_InteractiveContext *>::Iterator anIterC (myContexts); | |
143 | for (; anIterC.More(); anIterC.Next()) { | |
857ffd5e | 144 | NCollection_Map<Handle(NIS_Drawer)>::Iterator anIterD |
7fd59977 | 145 | (anIterC.Value()->myDrawers); |
146 | for (; anIterD.More(); anIterD.Next()) { | |
147 | const Handle(NIS_Drawer)& aDrawer = anIterD.Value(); | |
148 | Bnd_B3f aBoxD = aDrawer->GetBox (this); | |
149 | aBox.Add (aBoxD); | |
150 | } | |
151 | } | |
152 | ||
7fd59977 | 153 | // Take the bounding box of AIS objects displayed in the view |
ed063270 | 154 | Bnd_Box aVal = View()->MinMaxValues(); |
155 | if (!aVal.IsVoid()) | |
156 | { | |
157 | aBox.Add (aVal.CornerMin()); | |
158 | aBox.Add (aVal.CornerMax()); | |
7fd59977 | 159 | } |
160 | ||
ffe2bea7 A |
161 | return aBox; |
162 | } | |
163 | ||
164 | //======================================================================= | |
165 | //function : GetBndBox | |
cfd5fa01 | 166 | //purpose : |
ffe2bea7 A |
167 | //======================================================================= |
168 | ||
cfd5fa01 | 169 | void NIS_View::GetBndBox( Standard_Integer& theXMin, Standard_Integer& theXMax, |
ffe2bea7 A |
170 | Standard_Integer& theYMin, Standard_Integer& theYMax ) const |
171 | { | |
cfd5fa01 | 172 | theXMin = theYMin = 0; |
ffe2bea7 A |
173 | theXMax = theYMax = -1; |
174 | ||
175 | Bnd_B3f aBox = GetBndBox(); | |
176 | ||
7fd59977 | 177 | // Check that the box is not empty |
178 | if (aBox.IsVoid() == Standard_False) { | |
179 | // Convert the 3D box to 2D representation in pixel coordinates | |
180 | gp_XYZ aCoord; | |
181 | Standard_Integer anXp, anYp; | |
182 | const gp_XYZ aCorner[2] = { aBox.CornerMin(), aBox.CornerMax() }; | |
183 | Standard_Integer aLimp[4] = { 1000000, -1000000, 1000000, -1000000 }; | |
184 | for (Standard_Integer i = 0; i < 8; i++) { | |
185 | if (i & 0x1) aCoord.SetX (aCorner[0].X()); | |
186 | else aCoord.SetX (aCorner[1].X()); | |
187 | if (i & 0x2) aCoord.SetY (aCorner[0].Y()); | |
188 | else aCoord.SetY (aCorner[1].Y()); | |
189 | if (i & 0x4) aCoord.SetZ (aCorner[0].Z()); | |
190 | else aCoord.SetZ (aCorner[1].Z()); | |
191 | Convert( aCoord.X(), aCoord.Y(), aCoord.Z(), anXp, anYp ); | |
192 | if (aLimp[0] > anXp) aLimp[0] = anXp; | |
193 | if (aLimp[1] < anXp) aLimp[1] = anXp; | |
194 | if (aLimp[2] > anYp) aLimp[2] = anYp; | |
195 | if (aLimp[3] < anYp) aLimp[3] = anYp; | |
196 | } | |
197 | if (aLimp[0] < aLimp[1] && aLimp[2] < aLimp[3]) | |
198 | { | |
199 | // Scale the view | |
cfd5fa01 | 200 | // WindowFit (aLimp[0], aLimp[2], aLimp[1], aLimp[3]); |
ffe2bea7 A |
201 | theXMin = aLimp[0]; |
202 | theXMax = aLimp[1]; | |
203 | theYMin = aLimp[2]; | |
204 | theYMax = aLimp[3]; | |
cfd5fa01 | 205 | } |
7fd59977 | 206 | } |
207 | } | |
208 | ||
209 | ||
210 | //======================================================================= | |
211 | //function : MyCallback | |
cfd5fa01 | 212 | //purpose : |
7fd59977 | 213 | //======================================================================= |
214 | ||
215 | int NIS_View::MyCallback (Aspect_Drawable /* Window ID */, | |
cfd5fa01 | 216 | void* ptrData, |
b299a91c | 217 | Aspect_GraphicCallbackStruct* callData /* call data */) |
7fd59977 | 218 | { |
b299a91c A |
219 | // Avoid multiple rendering of the scene ( accordingly with update of |
220 | // callback mechanism, that invokes additional callbacks before | |
221 | // underlay and overlay redrawing with OCC_PRE_REDRAW and OCC_PRE_OVERLAY | |
222 | // bits added to the "reason" value of the callback data structure; | |
223 | // see comments to OCC_REDRAW_ADDITIONAL_CALLBACKS definition ) | |
224 | if (callData->reason & OCC_REDRAW_ADDITIONAL_CALLBACKS) | |
225 | return 0; | |
cfd5fa01 | 226 | |
7fd59977 | 227 | const Handle(NIS_View) thisView (static_cast<NIS_View *> (ptrData)); |
228 | NCollection_List<NIS_InteractiveContext *>::Iterator anIter; | |
229 | #ifdef CLIP | |
230 | // Find the bounding box of all displayed objects by summing the boxes stored | |
231 | // in the relevant DrawList instances. | |
232 | Bnd_B3f aBndBox; | |
233 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) | |
234 | anIter.Value()->GetBox (aBndBox, pView); | |
235 | ||
236 | if (aBndBox.IsVoid() == Standard_False) { | |
237 | const gp_XYZ aBoxSize = 0.5 * (aBndBox.CornerMax() - aBndBox.CornerMin()); | |
238 | const gp_XYZ aBoxCenter = 0.5 * (aBndBox.CornerMax() + aBndBox.CornerMin()); | |
239 | ||
240 | // Find the ray passing through the clicked point in the view window. | |
241 | Standard_Real anX, anY, aZ; | |
242 | thisView->Convert(0, 0, anX, anY, aZ); // 3D point for the 3D coordinates | |
243 | const gp_Pnt anEye (anX, anY, aZ); | |
244 | thisView->Proj (anX, anY, aZ); // vector orthogonal to the view plane | |
245 | const gp_Dir aProj (anX, anY, aZ); | |
246 | const gp_Ax1 anAxis (anEye, aProj); | |
247 | ||
248 | const Standard_Real aCenterDist = (anEye.XYZ() - aBoxCenter) * aProj.XYZ(); | |
249 | const Standard_Real aBoxExtent /*(fabs(aBoxSize.X() * anX) + | |
250 | fabs(aBoxSize.Y() * anY) + | |
251 | fabs(aBoxSize.Z() * aZ))*/(100.); | |
252 | ||
253 | #define FRONT_CLIPPING_PLANE (GL_CLIP_PLANE0 + 0) | |
254 | #define BACK_CLIPPING_PLANE (GL_CLIP_PLANE0 + 1) | |
255 | Standard_Real arr[4] = { | |
256 | 0.0, /* Nx */ | |
257 | 0.0, /* Ny */ | |
258 | 1.0, /* Nz */ | |
259 | 0. | |
260 | }; | |
261 | arr[3] = aBoxExtent + 1.; | |
262 | glClipPlane (BACK_CLIPPING_PLANE, arr); | |
263 | glEnable (BACK_CLIPPING_PLANE); | |
264 | arr[2] = -1.0; | |
265 | arr[3] = aBoxExtent + 1.; | |
266 | glClipPlane (FRONT_CLIPPING_PLANE, arr); | |
267 | glEnable (FRONT_CLIPPING_PLANE); | |
268 | } | |
269 | #endif //IS_DISABLED | |
270 | ||
7fd59977 | 271 | GLboolean isDepthWriteMask, isDepthTest; |
272 | glGetBooleanv(GL_DEPTH_WRITEMASK,&isDepthWriteMask); | |
273 | glGetBooleanv(GL_DEPTH_TEST,&isDepthTest); | |
274 | // printf ("GlDepthMask=%d; GlDepthTest=%d\n", depthwritemask, depthtest); | |
275 | glDisableClientState(GL_COLOR_ARRAY); | |
276 | glDisableClientState(GL_EDGE_FLAG_ARRAY); | |
277 | glDisableClientState(GL_INDEX_ARRAY); | |
278 | glDisableClientState(GL_NORMAL_ARRAY); | |
279 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |
280 | if (!isDepthTest) { | |
281 | glEnable(GL_DEPTH_TEST); | |
282 | glDepthFunc(GL_LESS); | |
283 | glClearDepth(1.); | |
284 | glClear(GL_DEPTH_BUFFER_BIT); | |
285 | } | |
286 | ||
ffe2bea7 A |
287 | TColStd_MapIteratorOfPackedMapOfInteger anIterM(thisView->myExListId); |
288 | for (; anIterM.More(); anIterM.Next()) | |
289 | if (anIterM.Key() != 0) { | |
290 | #ifdef ARRAY_LISTS | |
291 | glDeleteLists (anIterM.Key(), 5); | |
292 | #else | |
293 | glDeleteLists (anIterM.Key(), 1); | |
294 | } | |
295 | #endif | |
296 | thisView->myExListId.Clear(); | |
297 | ||
7fd59977 | 298 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) |
299 | anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Normal); | |
ffe2bea7 A |
300 | |
301 | // #818151 - selected object is hidden by covered unselected one | |
302 | // display hilighted objects always above the rest ones | |
303 | if (thisView->myIsTopHilight == Standard_True) { | |
304 | glDepthFunc(GL_ALWAYS); | |
305 | } | |
306 | ||
7fd59977 | 307 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) |
308 | anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Hilighted); | |
309 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) | |
310 | anIter.Value()->redraw (thisView, NIS_Drawer::Draw_DynHilighted); | |
ffe2bea7 A |
311 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) |
312 | anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Transparent); | |
313 | ||
314 | // draw top objects always above | |
315 | if (thisView->myIsTopHilight == Standard_False) { | |
316 | glDepthFunc(GL_ALWAYS); | |
317 | } | |
318 | ||
319 | for (anIter = thisView->myContexts; anIter.More(); anIter.Next()) | |
320 | anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Top); | |
7fd59977 | 321 | |
322 | return 0; | |
323 | } | |
324 | ||
325 | //======================================================================= | |
326 | //function : DynamicHilight | |
cfd5fa01 | 327 | //purpose : |
7fd59977 | 328 | //======================================================================= |
329 | ||
330 | void NIS_View::DynamicHilight (const Standard_Integer theX, | |
331 | const Standard_Integer theY) | |
332 | { | |
ffe2bea7 | 333 | myDetected.Clear(); |
7fd59977 | 334 | const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY); |
335 | ||
cfd5fa01 | 336 | // ASV: if at least one Context returns IsSelectable()==False, |
7fd59977 | 337 | // hilight is canceled, this method returns |
338 | if (aSelected.IsNull() == Standard_False) { | |
339 | if (aSelected->IsSelectable() == Standard_False) | |
340 | return; | |
341 | } | |
342 | if (aSelected != myDynHilighted) { | |
343 | const Handle(NIS_View) aView (this); | |
344 | if (myDynHilighted.IsNull() == Standard_False) | |
ffe2bea7 A |
345 | if (myDynHilighted->GetDrawer().IsNull() == Standard_False) |
346 | myDynHilighted->GetDrawer()->SetDynamicHilighted(Standard_False, | |
347 | myDynHilighted, aView); | |
348 | ||
349 | // 30.07.10 - NKV - synchronize behaviour with AIS interactive context (if need) | |
350 | if (aSelected.IsNull() || | |
cfd5fa01 | 351 | (myDoHilightSelected == Standard_False && |
ffe2bea7 A |
352 | aSelected->GetDrawer()->GetContext()->IsSelected(aSelected))) |
353 | { | |
7fd59977 | 354 | myDynHilighted.Nullify(); |
ffe2bea7 | 355 | } |
7fd59977 | 356 | else { |
357 | aSelected->GetDrawer()->SetDynamicHilighted (Standard_True, | |
358 | aSelected, aView); | |
359 | myDynHilighted = aSelected; | |
360 | } | |
361 | Redraw(); | |
362 | } | |
363 | } | |
364 | ||
365 | //======================================================================= | |
366 | //function : DynamicUnhilight | |
cfd5fa01 | 367 | //purpose : |
7fd59977 | 368 | //======================================================================= |
369 | ||
857ffd5e | 370 | void NIS_View::DynamicUnhilight(const Handle(NIS_InteractiveObject)& theObj) |
7fd59977 | 371 | { |
372 | if (theObj == myDynHilighted && theObj.IsNull() == Standard_False) { | |
373 | const Handle(NIS_View) aView (this); | |
ffe2bea7 A |
374 | if (myDynHilighted->GetDrawer().IsNull() == Standard_False) |
375 | myDynHilighted->GetDrawer()->SetDynamicHilighted (Standard_False, | |
376 | myDynHilighted, aView); | |
7fd59977 | 377 | myDynHilighted.Nullify(); |
378 | Redraw(); | |
379 | } | |
380 | } | |
381 | ||
382 | //======================================================================= | |
383 | //function : Select | |
384 | //purpose : selection by single click | |
385 | //======================================================================= | |
386 | ||
387 | void NIS_View::Select (const Standard_Integer theX, | |
388 | const Standard_Integer theY, | |
ffe2bea7 A |
389 | const Standard_Boolean isForceMultiple, |
390 | const Standard_Boolean theRedraw) | |
7fd59977 | 391 | { |
ffe2bea7 | 392 | myDetected.Clear(); |
7fd59977 | 393 | const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY); |
394 | NCollection_List<NIS_InteractiveContext *>::Iterator anIter (myContexts); | |
395 | for (; anIter.More(); anIter.Next()) | |
396 | anIter.Value()->ProcessSelection (aSelected, isForceMultiple); | |
397 | if (aSelected == myDynHilighted && aSelected.IsNull() == Standard_False) | |
398 | { | |
399 | myDynHilighted.Nullify(); | |
400 | const Handle(NIS_Drawer)& aDrawer = aSelected->GetDrawer(); | |
401 | aDrawer->SetDynamicHilighted (Standard_False, aSelected, this); | |
402 | } | |
ffe2bea7 | 403 | if (theRedraw) Redraw(); |
7fd59977 | 404 | } |
405 | ||
406 | //======================================================================= | |
407 | //function : Select | |
408 | //purpose : selection by rectange | |
409 | //======================================================================= | |
410 | ||
411 | void NIS_View::Select (const Standard_Integer theXmin, | |
412 | const Standard_Integer theYmin, | |
413 | const Standard_Integer theXmax, | |
414 | const Standard_Integer theYmax, | |
415 | const Standard_Boolean isForceMult, | |
ffe2bea7 A |
416 | const Standard_Boolean isFullyIncluded, |
417 | const Standard_Boolean theRedraw) | |
7fd59977 | 418 | { |
ffe2bea7 | 419 | myDetected.Clear(); |
7fd59977 | 420 | Standard_Real anX, anY, aZ; |
421 | if (theXmin == theXmax || theYmin == theYmax) | |
422 | return; | |
423 | ||
424 | //Transformed box corresponding to the selected rectangle | |
425 | Proj (anX, anY, aZ); // vector orthogonal to the view plane | |
426 | const gp_Dir aProj (anX, anY, aZ); | |
427 | ||
428 | Convert(theXmin, theYmin, anX, anY, aZ); // 3D point for the 3D coordinates | |
429 | const gp_Pnt anEye (anX, anY, aZ); | |
430 | ||
431 | Convert(theXmax, theYmin, anX, anY, aZ); // 3D point for the 3D coordinates | |
432 | const gp_XYZ anXdir (gp_XYZ(anX, anY, aZ) - anEye.XYZ()); | |
433 | const gp_Ax3 anAx3 (anEye, aProj, anXdir); | |
434 | gp_Trsf aTrf; | |
435 | aTrf.SetTransformation (anAx3); | |
436 | const gp_Trsf aTrfInv = aTrf.Inverted(); | |
437 | ||
438 | Convert(theXmax, theYmax, anX, anY, aZ); // 3D point for the 3D coordinates | |
439 | gp_XYZ anUpperCorner (anX, anY, aZ); | |
440 | aTrf.Transforms(anUpperCorner); | |
441 | ||
442 | // Selecting box | |
443 | Bnd_B3f aBoxSel; | |
444 | aBoxSel.Add (gp_XYZ(0., 0., -10000.)); | |
445 | aBoxSel.Add (anUpperCorner); | |
446 | ||
447 | TColStd_PackedMapOfInteger mapSelected; | |
448 | NCollection_List<NIS_InteractiveContext *>::Iterator anIterC (myContexts); | |
449 | for (; anIterC.More(); anIterC.Next()) { | |
450 | NIS_InteractiveContext * pCtx = anIterC.Value(); | |
451 | mapSelected.Clear(); | |
452 | pCtx->selectObjects (mapSelected, aBoxSel, aTrfInv, aTrf, isFullyIncluded); | |
453 | pCtx->ProcessSelection (mapSelected, isForceMult); | |
454 | } | |
ffe2bea7 | 455 | if (theRedraw) Redraw(); |
7fd59977 | 456 | } |
457 | ||
ffe2bea7 A |
458 | //======================================================================= |
459 | //function : Select | |
460 | //purpose : Selection by polygon | |
461 | //======================================================================= | |
462 | ||
463 | void NIS_View::Select (const NCollection_List<gp_XY> &thePolygon, | |
464 | const Standard_Boolean isForceMult, | |
465 | const Standard_Boolean isFullyIncluded, | |
466 | const Standard_Boolean theRedraw) | |
467 | { | |
468 | myDetected.Clear(); | |
469 | if (thePolygon.IsEmpty()) | |
470 | return; | |
471 | ||
472 | Standard_Real anX, anY, aZ; | |
473 | ||
474 | //Transformed box corresponding to the selected rectangle | |
475 | Proj (anX, anY, aZ); // vector orthogonal to the view plane | |
476 | const gp_Dir aProj (anX, anY, aZ); | |
477 | ||
478 | const gp_XY &aPf = thePolygon.First(); | |
479 | // 3D point for the 3D coordinates | |
480 | Convert((Standard_Integer) aPf.X(), (Standard_Integer) aPf.Y(), anX, anY, aZ); | |
481 | const gp_Pnt anEye (anX, anY, aZ); | |
482 | ||
483 | // 3D point for the 3D coordinates | |
484 | const gp_XY &aPl = thePolygon.Last(); | |
485 | ||
486 | Convert((Standard_Integer) aPl.X(), (Standard_Integer) aPl.Y(), anX, anY, aZ); | |
487 | ||
488 | // Compute transformation. | |
489 | const gp_XYZ anXdir (gp_XYZ(anX, anY, aZ) - anEye.XYZ()); | |
476ed21f | 490 | if (anXdir.Modulus() <= gp::Resolution()) |
491 | { | |
492 | return; | |
493 | } | |
494 | ||
ffe2bea7 A |
495 | const gp_Ax3 anAx3 (anEye, aProj, anXdir); |
496 | gp_Trsf aTrf; | |
497 | aTrf.SetTransformation (anAx3); | |
ffe2bea7 A |
498 | |
499 | // Prepare list of 2d points of selection polygon. | |
500 | NCollection_List<gp_XY> aPoints; | |
501 | NCollection_List<gp_XY>::Iterator anIter(thePolygon); | |
502 | Bnd_B2f aPolyBox; | |
503 | ||
504 | for (; anIter.More(); anIter.Next()) { | |
505 | const gp_XY &aP = anIter.Value(); | |
506 | ||
507 | Convert((Standard_Integer) aP.X(), (Standard_Integer) aP.Y(), anX, anY, aZ); | |
508 | gp_XYZ aP3d(anX, anY, aZ); | |
509 | ||
510 | aTrf.Transforms(aP3d); | |
511 | ||
512 | gp_XY aP2d(aP3d.X(), aP3d.Y()); | |
513 | ||
514 | aPoints.Append(aP2d); | |
515 | aPolyBox.Add(aP2d); | |
516 | } | |
517 | ||
518 | TColStd_PackedMapOfInteger mapSelected; | |
519 | NCollection_List<NIS_InteractiveContext *>::Iterator anIterC(myContexts); | |
520 | ||
521 | for (; anIterC.More(); anIterC.Next()) { | |
522 | NIS_InteractiveContext * pCtx = anIterC.Value(); | |
523 | mapSelected.Clear(); | |
524 | pCtx->selectObjects (mapSelected, aPoints, aPolyBox, aTrf, isFullyIncluded); | |
525 | pCtx->ProcessSelection (mapSelected, isForceMult); | |
526 | } | |
527 | ||
528 | if (theRedraw) Redraw(); | |
529 | } | |
7fd59977 | 530 | |
531 | //======================================================================= | |
532 | //function : Pick | |
cfd5fa01 | 533 | //purpose : |
7fd59977 | 534 | //======================================================================= |
535 | ||
857ffd5e | 536 | Handle(NIS_InteractiveObject) NIS_View::Pick (const Standard_Integer theX, |
ffe2bea7 | 537 | const Standard_Integer theY) |
7fd59977 | 538 | { |
539 | // Find the ray passing through the clicked point in the view window. | |
540 | Standard_Real anX, anY, aZ, anOver; | |
541 | Convert(theX, theY, anX, anY, aZ); // 3D point for the 3D coordinates | |
542 | const gp_Pnt anEye (anX, anY, aZ); | |
543 | Proj (anX, anY, aZ); // vector orthogonal to the view plane | |
544 | const gp_Dir aProj (-anX, -anY, -aZ); | |
545 | const gp_Ax1 anAxis (anEye, aProj); | |
546 | ||
547 | Convert (theX+1, theY+1, anX, anY, aZ); | |
548 | anOver = ((gp_XYZ(anX, anY, aZ) - anEye.XYZ()) ^ aProj.XYZ()).Modulus() * 1.5; | |
549 | ||
550 | return Pick(anAxis, anOver, Standard_True); | |
551 | } | |
552 | ||
553 | //======================================================================= | |
554 | //function : Pick | |
cfd5fa01 | 555 | //purpose : |
7fd59977 | 556 | //======================================================================= |
557 | ||
857ffd5e | 558 | Handle(NIS_InteractiveObject) NIS_View::Pick |
7fd59977 | 559 | (const gp_Ax1& theAxis, |
560 | const Standard_Real theOver, | |
ffe2bea7 | 561 | const Standard_Boolean isOnlySelectable) |
7fd59977 | 562 | { |
ffe2bea7 | 563 | typedef NCollection_List<NIS_InteractiveContext::DetectedEnt> LstDetected; |
7fd59977 | 564 | Standard_Real aDistance (0.1 * RealLast()); |
565 | Handle(NIS_InteractiveObject) aSelected, aTmpSel; | |
ffe2bea7 | 566 | LstDetected aDetected; |
7fd59977 | 567 | |
568 | NCollection_List<NIS_InteractiveContext *>::Iterator anIterC (myContexts); | |
569 | for (; anIterC.More(); anIterC.Next()) { | |
570 | const Standard_Real aDist = | |
ffe2bea7 | 571 | anIterC.Value()->selectObject (aTmpSel, aDetected, theAxis, theOver, |
7fd59977 | 572 | isOnlySelectable); |
573 | if (aDist < aDistance) { | |
574 | aDistance = aDist; | |
575 | aSelected = aTmpSel; | |
576 | } | |
577 | } | |
ffe2bea7 A |
578 | |
579 | // simple iterating is enough to create list of detected objects | |
580 | // in the order of increasing distance | |
581 | myDetected.Clear(); | |
582 | for (LstDetected::Iterator anIt(aDetected); anIt.More(); anIt.Next()) | |
583 | myDetected.Append(anIt.Value().PObj); | |
584 | ||
7fd59977 | 585 | return aSelected; |
586 | } | |
ffe2bea7 | 587 |