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