0025332: Visualization - rewrite MinMaxValues methods to using of Bnd_Box
[occt.git] / src / NIS / NIS_View.cxx
CommitLineData
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 26IMPLEMENT_STANDARD_HANDLE (NIS_View, V3d_View)
27IMPLEMENT_STANDARD_RTTIEXT (NIS_View, V3d_View)
7fd59977 28
29//=======================================================================
30//function : NIS_View()
31//purpose : Constructor
32//=======================================================================
33
34NIS_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
49void 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
68void 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
84void 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
107Standard_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
137Bnd_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 169void 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
215int 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
330void 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 370void 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
387void 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
411void 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
463void 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 536Handle(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 558Handle(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