0026392: Visualization, TKD3DHost - provide straight-forward base for integration...
[occt.git] / src / V3d / V3d_View.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 /***********************************************************************
15 FONCTION :
16 ----------
17 Classe V3d_View :
18 HISTORIQUE DES MODIFICATIONS   :
19 --------------------------------
20 00-09-92 : GG  ; Creation.
21 02-10-96 : FMN ; Suppression appel Redraw sans MustBeResized()
22 05-06-97 : FMN ; Correction FitAll()
23 30-06-97 : GG ; Correction + Optimisation de Panning(...)
24 On fait la translation + le zoom en une seule
25 operation au lieu de 2 precedemment qui etait buggee.
26 09-07-97 : FMN ; Correction FitAll() sur le Ratio
27 16-07-97 : FMN ; Correction FitAll() sur le calcul de la Box
28 22-07-97 : FMN ; Ajout mode RetainMode pour le Transient
29 15-12-97 : FMN ; Ajout texture mapping
30 17-12-97 : FMN ; CTS19129 Correction FitAll() multiple
31 18-12-97 : FMN ; Ajout mode Ajout
32 24-12-97 : FMN ; Remplacement de math par MathGra
33 24-12-97 : CQO ; BUC50037 Xw_Window -> Aspect_Window
34 31-12-97 : CAL ; Remplacement de MathGra par Array2OfReal
35 07-01-98 : CAL ; Ajout de la methode DoMapping.
36 07-01-98 : CAL ; Retrait de tous les "this->" inutiles
37 21-01-98 : CAL ; Remplacement des Window->Position () par Window->Size ()
38 27-01-98 : FMN ; PERF: OPTIMISATION LOADER (LOPTIM)
39 12-02-98 : GG  ; Reactivation du Redraw dans MustBeResized()
40 23-02-98 : FMN ; Remplacement PI par Standard_PI
41 25-02-98 : FMN ; PERF.27: Optimisation of view creation from existing view
42 11-03-98 : STT ; S3558
43 19-03-98 : FMN ; Probleme dans FitAll car la methode WNT_Window::Size(Real,Real)
44 ne marche pas.
45 08-04-98 : STT ; suppr. S3558
46 10-04-98 : CAL ; Ajout des methodes RefToPix et PixToRef
47 13-06-98 : FMN ; Probleme dans FitAll car la methode WNT_Window::Size(Real,Real)
48 ne marche pas. Contournement en appelant WNT_Window::Size(Int,Int).
49 16-08-98 : CAL ; S3892. Ajout grilles 3d.
50 09-09-98 : CAL ; S3892. Generalisation de TrsPoint.
51 06-10-98 : CAL ; Ajout d'un TIMER si CSF_GraphicTimer est definie.
52 16-10-98 : CAL ; Retrait d'un TIMER si CSF_GraphicTimer est definie.
53 06-11-98 : CAL ; PRO ?????. Probleme dans ZFitAll si un point dans la vue.
54 29-OCT-98 : DCB : Adding ScreenCopy () method.
55 REMARQUES :
56 -----------
57 About  FitAll() multiple. This probleme is caused by missing
58 precision of transformation matrices. If it is supposed that
59 projection is made in the plane (U,V), there is a difference
60 after several Zoom - compared to the exact value (cf ZoomX).
61 Don't forget that the matrices work in float and not in double.
62 To solve the problem (for lack of a better solution) I make 2 passes.
63 ************************************************************************/
64 /*----------------------------------------------------------------------*/
65 /*
66 * Includes
67 */
68
69 #include <Aspect_ColorScale.hxx>
70 #include <Aspect_GradientBackground.hxx>
71 #include <Aspect_Grid.hxx>
72 #include <Aspect_Window.hxx>
73 #include <Bnd_Box.hxx>
74 #include <gp_Ax3.hxx>
75 #include <gp_Dir.hxx>
76 #include <gp_Pln.hxx>
77 #include <Graphic3d_AspectMarker3d.hxx>
78 #include <Graphic3d_GraphicDriver.hxx>
79 #include <Graphic3d_Group.hxx>
80 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
81 #include <Graphic3d_MapOfStructure.hxx>
82 #include <Graphic3d_Structure.hxx>
83 #include <Graphic3d_TextureEnv.hxx>
84 #include <Graphic3d_Vector.hxx>
85 #include <Image_AlienPixMap.hxx>
86 #include <NCollection_Array1.hxx>
87 #include <Precision.hxx>
88 #include <Quantity_Color.hxx>
89 #include <Standard_Assert.hxx>
90 #include <Standard_DivideByZero.hxx>
91 #include <Standard_ErrorHandler.hxx>
92 #include <Standard_MultiplyDefined.hxx>
93 #include <Standard_ShortReal.hxx>
94 #include <Standard_Type.hxx>
95 #include <Standard_TypeMismatch.hxx>
96 #include <TColStd_Array2OfReal.hxx>
97 #include <TColStd_HSequenceOfInteger.hxx>
98 #include <V3d.hxx>
99 #include <V3d_BadValue.hxx>
100 #include <V3d_LayerMgr.hxx>
101 #include <V3d_Light.hxx>
102 #include <V3d_StereoDumpOptions.hxx>
103 #include <V3d_UnMapped.hxx>
104 #include <V3d_View.hxx>
105 #include <V3d_Viewer.hxx>
106 #include <Visual3d_Layer.hxx>
107 #include <Visual3d_Light.hxx>
108 #include <Visual3d_View.hxx>
109 #include <Visual3d_ViewManager.hxx>
110
111 #define V3d_FLAG_COMPUTATION   0x00000004
112
113 // Perspective
114 #include <OSD_Environment.hxx>
115
116 /*----------------------------------------------------------------------*/
117 /*
118 * Constant
119 */
120
121 #define DEUXPI (2. * M_PI)
122
123 namespace
124 {
125   static const Standard_Integer THE_NB_BOUND_POINTS = 8;
126 }
127
128 //=============================================================================
129 //function : Constructor
130 //purpose  :
131 //=============================================================================
132 V3d_View::V3d_View(const Handle(V3d_Viewer)& VM, const V3d_TypeOfView Type ) :
133   MyViewer(VM.operator->()),
134   MyActiveLights(),
135   MyViewContext (),
136   myActiveLightsIterator(),
137   SwitchSetFront(Standard_False),
138   MyTrsf (1, 4, 1, 4)
139 {
140   myImmediateUpdate = Standard_False;
141   MyView = new Visual3d_View(MyViewer->Viewer());
142
143   // { Begin to retrieve the definition from ViewContext.
144   // Step MyViewContext = MyView->Context() ;
145   // to permit MyView->SetContext to compare
146   // the old and the new context.
147   // No problem for MyViewMapping, MyViewOrientation
148   // as MyView->SetViewMapping and MyView->SetViewOrientation
149   // don't try to optimize the modifications introduced to
150   // viewmapping and vieworientation.
151
152   // Aliasing
153   if ((MyView->Context ()).AliasingIsOn ())
154     MyViewContext.SetAliasingOn ();
155   else
156     MyViewContext.SetAliasingOff ();
157
158   // DepthCueing
159   MyViewContext.SetDepthCueingBackPlane
160     ((MyView->Context ()).DepthCueingBackPlane ());
161   MyViewContext.SetDepthCueingFrontPlane
162     ((MyView->Context ()).DepthCueingFrontPlane ());
163
164   if ((MyView->Context ()).DepthCueingIsOn ())
165     MyViewContext.SetDepthCueingOn ();
166   else
167     MyViewContext.SetDepthCueingOff ();
168
169   // ZClipping
170   MyViewContext.SetZClippingBackPlane
171     ((MyView->Context ()).ZClippingBackPlane ());
172   MyViewContext.SetZClippingFrontPlane
173     ((MyView->Context ()).ZClippingFrontPlane ());
174
175   if ((MyView->Context ()).FrontZClippingIsOn ())
176     MyViewContext.SetFrontZClippingOn ();
177   else
178     MyViewContext.SetFrontZClippingOff ();
179
180   if ((MyView->Context ()).BackZClippingIsOn ())
181     MyViewContext.SetBackZClippingOn ();
182   else
183     MyViewContext.SetBackZClippingOff ();
184
185   // Visualization and Shading Model
186   MyViewContext.SetModel ((MyView->Context ()).Model ());
187   MyViewContext.SetVisualization ((MyView->Context ()).Visualization ());
188
189   // Texture Mapping
190   MyViewContext.SetSurfaceDetail (MyView->Context ().SurfaceDetail ());
191   MyViewContext.SetTextureEnv (MyView->Context ().TextureEnv ());
192   // } End of retrieval of the definition of ViewContext.
193
194   MyBackground = VM->GetBackgroundColor() ;
195   MyGradientBackground = VM->GetGradientBackground() ;
196
197   // camera init
198   Handle(Graphic3d_Camera) aCamera = new Graphic3d_Camera();
199   aCamera->SetFOVy (45.0);
200   aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, 0.05);
201   aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, 1.0);
202   SetCamera (aCamera);
203
204   SetAxis (0.,0.,0.,1.,1.,1.);
205   SetVisualization (VM->DefaultVisualization());
206   SetShadingModel (VM->DefaultShadingModel());
207   SetSurfaceDetail (VM->DefaultSurfaceDetail());
208   SetTwist (0.);
209   SetAt (0.,0.,0.);
210   SetProj (VM->DefaultViewProj());
211   SetSize (VM->DefaultViewSize());
212   Standard_Real zsize = VM->DefaultViewSize();
213   SetZSize (2.*zsize);
214   SetZClippingDepth (0.);
215   SetZClippingWidth (zsize);
216   SetZCueingDepth (0.);
217   SetZCueingWidth (zsize);
218   SetDepth (VM->DefaultViewSize()/2.0);
219   SetViewMappingDefault();
220   SetViewOrientationDefault();
221   VM->AddView (this);
222   Init();
223   myImmediateUpdate = Standard_True;
224
225   aCamera->SetProjectionType ((Type == V3d_ORTHOGRAPHIC)
226     ? Graphic3d_Camera::Projection_Orthographic
227     : Graphic3d_Camera::Projection_Perspective);
228 }
229
230 //=============================================================================
231 //function : Constructor
232 //purpose  :
233 //=============================================================================
234 V3d_View::V3d_View(const Handle(V3d_Viewer)& theVM,const Handle(V3d_View)& theView) :
235   MyViewer(theVM.operator->()),
236   MyActiveLights(),
237   MyViewContext (),
238   myActiveLightsIterator(),
239   SwitchSetFront(Standard_False),
240   MyTrsf (1, 4, 1, 4)
241 {
242   Handle(Visual3d_View) aFromView = theView->View();
243
244   myImmediateUpdate = Standard_False;
245   MyView = new Visual3d_View (MyViewer->Viewer());
246
247   for (theView->InitActiveLights(); theView->MoreActiveLights(); theView->NextActiveLights())
248   {
249     MyActiveLights.Append (theView->ActiveLight());
250   }
251
252   MyViewContext = aFromView->Context() ;
253
254   SetCamera (new Graphic3d_Camera (theView->Camera()));
255   View()->SetAutoZFitMode (theView->View()->AutoZFitMode(), theView->View()->AutoZFitScaleFactor());
256
257   MyBackground = aFromView->Background() ;
258   MyGradientBackground = aFromView->GradientBackground();
259
260   MyView->SetContext (MyViewContext) ;
261
262   SetAxis (0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
263
264   SetViewMappingDefault();
265   SetViewOrientationDefault();
266   theVM->AddView (this);
267
268   Init();
269
270   myImmediateUpdate = Standard_True;
271 }
272
273 //=============================================================================
274 //function : SetMagnify
275 //purpose  :
276 //=============================================================================
277 void V3d_View::SetMagnify(const Handle(Aspect_Window)& TheWindow,
278                           const Handle(V3d_View)& aPreviousView,
279                           const Standard_Integer x1,
280                           const Standard_Integer y1,
281                           const Standard_Integer x2,
282                           const Standard_Integer y2)
283 {
284   if( !MyView->IsDefined() ) {
285     Standard_Real a,b,c,d;
286     aPreviousView->Convert(x1,y1,a,b);
287     aPreviousView->Convert(x2,y2,c,d);
288     MyView->SetWindow(TheWindow) ;
289     FitAll(TheWindow,a,b,c,d);
290     MyView->SetContext(MyViewContext) ;
291     MyView->SetBackground(MyBackground) ;
292     MyViewer->SetViewOn(this) ;
293     MyWindow = TheWindow;
294     MyView->Redraw() ;
295     SetViewMappingDefault();
296   }
297 }
298
299 //=============================================================================
300 //function : SetWindow
301 //purpose  :
302 //=============================================================================
303 void V3d_View::SetWindow(const Handle(Aspect_Window)& TheWindow)
304 {
305   MyView->SetWindow(TheWindow) ;
306   // method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw()
307   MyWindow = TheWindow;
308   // SetWindow carries out SetRatio and modifies
309   MyView->SetContext(MyViewContext) ;
310   MyView->SetBackground(MyBackground) ;
311   MyViewer->SetViewOn(this) ;
312   MyView->Redraw() ;
313 }
314
315 //=============================================================================
316 //function : SetWindow
317 //purpose  :
318 //=============================================================================
319 void V3d_View::SetWindow(const Handle(Aspect_Window)&      aWindow,
320                          const Aspect_RenderingContext     aContext,
321                          const Aspect_GraphicCallbackProc& aDisplayCB,
322                          const Standard_Address            aClientData)
323 {
324   // method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw()
325   MyWindow = aWindow;
326   MyView->SetWindow(aWindow, aContext, aDisplayCB, aClientData) ;
327   MyView->SetContext(MyViewContext) ;
328   MyView->SetBackground(MyBackground) ;
329   MyViewer->SetViewOn(this) ;
330   MyView->Redraw() ;
331 }
332
333 //=============================================================================
334 //function : Remove
335 //purpose  :
336 //=============================================================================
337 void V3d_View::Remove() const
338 {
339   MyViewer->DelView (this);
340   MyView->Remove();
341   Handle(Aspect_Window)& aWin = const_cast<Handle(Aspect_Window)&> (MyWindow);
342   aWin.Nullify();
343 }
344
345 //=============================================================================
346 //function : Update
347 //purpose  :
348 //=============================================================================
349 void V3d_View::Update() const
350 {
351   if( MyView->IsDefined() )  MyView->Update (Aspect_TOU_ASAP) ;
352 }
353
354 //=============================================================================
355 //function : Redraw
356 //purpose  :
357 //=============================================================================
358 void V3d_View::Redraw() const
359 {
360   if( MyView->IsDefined() ) MyView->Redraw() ;
361 }
362
363 //=============================================================================
364 //function : RedrawImmediate
365 //purpose  :
366 //=============================================================================
367 void V3d_View::RedrawImmediate() const
368 {
369   if (MyView->IsDefined())
370   {
371     MyView->RedrawImmediate();
372   }
373 }
374
375 //=============================================================================
376 //function : Invalidate
377 //purpose  :
378 //=============================================================================
379 void V3d_View::Invalidate() const
380 {
381   if (MyView->IsDefined())
382   {
383     MyView->Invalidate();
384   }
385 }
386
387 //=============================================================================
388 //function : IsInvalidated
389 //purpose  :
390 //=============================================================================
391 Standard_Boolean V3d_View::IsInvalidated() const
392 {
393   return !MyView->IsDefined()
394        || MyView->IsInvalidated();
395 }
396
397 //=============================================================================
398 //function : AutoZFit
399 //purpose  :
400 //=============================================================================
401 void V3d_View::AutoZFit()
402 {
403   View()->AutoZFit();
404 }
405
406 //=============================================================================
407 //function : ZFitAll
408 //purpose  :
409 //=============================================================================
410 void V3d_View::ZFitAll (const Standard_Real theScaleFactor)
411 {
412   View()->ZFitAll (theScaleFactor);
413 }
414
415 //=============================================================================
416 //function : Redraw
417 //purpose  :
418 //=============================================================================
419 void V3d_View::Redraw(const Standard_Integer xc,const Standard_Integer yc,
420                       const Standard_Integer width,const Standard_Integer height) const
421 {
422   if( MyView->IsDefined() ) MyView->Redraw(xc,yc,width,height) ;
423 }
424
425 //=============================================================================
426 //function : IsEmpty
427 //purpose  :
428 //=============================================================================
429 Standard_Boolean V3d_View::IsEmpty() const
430 {
431   Standard_Boolean TheStatus = Standard_True ;
432   if( MyView->IsDefined() ) {
433     Standard_Integer Nstruct = MyView->NumberOfDisplayedStructures() ;
434     if( Nstruct > 0 ) TheStatus = Standard_False ;
435   }
436   return (TheStatus) ;
437 }
438
439 //=============================================================================
440 //function : UpdateLights
441 //purpose  :
442 //=============================================================================
443 void V3d_View::UpdateLights() const
444 {
445   MyView->SetContext(MyViewContext);
446   Update();
447 }
448
449 //=============================================================================
450 //function : DoMapping
451 //purpose  :
452 //=============================================================================
453 void V3d_View::DoMapping()
454 {
455   if( MyView->IsDefined() ) {
456     (MyView->Window())->DoMapping() ;
457   }
458 }
459
460 //=============================================================================
461 //function : MustBeResized
462 //purpose  :
463 //=============================================================================
464 void V3d_View::MustBeResized()
465 {
466   if ( !MyLayerMgr.IsNull() )
467     MyLayerMgr->Resized();
468
469   if( MyView->IsDefined() ) {
470     MyView->Resized() ;
471     MyView->Redraw();
472   }
473 }
474
475 //=============================================================================
476 //function : SetBackgroundColor
477 //purpose  :
478 //=============================================================================
479 void V3d_View::SetBackgroundColor(const Quantity_TypeOfColor Type, const Standard_Real v1, const Standard_Real v2, const Standard_Real v3)
480 {
481   Standard_Real V1 = Max( Min( v1, 1.0 ), 0.0 );
482   Standard_Real V2 = Max( Min( v2, 1.0 ), 0.0 );
483   Standard_Real V3 = Max( Min( v3, 1.0 ), 0.0 );
484
485   Quantity_Color C( V1, V2, V3, Type );
486   SetBackgroundColor( C );
487 }
488
489 //=============================================================================
490 //function : SetBackgroundColor
491 //purpose  :
492 //=============================================================================
493 void V3d_View::SetBackgroundColor(const Quantity_Color &Color)
494 {
495   MyBackground.SetColor( Color );
496   if ( MyView->IsDefined() )
497     MyView->SetBackground( MyBackground );
498   //szv: Why?
499   if ( !MyLayerMgr.IsNull() )
500     MyLayerMgr->Resized();
501 }
502
503 //=============================================================================
504 //function : SetBackgroundColor
505 //purpose  :
506 //=============================================================================
507 void V3d_View::SetBackgroundColor(const Quantity_NameOfColor Name)
508 {
509   Quantity_Color C( Name );
510   SetBackgroundColor( C );
511 }
512
513 //=============================================================================
514 //function : SetBgGradientColors
515 //purpose  :
516 //=============================================================================
517 void V3d_View::SetBgGradientColors( const Quantity_Color& Color1,
518                                     const Quantity_Color& Color2,
519                                     const Aspect_GradientFillMethod FillStyle,
520                                     const Standard_Boolean status)
521 {
522   MyGradientBackground.SetColors(Color1, Color2, FillStyle);
523   if ( MyView->IsDefined() )
524     MyView->SetGradientBackground( MyGradientBackground, status );
525 }
526
527 //=============================================================================
528 //function : SetBgGradientColors
529 //purpose  :
530 //=============================================================================
531 void V3d_View::SetBgGradientColors( const Quantity_NameOfColor Color1,
532                                     const Quantity_NameOfColor Color2,
533                                     const Aspect_GradientFillMethod FillStyle,
534                                     const Standard_Boolean status )
535 {
536   Quantity_Color C1( Color1 );
537   Quantity_Color C2( Color2 );
538   MyGradientBackground.SetColors( C1, C2, FillStyle );
539   if ( MyView->IsDefined() )
540     MyView->SetGradientBackground( MyGradientBackground, status );
541 }
542
543 //=============================================================================
544 //function : SetBgGradientStyle
545 //purpose  :
546 //=============================================================================
547 void V3d_View::SetBgGradientStyle( const Aspect_GradientFillMethod FillStyle,
548                                    const Standard_Boolean update)
549 {
550   Quantity_Color Color1, Color2;
551   MyGradientBackground.Colors( Color1, Color2 );
552   MyGradientBackground.SetColors( Color1, Color2, FillStyle );
553   if( MyView->IsDefined() )
554     MyView->SetBgGradientStyle( FillStyle, update ) ;
555 }
556
557 //=============================================================================
558 //function : SetBackgroundImage
559 //purpose  :
560 //=============================================================================
561 void V3d_View::SetBackgroundImage( const Standard_CString FileName,
562                                    const Aspect_FillMethod FillStyle,
563                                    const Standard_Boolean update )
564 {
565   if( MyView->IsDefined() )
566     MyView->SetBackgroundImage( FileName, FillStyle, update ) ;
567 }
568
569 //=============================================================================
570 //function : SetBgImageStyle
571 //purpose  :
572 //=============================================================================
573 void V3d_View::SetBgImageStyle( const Aspect_FillMethod FillStyle,
574                                 const Standard_Boolean update )
575 {
576   if( MyView->IsDefined() )
577     MyView->SetBgImageStyle( FillStyle, update ) ;
578 }
579
580 //=============================================================================
581 //function : SetAxis
582 //purpose  :
583 //=============================================================================
584 void V3d_View::SetAxis(const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Real Vx, const Standard_Real Vy, const Standard_Real Vz)
585 {
586   Standard_Real D,Nx = Vx,Ny = Vy,Nz = Vz ;
587
588   D = Sqrt( Vx*Vx + Vy*Vy + Vz*Vz ) ;
589   V3d_BadValue_Raise_if ( D <= 0. , "V3d_View::SetAxis, bad axis");
590   Nx /= D ; Ny /= D ; Nz /= D ;
591   MyDefaultViewPoint.SetCoord(X,Y,Z) ;
592   MyDefaultViewAxis.SetCoord(Nx,Ny,Nz) ;
593 }
594
595 //=============================================================================
596 //function : SetShadingModel
597 //purpose  :
598 //=============================================================================
599 void V3d_View::SetShadingModel(const V3d_TypeOfShadingModel Model)
600 {
601   MyViewContext.SetModel((Visual3d_TypeOfModel) Model) ;
602   MyView->SetContext(MyViewContext) ;
603 }
604
605 //=============================================================================
606 //function : SetSurfaceDetail
607 //purpose  :
608 //=============================================================================
609 void V3d_View::SetSurfaceDetail(const V3d_TypeOfSurfaceDetail Model)
610 {
611   MyViewContext.SetSurfaceDetail((Visual3d_TypeOfSurfaceDetail) Model) ;
612   MyView->SetContext(MyViewContext) ;
613 }
614
615 //=============================================================================
616 //function : SetTextureEnv
617 //purpose  :
618 //=============================================================================
619 void V3d_View::SetTextureEnv(const Handle(Graphic3d_TextureEnv)& ATexture)
620 {
621   MyViewContext.SetTextureEnv(ATexture) ;
622   MyView->SetContext(MyViewContext) ;
623 }
624
625 //=============================================================================
626 //function : SetVisualization
627 //purpose  :
628 //=============================================================================
629 void V3d_View::SetVisualization(const V3d_TypeOfVisualization Mode)
630 {
631   MyViewContext.SetVisualization((Visual3d_TypeOfVisualization) Mode);
632   MyView->SetContext(MyViewContext) ;
633 }
634
635 //=============================================================================
636 //function : SetFront
637 //purpose  :
638 //=============================================================================
639 void V3d_View::SetFront()
640 {
641   gp_Ax3 a = MyViewer->PrivilegedPlane();
642   Standard_Real xo, yo, zo, vx, vy, vz, xu, yu, zu;
643
644   a.Direction().Coord(vx,vy,vz);
645   a.YDirection().Coord(xu,yu,zu);
646   a.Location().Coord(xo,yo,zo);
647
648   myCamera->SetCenter (gp_Pnt (xo, yo, zo));
649   if(SwitchSetFront)
650     myCamera->SetDirection (gp_Dir (vx, vy, vz));
651   else
652     myCamera->SetDirection (gp_Dir (vx, vy, vz).Reversed());
653   myCamera->SetUp (gp_Dir (xu, yu, zu));
654
655   View()->AutoZFit();
656
657   SwitchSetFront = !SwitchSetFront;
658
659   ImmediateUpdate();
660 }
661
662 //=============================================================================
663 //function : Rotate
664 //purpose  :
665 //=============================================================================
666 void V3d_View::Rotate (const Standard_Real ax, 
667                        const Standard_Real ay, 
668                        const Standard_Real az, 
669                        const Standard_Boolean Start)
670 {
671   Standard_Real Ax = ax;
672   Standard_Real Ay = ay;
673   Standard_Real Az = az;
674
675   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI;
676   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI;
677   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI;
678   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI;
679   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI;
680   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI;
681
682   if (Start)
683   {
684     myCamStartOpUp = myCamera->Up();
685     myCamStartOpEye = myCamera->Eye();
686     myCamStartOpCenter = myCamera->Center();
687   }
688
689   myCamera->SetUp (myCamStartOpUp);
690   myCamera->SetEye (myCamStartOpEye);
691   myCamera->SetCenter (myCamStartOpCenter);
692
693   // rotate camera around 3 initial axes
694   gp_Dir aBackDir (gp_Vec (myCamStartOpCenter, myCamStartOpEye));
695   gp_Dir aXAxis (myCamStartOpUp.Crossed (aBackDir));
696   gp_Dir aYAxis (aBackDir.Crossed (aXAxis));
697   gp_Dir aZAxis (aXAxis.Crossed (aYAxis));
698
699   gp_Trsf aRot[3], aTrsf;
700   aRot[0].SetRotation (gp_Ax1 (myCamStartOpCenter, aYAxis), -Ax);
701   aRot[1].SetRotation (gp_Ax1 (myCamStartOpCenter, aXAxis), Ay);
702   aRot[2].SetRotation (gp_Ax1 (myCamStartOpCenter, aZAxis), Az);
703   aTrsf.Multiply (aRot[0]);
704   aTrsf.Multiply (aRot[1]);
705   aTrsf.Multiply (aRot[2]);
706
707   myCamera->Transform (aTrsf);
708
709   View()->AutoZFit();
710
711   ImmediateUpdate();
712 }
713
714 //=============================================================================
715 //function : Rotate
716 //purpose  :
717 //=============================================================================
718 void V3d_View::Rotate(const Standard_Real ax, const Standard_Real ay, const Standard_Real az,
719                       const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Boolean Start)
720 {
721
722   Standard_Real Ax = ax ;
723   Standard_Real Ay = ay ;
724   Standard_Real Az = az ;
725
726   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI ;
727   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI ;
728   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI ;
729   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI ;
730   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI ;
731   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI ;
732
733   if (Start)
734   {
735     myGravityReferencePoint.SetCoord (X, Y, Z);
736     myCamStartOpUp = myCamera->Up();
737     myCamStartOpEye = myCamera->Eye();
738     myCamStartOpCenter = myCamera->Center();
739   }
740
741   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
742
743   myCamera->SetUp (myCamStartOpUp);
744   myCamera->SetEye (myCamStartOpEye);
745   myCamera->SetCenter (myCamStartOpCenter);
746
747   // rotate camera around 3 initial axes
748   gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z());
749
750   gp_Dir aZAxis (myCamera->Direction().Reversed());
751   gp_Dir aYAxis (myCamera->Up());
752   gp_Dir aXAxis (aYAxis.Crossed (aZAxis)); 
753
754   gp_Trsf aRot[3], aTrsf;
755   aRot[0].SetRotation (gp_Ax1 (aRCenter, aYAxis), -Ax);
756   aRot[1].SetRotation (gp_Ax1 (aRCenter, aXAxis), Ay);
757   aRot[2].SetRotation (gp_Ax1 (aRCenter, aZAxis), Az);
758   aTrsf.Multiply (aRot[0]);
759   aTrsf.Multiply (aRot[1]);
760   aTrsf.Multiply (aRot[2]);
761
762   myCamera->Transform (aTrsf);
763
764   View()->AutoZFit();
765
766   ImmediateUpdate();
767 }
768
769 //=============================================================================
770 //function : Rotate
771 //purpose  :
772 //=============================================================================
773 void V3d_View::Rotate(const V3d_TypeOfAxe Axe, const Standard_Real angle, const Standard_Boolean Start)
774 {
775   switch (Axe) {
776   case V3d_X :
777     Rotate(angle,0.,0.,Start);
778     break ;
779   case V3d_Y :
780     Rotate(0.,angle,0.,Start);
781     break ;
782   case V3d_Z :
783     Rotate(0.,0.,angle,Start);
784     break ;
785   }
786 }
787
788 //=============================================================================
789 //function : Rotate
790 //purpose  :
791 //=============================================================================
792 void V3d_View::Rotate(const V3d_TypeOfAxe Axe, const Standard_Real angle,
793                       const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Boolean Start)
794 {
795   Standard_Real Angle = angle ;
796
797   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
798   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
799
800   if (Start)
801   {
802     myGravityReferencePoint.SetCoord (X, Y, Z);
803     myCamStartOpUp = myCamera->Up();
804     myCamStartOpEye = myCamera->Eye();
805     myCamStartOpCenter = myCamera->Center();
806
807     switch (Axe) {
808     case V3d_X :
809       myViewAxis.SetCoord(1.,0.,0.) ;
810       break ;
811     case V3d_Y :
812       myViewAxis.SetCoord(0.,1.,0.) ;
813       break ;
814     case V3d_Z :
815       myViewAxis.SetCoord(0.,0.,1.) ;
816       break ;
817     }
818
819     myCamStartOpUp = myCamera->Up();
820     myCamStartOpEye = myCamera->Eye();
821     myCamStartOpCenter = myCamera->Center();
822   }
823
824   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
825
826   myCamera->SetUp (myCamStartOpUp);
827   myCamera->SetEye (myCamStartOpEye);
828   myCamera->SetCenter (myCamStartOpCenter);
829
830   // rotate camera around passed axis
831   gp_Trsf aRotation;
832   gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z());
833   gp_Dir aRAxis ((Axe == V3d_X) ? 1.0 : 0.0,
834                   (Axe == V3d_Y) ? 1.0 : 0.0,
835                   (Axe == V3d_Z) ? 1.0 : 0.0);
836
837   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
838   myCamera->Transform (aRotation);
839
840   View()->AutoZFit();
841
842   ImmediateUpdate();
843 }
844
845 //=============================================================================
846 //function : Rotate
847 //purpose  :
848 //=============================================================================
849 void V3d_View::Rotate(const Standard_Real angle, const Standard_Boolean Start)
850 {
851   Standard_Real Angle = angle;
852
853   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
854   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
855
856   if( Start ) {
857     myCamStartOpUp = myCamera->Up();
858     myCamStartOpEye = myCamera->Eye();
859     myCamStartOpCenter = myCamera->Center();
860   }
861
862   const Graphic3d_Vertex& aPnt = MyDefaultViewPoint;
863   const Graphic3d_Vector& anAxis = MyDefaultViewAxis;
864
865   myCamera->SetUp (myCamStartOpUp);
866   myCamera->SetEye (myCamStartOpEye);
867   myCamera->SetCenter (myCamStartOpCenter);
868
869   gp_Trsf aRotation;
870   gp_Pnt aRCenter (aPnt.X(), aPnt.Y(), aPnt.Z());
871   gp_Dir aRAxis (anAxis.X(), anAxis.Y(), anAxis.Z());
872   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
873   myCamera->Transform (aRotation);
874
875   View()->AutoZFit();
876
877   ImmediateUpdate();
878 }
879
880 //=============================================================================
881 //function : Turn
882 //purpose  :
883 //=============================================================================
884 void V3d_View::Turn(const Standard_Real ax, const Standard_Real ay, const Standard_Real az, const Standard_Boolean Start)
885 {
886   Standard_Real Ax = ax;
887   Standard_Real Ay = ay;
888   Standard_Real Az = az;
889
890   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI ;
891   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI ;
892   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI ;
893   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI ;
894   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI ;
895   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI ;
896
897   if( Start ) {
898     myCamStartOpUp = myCamera->Up();
899     myCamStartOpEye = myCamera->Eye();
900     myCamStartOpCenter = myCamera->Center();
901   }
902
903   myCamera->SetUp (myCamStartOpUp);
904   myCamera->SetEye (myCamStartOpEye);
905   myCamera->SetCenter (myCamStartOpCenter);
906
907   // rotate camera around 3 initial axes
908   gp_Pnt aRCenter = myCamera->Eye();
909   gp_Dir aZAxis (myCamera->Direction().Reversed());
910   gp_Dir aYAxis (myCamera->Up());
911   gp_Dir aXAxis (aYAxis.Crossed (aZAxis)); 
912
913   gp_Trsf aRot[3], aTrsf;
914   aRot[0].SetRotation (gp_Ax1 (aRCenter, aYAxis), -Ax);
915   aRot[1].SetRotation (gp_Ax1 (aRCenter, aXAxis), Ay);
916   aRot[2].SetRotation (gp_Ax1 (aRCenter, aZAxis), Az);
917   aTrsf.Multiply (aRot[0]);
918   aTrsf.Multiply (aRot[1]);
919   aTrsf.Multiply (aRot[2]);
920
921   myCamera->Transform (aTrsf);
922
923   View()->AutoZFit();
924
925   ImmediateUpdate();
926 }
927
928 //=============================================================================
929 //function : Turn
930 //purpose  :
931 //=============================================================================
932 void V3d_View::Turn(const V3d_TypeOfAxe Axe, const Standard_Real angle, const Standard_Boolean Start)
933 {
934   switch (Axe) {
935   case V3d_X :
936     Turn(angle,0.,0.,Start);
937     break ;
938   case V3d_Y :
939     Turn(0.,angle,0.,Start);
940     break ;
941   case V3d_Z :
942     Turn(0.,0.,angle,Start);
943     break ;
944   }
945 }
946
947 //=============================================================================
948 //function : Turn
949 //purpose  :
950 //=============================================================================
951 void V3d_View::Turn(const Standard_Real angle, const Standard_Boolean Start)
952 {
953   Standard_Real Angle = angle ;
954
955   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
956   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
957
958   if( Start ) {
959     myCamStartOpUp = myCamera->Up();
960     myCamStartOpEye = myCamera->Eye();
961     myCamStartOpCenter = myCamera->Center();
962   }
963
964   myCamera->SetUp (myCamStartOpUp);
965   myCamera->SetEye (myCamStartOpEye);
966   myCamera->SetCenter (myCamStartOpCenter);
967
968   const Graphic3d_Vector& anAxis = MyDefaultViewAxis;
969
970   gp_Trsf aRotation;
971   gp_Pnt aRCenter = myCamera->Eye();
972   gp_Dir aRAxis (anAxis.X(), anAxis.Y(), anAxis.Z());
973   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
974   myCamera->Transform (aRotation);
975
976   View()->AutoZFit();
977
978   ImmediateUpdate();
979 }
980
981 //=============================================================================
982 //function : SetTwist
983 //purpose  :
984 //=============================================================================
985 void V3d_View::SetTwist(const Standard_Real angle)
986 {
987   Standard_Real Angle = angle ;
988   Standard_Boolean TheStatus;
989
990   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
991   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
992
993   gp_Dir aReferencePlane (myCamera->Direction().Reversed());
994   gp_Dir anUp;
995
996   anUp = gp_Dir (0.0, 0.0, 1.0);
997
998   TheStatus = ScreenAxis(aReferencePlane, anUp,
999     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1000   if( !TheStatus ) {
1001     anUp = gp_Dir (0.0, 1.0, 0.0);
1002     TheStatus = ScreenAxis(aReferencePlane, anUp,
1003       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1004   }
1005   if( !TheStatus ) {
1006     anUp = gp_Dir (1.0, 0.0, 0.0);
1007     TheStatus = ScreenAxis(aReferencePlane, anUp,
1008       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1009   }
1010
1011   V3d_BadValue_Raise_if( !TheStatus,"V3d_ViewSetTwist, alignment of Eye,At,Up,");
1012   
1013   gp_Pnt aRCenter = myCamera->Center();
1014   gp_Dir aZAxis (myCamera->Direction().Reversed());
1015
1016   gp_Trsf aTrsf;
1017   aTrsf.SetRotation (gp_Ax1 (aRCenter, aZAxis), Angle);
1018
1019   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
1020   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
1021
1022   myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
1023   myCamera->Transform (aTrsf);
1024
1025   View()->AutoZFit();
1026
1027   ImmediateUpdate();
1028 }
1029
1030 //=============================================================================
1031 //function : SetEye
1032 //purpose  :
1033 //=============================================================================
1034 void V3d_View::SetEye(const Standard_Real X,const Standard_Real Y,const Standard_Real Z)
1035 {
1036   Standard_Real aTwistBefore = Twist();
1037
1038   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1039
1040   myCamera->SetEye (gp_Pnt (X, Y, Z));
1041   SetTwist (aTwistBefore);
1042
1043   View()->AutoZFit();
1044
1045   SetImmediateUpdate (wasUpdateEnabled);
1046
1047   ImmediateUpdate();
1048 }
1049
1050 //=============================================================================
1051 //function : SetDepth
1052 //purpose  :
1053 //=============================================================================
1054 void V3d_View::SetDepth(const Standard_Real Depth)
1055 {
1056   V3d_BadValue_Raise_if (Depth == 0. ,"V3d_View::SetDepth, bad depth");
1057
1058   if( Depth > 0. )
1059   {
1060     // Move eye using center (target) as anchor.
1061     myCamera->SetDistance (Depth);
1062   }
1063   else
1064   {
1065     // Move the view ref point instead of the eye.
1066     gp_Vec aDir (myCamera->Direction());
1067     gp_Pnt aCameraEye = myCamera->Eye();
1068     gp_Pnt aCameraCenter = aCameraEye.Translated (aDir.Multiplied (Abs (Depth)));
1069
1070     myCamera->SetCenter (aCameraCenter);
1071   }
1072
1073   View()->AutoZFit();
1074
1075   ImmediateUpdate();
1076 }
1077
1078 //=============================================================================
1079 //function : SetProj
1080 //purpose  :
1081 //=============================================================================
1082 void V3d_View::SetProj( const Standard_Real Vx,const Standard_Real Vy, const Standard_Real Vz )
1083 {
1084   V3d_BadValue_Raise_if( Sqrt(Vx*Vx + Vy*Vy + Vz*Vz) <= 0.,
1085     "V3d_View::SetProj, null projection vector");
1086
1087   Standard_Real aTwistBefore = Twist();
1088
1089   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1090
1091   myCamera->SetDirection (gp_Dir (Vx, Vy, Vz).Reversed());
1092
1093   SetTwist(aTwistBefore);
1094
1095   View()->AutoZFit();
1096
1097   SetImmediateUpdate (wasUpdateEnabled);
1098
1099   ImmediateUpdate();
1100 }
1101
1102 //=============================================================================
1103 //function : SetProj
1104 //purpose  :
1105 //=============================================================================
1106 void V3d_View::SetProj( const V3d_TypeOfOrientation Orientation )
1107 {
1108   Standard_Real Xpn=0;
1109   Standard_Real Ypn=0;
1110   Standard_Real Zpn=0;
1111
1112   switch (Orientation) {
1113   case V3d_Zpos :
1114     Ypn = 1.;
1115     break;
1116   case V3d_Zneg :
1117     Ypn = -1.;
1118     break;
1119   default:
1120     Zpn = 1.;
1121   }
1122
1123   const Graphic3d_Vector& aBck = V3d::GetProjAxis (Orientation);
1124
1125   // retain camera panning from origin when switching projection
1126   gp_Pnt anOriginVCS = myCamera->ConvertWorld2View (gp::Origin());
1127   Standard_Real aPanX = anOriginVCS.X();
1128   Standard_Real aPanY = anOriginVCS.Y();
1129
1130   myCamera->SetCenter (gp_Pnt (0, 0, 0));
1131   myCamera->SetDirection (gp_Dir (aBck.X(), aBck.Y(), aBck.Z()).Reversed());
1132   myCamera->SetUp (gp_Dir (Xpn, Ypn, Zpn));
1133   myCamera->OrthogonalizeUp();
1134
1135   Panning (aPanX, aPanY);
1136
1137   View()->AutoZFit();
1138
1139   ImmediateUpdate();
1140 }
1141
1142 //=============================================================================
1143 //function : SetAt
1144 //purpose  :
1145 //=============================================================================
1146 void V3d_View::SetAt(const Standard_Real X,const Standard_Real Y,const Standard_Real Z)
1147 {
1148   Standard_Real aTwistBefore = Twist();
1149
1150   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1151
1152   myCamera->SetCenter (gp_Pnt (X, Y, Z));
1153
1154   SetTwist (aTwistBefore);
1155
1156   View()->AutoZFit();
1157
1158   SetImmediateUpdate (wasUpdateEnabled);
1159
1160   ImmediateUpdate();
1161 }
1162
1163 //=============================================================================
1164 //function : SetUp
1165 //purpose  :
1166 //=============================================================================
1167 void V3d_View::SetUp(const Standard_Real Vx,const Standard_Real Vy,const Standard_Real Vz)
1168 {
1169   Standard_Boolean TheStatus ;
1170   V3d_BadValue_Raise_if( Sqrt(Vx*Vx + Vy*Vy + Vz*Vz) <= 0. ,
1171     "V3d_View::SetUp, nullUp vector");
1172
1173   gp_Dir aReferencePlane (myCamera->Direction().Reversed());
1174   gp_Dir anUp (Vx, Vy, Vz);
1175
1176   TheStatus = ScreenAxis(aReferencePlane,anUp,
1177     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1178   if( !TheStatus ) {
1179     anUp = gp_Dir (0.0, 0.0, 1.0);
1180     TheStatus = ScreenAxis(aReferencePlane,anUp,
1181       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1182   }
1183   if( !TheStatus ) {
1184     anUp = gp_Dir (0.0, 1.0, 0.0);
1185     TheStatus = ScreenAxis(aReferencePlane,anUp,
1186       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1187   }
1188   if( !TheStatus ) {
1189     anUp = gp_Dir (1.0, 0.0, 0.0);
1190     TheStatus = ScreenAxis(aReferencePlane,anUp,
1191       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1192   }
1193   V3d_BadValue_Raise_if( !TheStatus,"V3d_View::Setup, alignment of Eye,At,Up");
1194
1195   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
1196   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
1197
1198   myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
1199
1200   View()->AutoZFit();
1201
1202   ImmediateUpdate();
1203 }
1204
1205 //=============================================================================
1206 //function : SetUp
1207 //purpose  :
1208 //=============================================================================
1209 void V3d_View::SetUp( const V3d_TypeOfOrientation Orientation )
1210 {
1211   Standard_Boolean TheStatus ;
1212
1213   gp_Dir aReferencePlane (myCamera->Direction().Reversed());
1214   gp_Dir anUp;
1215
1216   const Graphic3d_Vector& aViewReferenceUp = V3d::GetProjAxis(Orientation) ;
1217   anUp = gp_Dir (aViewReferenceUp.X(), aViewReferenceUp.Y(), aViewReferenceUp.Z());
1218
1219   TheStatus = ScreenAxis(aReferencePlane,anUp,
1220     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1221   if( !TheStatus ) {
1222     anUp = gp_Dir (0.,0.,1.);
1223     TheStatus = ScreenAxis(aReferencePlane,anUp,
1224       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1225   }
1226   if( !TheStatus ) {
1227     anUp = gp_Dir (0.,1.,0.);
1228     TheStatus = ScreenAxis(aReferencePlane,anUp,
1229       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1230   }
1231   if( !TheStatus ) {
1232     anUp = gp_Dir (1.,0.,0.);
1233     TheStatus = ScreenAxis(aReferencePlane,anUp,
1234       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1235   }
1236   V3d_BadValue_Raise_if( !TheStatus, "V3d_View::SetUp, alignment of Eye,At,Up");
1237
1238   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
1239   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
1240
1241   myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
1242
1243   View()->AutoZFit();
1244
1245   ImmediateUpdate();
1246 }
1247
1248 //=============================================================================
1249 //function : SetViewOrientationDefault
1250 //purpose  :
1251 //=============================================================================
1252 void V3d_View::SetViewOrientationDefault()
1253 {
1254   MyView->SetViewOrientationDefault() ;
1255
1256   ImmediateUpdate();
1257 }
1258
1259 //=============================================================================
1260 //function : ResetViewOrientation
1261 //purpose  :
1262 //=============================================================================
1263 void V3d_View::ResetViewOrientation()
1264 {
1265   MyView->ViewOrientationReset() ;
1266
1267   ImmediateUpdate();
1268 }
1269
1270 //=============================================================================
1271 //function : Reset
1272 //purpose  :
1273 //=============================================================================
1274 void V3d_View::Reset( const Standard_Boolean update )
1275 {
1276   Handle(Graphic3d_Camera) aDefaultCamera = MyView->DefaultCamera();
1277
1278   if (!aDefaultCamera.IsNull())
1279   {
1280     myCamera->CopyMappingData (aDefaultCamera);
1281     myCamera->CopyOrientationData (aDefaultCamera);
1282
1283     View()->AutoZFit();
1284   }
1285
1286   SwitchSetFront = Standard_False;
1287
1288   if( myImmediateUpdate || update ) Update();
1289 }
1290
1291 //=======================================================================
1292 //function : SetCenter
1293 //purpose  :
1294 //=======================================================================
1295 void V3d_View::SetCenter (const Standard_Integer theXp,
1296                           const Standard_Integer theYp)
1297 {
1298   Standard_Real aXv, aYv;
1299   Convert (theXp, theYp, aXv, aYv);
1300   Translate (myCamera, aXv, aYv);
1301
1302   ImmediateUpdate();
1303 }
1304
1305 //=============================================================================
1306 //function : SetSize
1307 //purpose  :
1308 //=============================================================================
1309 void V3d_View::SetSize (const Standard_Real theSize)
1310 {
1311   V3d_BadValue_Raise_if (theSize <= 0.0, "V3d_View::SetSize, Window Size is NULL");
1312
1313   myCamera->SetScale (myCamera->Aspect() >= 1.0 ? theSize / myCamera->Aspect() : theSize);
1314
1315   View()->AutoZFit();
1316
1317   ImmediateUpdate();
1318 }
1319
1320 //=============================================================================
1321 //function : SetZSize
1322 //purpose  :
1323 //=============================================================================
1324 void V3d_View::SetZSize(const Standard_Real Size)
1325 {
1326   Standard_Real Zmax = Size/2.;
1327
1328   Standard_Real aDistance = myCamera->Distance();
1329
1330   if( Size <= 0. ) {
1331     Zmax = aDistance;
1332   }
1333
1334   Standard_Real Front = MyViewContext.ZClippingFrontPlane();
1335   Standard_Real Back  = MyViewContext.ZClippingBackPlane();
1336
1337   // ShortReal precision factor used to add meaningful tolerance to
1338   // ZNear, ZFar values in order to avoid equality after type conversion
1339   // to ShortReal matrices type.
1340   const Standard_Real aPrecision = 1.0 / Pow (10.0, ShortRealDigits() - 1);
1341
1342   Standard_Real aZFar  =  Zmax  + aDistance * 2.0;
1343   Standard_Real aZNear = -Zmax  + aDistance;
1344   aZNear              -= Abs (aZNear) * aPrecision;
1345   aZFar               += Abs (aZFar)  * aPrecision;
1346
1347   if (!myCamera->IsOrthographic())
1348   {
1349     if (aZFar < aPrecision)
1350     {
1351       // Invalid case when both values are negative
1352       aZNear = aPrecision;
1353       aZFar  = aPrecision * 2.0;
1354     }
1355     else if (aZNear < Abs (aZFar) * aPrecision)
1356     {
1357       // Z is less than 0.0, try to fix it using any appropriate z-scale
1358       aZNear = Abs (aZFar) * aPrecision;
1359     }
1360   }
1361
1362   // If range is too small
1363   if (aZFar < (aZNear + Abs (aZFar) * aPrecision))
1364   {
1365     aZFar = aZNear + Abs (aZFar) * aPrecision;
1366   }
1367
1368   myCamera->SetZRange (aZNear, aZFar);
1369
1370   if (MyViewContext.FrontZClippingIsOn()  ||
1371       MyViewContext.BackZClippingIsOn())
1372   {
1373     MyViewContext.SetZClippingFrontPlane (Front);
1374     MyViewContext.SetZClippingBackPlane (Back);
1375     MyView->SetContext (MyViewContext);
1376   }
1377 }
1378
1379 //=============================================================================
1380 //function : SetZoom
1381 //purpose  :
1382 //=============================================================================
1383 void V3d_View::SetZoom(const Standard_Real Coef,const Standard_Boolean Start)
1384 {
1385   V3d_BadValue_Raise_if( Coef <= 0.,"V3d_View::SetZoom, bad coefficient");
1386
1387   if (Start)
1388   {
1389     myCamStartOpEye    = myCamera->Eye();
1390     myCamStartOpCenter = myCamera->Center();
1391   }
1392
1393   Standard_Real aViewWidth  = myCamera->ViewDimensions().X();
1394   Standard_Real aViewHeight = myCamera->ViewDimensions().Y();
1395
1396   // ensure that zoom will not be too small or too big
1397   Standard_Real coef = Coef;
1398   if (aViewWidth < coef * Precision::Confusion())
1399   {
1400     coef = aViewWidth / Precision::Confusion();
1401   }
1402   else if (aViewWidth > coef * 1e12)
1403   {
1404     coef = aViewWidth / 1e12;
1405   }
1406   if (aViewHeight < coef * Precision::Confusion())
1407   {
1408     coef = aViewHeight / Precision::Confusion();
1409   }
1410   else if (aViewHeight > coef * 1e12)
1411   {
1412     coef = aViewHeight / 1e12;
1413   }
1414
1415   myCamera->SetEye (myCamStartOpEye);
1416   myCamera->SetCenter (myCamStartOpCenter);
1417   myCamera->SetScale (myCamera->Scale() / Coef);
1418   View()->AutoZFit();
1419
1420   ImmediateUpdate();
1421 }
1422
1423 //=============================================================================
1424 //function : SetScale
1425 //purpose  :
1426 //=============================================================================
1427 void V3d_View::SetScale( const Standard_Real Coef )
1428 {
1429   V3d_BadValue_Raise_if( Coef <= 0. ,"V3d_View::SetScale, bad coefficient");
1430
1431   Handle(Graphic3d_Camera) aDefaultCamera = MyView->DefaultCamera();
1432
1433   // Strange behavior for the sake of compatibility.
1434   if (!aDefaultCamera.IsNull())
1435   {
1436     myCamera->SetAspect (aDefaultCamera->Aspect());
1437     Standard_Real aDefaultScale = aDefaultCamera->Scale();
1438     myCamera->SetScale (aDefaultScale / Coef);
1439   } 
1440   else
1441   {
1442     myCamera->SetScale (myCamera->Scale() / Coef);
1443   }
1444
1445   View()->AutoZFit();
1446
1447   ImmediateUpdate();
1448 }
1449
1450 //=============================================================================
1451 //function : SetAxialScale
1452 //purpose  :
1453 //=============================================================================
1454 void V3d_View::SetAxialScale( const Standard_Real Sx, const Standard_Real Sy, const Standard_Real Sz )
1455 {
1456   V3d_BadValue_Raise_if( Sx <= 0. || Sy <= 0. || Sz <= 0.,"V3d_View::SetAxialScale, bad coefficient");
1457
1458   myCamera->SetAxialScale (gp_XYZ (Sx, Sy, Sz));
1459   View()->AutoZFit();
1460 }
1461
1462 //=============================================================================
1463 //function : FitAll
1464 //purpose  :
1465 //=============================================================================
1466 void V3d_View::FitAll (const Quantity_Coefficient theMargin, const Standard_Boolean theToUpdate)
1467 {
1468   FitAll (MyView->MinMaxValues(), theMargin, theToUpdate);
1469 }
1470
1471 //=============================================================================
1472 //function : FitAll
1473 //purpose  :
1474 //=============================================================================
1475 void V3d_View::FitAll (const Bnd_Box& theBox, const Quantity_Coefficient theMargin, const Standard_Boolean theToUpdate)
1476 {
1477   Standard_ASSERT_RAISE(theMargin >= 0.0 && theMargin < 1.0, "Invalid margin coefficient");
1478
1479   if (MyView->NumberOfDisplayedStructures() == 0)
1480   {
1481     return;
1482   }
1483
1484   if (!FitMinMax (myCamera, theBox, theMargin, 10.0 * Precision::Confusion()))
1485   {
1486     return;
1487   }
1488
1489   View()->AutoZFit();
1490
1491   if (myImmediateUpdate || theToUpdate)
1492   {
1493     Update();
1494   }
1495 }
1496
1497 //=============================================================================
1498 //function : DepthFitAll
1499 //purpose  :
1500 //=============================================================================
1501 void V3d_View::DepthFitAll(const Quantity_Coefficient Aspect,
1502                            const Quantity_Coefficient Margin)
1503 {
1504   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,U,V,W,U1,V1,W1 ;
1505   Standard_Real Umin,Vmin,Wmin,Umax,Vmax,Wmax ;
1506   Standard_Real Dx,Dy,Dz,Size;
1507
1508   Standard_Integer Nstruct = MyView->NumberOfDisplayedStructures() ;
1509
1510   if((Nstruct <= 0) || (Aspect < 0.) || (Margin < 0.) || (Margin > 1.)) {
1511     ImmediateUpdate();
1512     return ;
1513   }
1514
1515   Bnd_Box aBox = MyView->MinMaxValues();
1516   if (aBox.IsVoid())
1517   {
1518     ImmediateUpdate();
1519     return ;
1520   }
1521     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
1522     MyView->Projects(Xmin,Ymin,Zmin,U,V,W) ;
1523     MyView->Projects(Xmax,Ymax,Zmax,U1,V1,W1) ;
1524     Umin = Min(U,U1) ; Umax = Max(U,U1) ;
1525     Vmin = Min(V,V1) ; Vmax = Max(V,V1) ;
1526     Wmin = Min(W,W1) ; Wmax = Max(W,W1) ;
1527     MyView->Projects(Xmin,Ymin,Zmax,U,V,W) ;
1528     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1529     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1530     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1531     MyView->Projects(Xmax,Ymin,Zmax,U,V,W) ;
1532     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1533     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1534     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1535     MyView->Projects(Xmax,Ymin,Zmin,U,V,W) ;
1536     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1537     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1538     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1539     MyView->Projects(Xmax,Ymax,Zmin,U,V,W) ;
1540     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1541     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1542     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1543     MyView->Projects(Xmin,Ymax,Zmax,U,V,W) ;
1544     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1545     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1546     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1547     MyView->Projects(Xmin,Ymax,Zmin,U,V,W) ;
1548     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1549     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1550     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1551
1552     // Adjust Z size
1553     Wmax = Max(Abs(Wmin),Abs(Wmax)) ;
1554     Dz = 2.*Wmax + Margin * Wmax;
1555
1556     // Compute depth value
1557     Dx = Abs(Umax - Umin) ; Dy = Abs(Vmax - Vmin) ; // Dz = Abs(Wmax - Wmin);
1558     Dx += Margin * Dx; Dy += Margin * Dy;
1559     Size = Sqrt(Dx*Dx + Dy*Dy + Dz*Dz);
1560     if( Size > 0. ) {
1561       SetZSize(Size) ;
1562       SetDepth( Aspect * Size / 2.);
1563     }
1564
1565     ImmediateUpdate();
1566 }
1567
1568 //=============================================================================
1569 //function : FitAll
1570 //purpose  :
1571 //=============================================================================
1572 void V3d_View::FitAll(const Standard_Real theMinXv,
1573                       const Standard_Real theMinYv,
1574                       const Standard_Real theMaxXv,
1575                       const Standard_Real theMaxYv)
1576 {
1577   FitAll (MyWindow, theMinXv, theMinYv, theMaxXv, theMaxYv);
1578 }
1579
1580 //=============================================================================
1581 //function : WindowFitAll
1582 //purpose  :
1583 //=============================================================================
1584 void V3d_View::WindowFitAll(const Standard_Integer Xmin,
1585                             const Standard_Integer Ymin,
1586                             const Standard_Integer Xmax,
1587                             const Standard_Integer Ymax)
1588 {
1589   WindowFit(Xmin,Ymin,Xmax,Ymax);
1590 }
1591
1592 //=======================================================================
1593 //function : WindowFit
1594 //purpose  :
1595 //=======================================================================
1596 void V3d_View::WindowFit (const Standard_Integer theMinXp,
1597                           const Standard_Integer theMinYp,
1598                           const Standard_Integer theMaxXp,
1599                           const Standard_Integer theMaxYp)
1600 {
1601   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1602
1603   if (!myCamera->IsOrthographic())
1604   {
1605     // normalize view coordinates
1606     Standard_Integer aWinWidth, aWinHeight;
1607     MyWindow->Size (aWinWidth, aWinHeight);
1608
1609     // z coordinate of camera center
1610     Standard_Real aDepth = myCamera->Project (myCamera->Center()).Z();
1611
1612     // camera projection coordinate are in NDC which are normalized [-1, 1]
1613     Standard_Real aUMin = (2.0 / aWinWidth) * theMinXp  - 1.0;
1614     Standard_Real aUMax = (2.0 / aWinWidth) * theMaxXp  - 1.0;
1615     Standard_Real aVMin = (2.0 / aWinHeight) * theMinYp - 1.0;
1616     Standard_Real aVMax = (2.0 / aWinHeight) * theMaxYp - 1.0;
1617
1618     // compute camera panning
1619     gp_Pnt aScreenCenter (0.0, 0.0, aDepth);
1620     gp_Pnt aFitCenter ((aUMin + aUMax) * 0.5, (aVMin + aVMax) * 0.5, aDepth);
1621     gp_Pnt aPanTo = myCamera->ConvertProj2View (aFitCenter);
1622     gp_Pnt aPanFrom = myCamera->ConvertProj2View (aScreenCenter);
1623     gp_Vec aPanVec (aPanFrom, aPanTo);
1624
1625     // compute section size
1626     gp_Pnt aFitTopRight (aUMax, aVMax, aDepth);
1627     gp_Pnt aFitBotLeft (aUMin, aVMin, aDepth);
1628     gp_Pnt aViewBotLeft = myCamera->ConvertProj2View (aFitBotLeft);
1629     gp_Pnt aViewTopRight = myCamera->ConvertProj2View (aFitTopRight);
1630
1631     Standard_Real aUSize = aViewTopRight.X() - aViewBotLeft.X();
1632     Standard_Real aVSize = aViewTopRight.Y() - aViewBotLeft.Y();
1633
1634     Translate (myCamera, aPanVec.X(), -aPanVec.Y());
1635     Scale (myCamera, aUSize, aVSize);
1636     View()->AutoZFit();
1637   }
1638   else
1639   {
1640     Standard_Real aX1, aY1, aX2, aY2;
1641     Convert (theMinXp, theMinYp, aX1, aY1);
1642     Convert (theMaxXp, theMaxYp, aX2, aY2);
1643     FitAll (aX1, aY1, aX2, aY2);
1644   }
1645
1646   SetImmediateUpdate (wasUpdateEnabled);
1647
1648   ImmediateUpdate();
1649 }
1650
1651 //=======================================================================
1652 //function : SetViewMappingDefault
1653 //purpose  :
1654 //=======================================================================
1655 void V3d_View::SetViewMappingDefault()
1656 {
1657   MyView->SetViewMappingDefault();
1658
1659   ImmediateUpdate();
1660 }
1661
1662 //=======================================================================
1663 //function : ResetViewMapping
1664 //purpose  :
1665 //=======================================================================
1666 void V3d_View::ResetViewMapping()
1667 {
1668   MyView->ViewMappingReset();
1669
1670   Update();
1671 }
1672
1673 //=======================================================================
1674 //function : ConvertToGrid
1675 //purpose  :
1676 //=======================================================================
1677 void V3d_View::ConvertToGrid(const Standard_Integer Xp,
1678                              const Standard_Integer Yp,
1679                              Standard_Real& Xg,
1680                              Standard_Real& Yg,
1681                              Standard_Real& Zg) const
1682 {
1683   Graphic3d_Vertex aVrp;
1684   Standard_Real anX, anY, aZ;
1685   Convert (Xp, Yp, anX, anY, aZ);
1686   aVrp.SetCoord (anX, anY, aZ);
1687
1688   if( MyViewer->Grid()->IsActive() ) {
1689     Graphic3d_Vertex aNewVrp = Compute (aVrp) ;
1690     aNewVrp.Coord (Xg,Yg,Zg) ;
1691   } else
1692     aVrp.Coord (Xg,Yg,Zg) ;
1693 }
1694
1695 //=======================================================================
1696 //function : ConvertToGrid
1697 //purpose  :
1698 //=======================================================================
1699 void V3d_View::ConvertToGrid(const Standard_Real X,
1700                              const Standard_Real Y,
1701                              const Standard_Real Z,
1702                              Standard_Real& Xg,
1703                              Standard_Real& Yg,
1704                              Standard_Real& Zg) const
1705 {
1706   if( MyViewer->Grid()->IsActive() ) {
1707     Graphic3d_Vertex aVrp (X,Y,Z) ;
1708     Graphic3d_Vertex aNewVrp = Compute (aVrp) ;
1709     aNewVrp.Coord(Xg,Yg,Zg) ;
1710   } else {
1711     Xg = X; Yg = Y; Zg = Z;
1712   }
1713 }
1714
1715 //=======================================================================
1716 //function : Convert
1717 //purpose  :
1718 //=======================================================================
1719 Standard_Real V3d_View::Convert(const Standard_Integer Vp) const
1720 {
1721   Standard_Integer aDxw, aDyw ;
1722
1723   V3d_UnMapped_Raise_if (!MyView->IsDefined(), "view has no window");
1724
1725   MyWindow->Size (aDxw, aDyw);
1726   Standard_Real aValue;
1727
1728   gp_Pnt aViewDims = myCamera->ViewDimensions();
1729   aValue = aViewDims.X() * (Standard_Real)Vp / (Standard_Real)aDxw;
1730
1731   return aValue;
1732 }
1733
1734 //=======================================================================
1735 //function : Convert
1736 //purpose  :
1737 //=======================================================================
1738 void V3d_View::Convert(const Standard_Integer Xp,
1739                        const Standard_Integer Yp,
1740                        Standard_Real& Xv,
1741                        Standard_Real& Yv) const
1742 {
1743   Standard_Integer aDxw, aDyw;
1744
1745   V3d_UnMapped_Raise_if (!MyView->IsDefined(), "view has no window");
1746
1747   MyWindow->Size (aDxw, aDyw);
1748
1749   gp_Pnt aPoint (Xp * 2.0 / aDxw - 1.0, (aDyw - Yp) * 2.0 / aDyw - 1.0, 0.0);
1750   aPoint = myCamera->ConvertProj2View (aPoint);
1751
1752   Xv = aPoint.X();
1753   Yv = aPoint.Y();
1754 }
1755
1756 //=======================================================================
1757 //function : Convert
1758 //purpose  :
1759 //=======================================================================
1760 Standard_Integer V3d_View::Convert(const Standard_Real Vv) const
1761 {
1762   V3d_UnMapped_Raise_if (!MyView->IsDefined(), "view has no window");
1763
1764   Standard_Integer aDxw, aDyw;
1765   MyWindow->Size (aDxw, aDyw);
1766
1767   gp_Pnt aViewDims = myCamera->ViewDimensions();
1768   Standard_Integer aValue = RealToInt (aDxw * Vv / (aViewDims.X()));
1769
1770   return aValue;
1771 }
1772
1773 //=======================================================================
1774 //function : Convert
1775 //purpose  :
1776 //=======================================================================
1777 void V3d_View::Convert(const Standard_Real Xv,
1778                        const Standard_Real Yv,
1779                        Standard_Integer& Xp,
1780                        Standard_Integer& Yp) const
1781 {
1782   V3d_UnMapped_Raise_if (!MyView->IsDefined(), "view has no window");
1783
1784   Standard_Integer aDxw, aDyw;
1785   MyWindow->Size (aDxw, aDyw);
1786
1787   gp_Pnt aPoint (Xv, Yv, 0.0);
1788   aPoint = myCamera->ConvertView2Proj (aPoint);
1789   aPoint = gp_Pnt ((aPoint.X() + 1.0) * aDxw / 2.0, aDyw - (aPoint.Y() + 1.0) * aDyw / 2.0, 0.0);
1790
1791   Xp = RealToInt (aPoint.X());
1792   Yp = RealToInt (aPoint.Y());
1793 }
1794
1795 //=======================================================================
1796 //function : Convert
1797 //purpose  :
1798 //=======================================================================
1799 void V3d_View::Convert(const Standard_Integer Xp,
1800                        const Standard_Integer Yp,
1801                        Standard_Real& X,
1802                        Standard_Real& Y,
1803                        Standard_Real& Z) const
1804 {
1805   V3d_UnMapped_Raise_if (!MyView->IsDefined(), "view has no window");
1806   Standard_Integer aHeight, aWidth;
1807   MyWindow->Size (aWidth, aHeight);
1808
1809   Standard_Real anX = 2.0 * Xp / aWidth - 1.0;
1810   Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0;
1811   Standard_Real  aZ = 2.0 * 0.0 - 1.0;
1812
1813   gp_Pnt aResult = myCamera->UnProject (gp_Pnt (anX, anY, aZ));
1814
1815   X = aResult.X();
1816   Y = aResult.Y();
1817   Z = aResult.Z();
1818 }
1819
1820 //=======================================================================
1821 //function : ConvertWithProj
1822 //purpose  :
1823 //=======================================================================
1824 void V3d_View::ConvertWithProj(const Standard_Integer Xp,
1825                                const Standard_Integer Yp,
1826                                Standard_Real& X,
1827                                Standard_Real& Y,
1828                                Standard_Real& Z,
1829                                Standard_Real& Dx,
1830                                Standard_Real& Dy,
1831                                Standard_Real& Dz) const
1832 {
1833   V3d_UnMapped_Raise_if( !MyView->IsDefined(), "view has no window");
1834   Standard_Integer aHeight, aWidth;
1835   MyWindow->Size (aWidth, aHeight);
1836
1837   Standard_Real anX = 2.0 * Xp / aWidth - 1.0;
1838   Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0;
1839   Standard_Real  aZ = 2.0 * 0.0 - 1.0;
1840
1841   gp_Pnt aResult = myCamera->UnProject (gp_Pnt (anX, anY, aZ));
1842
1843   X = aResult.X();
1844   Y = aResult.Y();
1845   Z = aResult.Z();
1846
1847   Graphic3d_Vertex aVrp;
1848   aVrp.SetCoord (X, Y, Z);
1849
1850   aResult = myCamera->UnProject (gp_Pnt (anX, anY, aZ - 10.0));
1851
1852   Graphic3d_Vec3d aNormDir;
1853   aNormDir.x() = X - aResult.X();
1854   aNormDir.y() = Y - aResult.Y();
1855   aNormDir.z() = Z - aResult.Z();
1856   aNormDir.Normalize();
1857
1858   Dx = aNormDir.x();
1859   Dy = aNormDir.y();
1860   Dz = aNormDir.z();
1861 }
1862
1863 //=======================================================================
1864 //function : Convert
1865 //purpose  :
1866 //=======================================================================
1867 void V3d_View::Convert(const Standard_Real X,
1868                        const Standard_Real Y,
1869                        const Standard_Real Z,
1870                        Standard_Integer& Xp,
1871                        Standard_Integer& Yp) const
1872 {
1873   V3d_UnMapped_Raise_if( !MyView->IsDefined(), "view has no window");
1874   Standard_Integer aHeight, aWidth;
1875   MyWindow->Size (aWidth, aHeight);
1876
1877   gp_Pnt aPoint = myCamera->Project (gp_Pnt (X, Y, Z));
1878
1879   Xp = RealToInt ((aPoint.X() + 1) * 0.5 * aWidth);
1880   Yp = RealToInt (aHeight - 1 - (aPoint.Y() + 1) * 0.5 * aHeight);
1881 }
1882
1883 //=======================================================================
1884 //function : Project
1885 //purpose  :
1886 //=======================================================================
1887 void V3d_View::Project(const Standard_Real X,
1888                        const Standard_Real Y,
1889                        const Standard_Real Z,
1890                        Standard_Real &Xp,
1891                        Standard_Real &Yp) const
1892 {
1893   Standard_Real Zp;
1894   MyView->Projects (X, Y, Z, Xp, Yp, Zp);
1895 }
1896
1897 //=======================================================================
1898 //function : BackgroundColor
1899 //purpose  :
1900 //=======================================================================
1901 void V3d_View::BackgroundColor(const Quantity_TypeOfColor Type,
1902                                Standard_Real& V1,
1903                                Standard_Real& V2,
1904                                Standard_Real& V3) const
1905 {
1906   Quantity_Color C = BackgroundColor() ;
1907   C.Values(V1,V2,V3,Type) ;
1908 }
1909
1910 //=======================================================================
1911 //function : BackgroundColor
1912 //purpose  :
1913 //=======================================================================
1914 Quantity_Color V3d_View::BackgroundColor() const
1915 {
1916   return MyBackground.Color() ;
1917 }
1918
1919 //=======================================================================
1920 //function : GradientBackgroundColors
1921 //purpose  :
1922 //=======================================================================
1923 void V3d_View::GradientBackgroundColors(Quantity_Color& Color1,Quantity_Color& Color2) const
1924 {
1925   MyGradientBackground.Colors(Color1, Color2);
1926 }
1927
1928 //=======================================================================
1929 //function : GradientBackground
1930 //purpose  :
1931 //=======================================================================
1932 Aspect_GradientBackground V3d_View::GradientBackground() const
1933 {
1934    return MyGradientBackground;
1935 }
1936
1937 //=======================================================================
1938 //function : Scale
1939 //purpose  :
1940 //=======================================================================
1941 Standard_Real V3d_View::Scale() const
1942 {
1943   Handle(Graphic3d_Camera) aDefaultCamera = MyView->DefaultCamera();
1944
1945   Standard_Real aCameraScale;
1946
1947   // Strange behavior for the sake of compatibility.
1948   if (!aDefaultCamera.IsNull())
1949   {
1950     Standard_Real aDefaultScale = aDefaultCamera->Scale();
1951     aCameraScale = aDefaultScale / myCamera->Scale();
1952   } 
1953   else
1954   {
1955     aCameraScale = myCamera->Scale();
1956   }
1957
1958   return aCameraScale;
1959 }
1960
1961 //=======================================================================
1962 //function : AxialScale
1963 //purpose  :
1964 //=======================================================================
1965 void V3d_View::AxialScale(Standard_Real& Sx, Standard_Real& Sy, Standard_Real& Sz) const
1966 {
1967   gp_Pnt anAxialScale = myCamera->AxialScale();
1968   Sx = anAxialScale.X();
1969   Sy = anAxialScale.Y();
1970   Sz = anAxialScale.Z();
1971 }
1972
1973 //=======================================================================
1974 //function : Size
1975 //purpose  :
1976 //=======================================================================
1977 void V3d_View::Size(Standard_Real& Width, Standard_Real& Height) const
1978 {
1979   gp_Pnt aViewDims = myCamera->ViewDimensions();
1980
1981   Width = aViewDims.X();
1982   Height = aViewDims.Y();
1983 }
1984
1985 //=======================================================================
1986 //function : ZSize
1987 //purpose  :
1988 //=======================================================================
1989 Standard_Real V3d_View::ZSize() const
1990 {
1991   gp_Pnt aViewDims = myCamera->ViewDimensions();
1992
1993   return aViewDims.Z();
1994 }
1995
1996 //=======================================================================
1997 //function : MinMax
1998 //purpose  :
1999 //=======================================================================
2000 Standard_Integer V3d_View::MinMax(Standard_Real& Umin,
2001                                   Standard_Real& Vmin,
2002                                   Standard_Real& Umax,
2003                                   Standard_Real& Vmax) const
2004 {
2005   Standard_Real Wmin,Wmax,U,V,W ;
2006   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax ;
2007   // CAL 6/11/98
2008   Standard_Integer Nstruct = MyView->NumberOfDisplayedStructures() ;
2009
2010   if( Nstruct ) {
2011     Bnd_Box aBox = MyView->MinMaxValues();
2012     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
2013     MyView->Projects(Xmin,Ymin,Zmin,Umin,Vmin,Wmin) ;
2014     MyView->Projects(Xmax,Ymax,Zmax,Umax,Vmax,Wmax) ;
2015     MyView->Projects(Xmin,Ymin,Zmax,U,V,W) ;
2016     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2017     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2018     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2019     MyView->Projects(Xmax,Ymin,Zmax,U,V,W) ;
2020     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2021     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2022     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2023     MyView->Projects(Xmax,Ymin,Zmin,U,V,W) ;
2024     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2025     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2026     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2027     MyView->Projects(Xmax,Ymax,Zmin,U,V,W) ;
2028     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2029     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2030     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2031     MyView->Projects(Xmin,Ymax,Zmax,U,V,W) ;
2032     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2033     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2034     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2035     MyView->Projects(Xmin,Ymax,Zmin,U,V,W) ;
2036     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2037     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2038     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2039   }
2040   return Nstruct ;
2041 }
2042
2043 //=======================================================================
2044 //function : MinMax
2045 //purpose  :
2046 //=======================================================================
2047 Standard_Integer V3d_View::MinMax(Standard_Real& Xmin,
2048                                   Standard_Real& Ymin,
2049                                   Standard_Real& Zmin,
2050                                   Standard_Real& Xmax,
2051                                   Standard_Real& Ymax,
2052                                   Standard_Real& Zmax) const
2053 {
2054   // CAL 6/11/98
2055   // Standard_Integer Nstruct = (MyView->DisplayedStructures())->Extent() ;
2056   Standard_Integer Nstruct = MyView->NumberOfDisplayedStructures() ;
2057
2058   if( Nstruct ) {
2059     Bnd_Box aBox = MyView->MinMaxValues();
2060     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
2061   }
2062   return Nstruct ;
2063 }
2064
2065 //=======================================================================
2066 //function : Gravity
2067 //purpose  :
2068 //=======================================================================
2069 void V3d_View::Gravity (Standard_Real& theX,
2070                         Standard_Real& theY,
2071                         Standard_Real& theZ) const
2072 {
2073   Graphic3d_MapOfStructure aSetOfStructures;
2074   MyView->DisplayedStructures (aSetOfStructures);
2075
2076   Standard_Boolean hasSelection = Standard_False;
2077   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
2078        aStructIter.More(); aStructIter.Next())
2079   {
2080     if (aStructIter.Key()->IsHighlighted()
2081      && aStructIter.Key()->IsVisible())
2082     {
2083       hasSelection = Standard_True;
2084       break;
2085     }
2086   }
2087
2088   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2089   Standard_Integer aNbPoints = 0;
2090   gp_XYZ aResult (0.0, 0.0, 0.0);
2091   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
2092        aStructIter.More(); aStructIter.Next())
2093   {
2094     const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
2095     if (!aStruct->IsVisible()
2096     || (hasSelection && !aStruct->IsHighlighted())
2097     ||  aStruct->IsEmpty())
2098     {
2099       continue;
2100     }
2101
2102     Bnd_Box aBox = aStruct->MinMaxValues();
2103     if (aBox.IsVoid() || aStruct->IsInfinite())
2104     {
2105       continue;
2106     }
2107
2108     // use camera projection to find gravity point
2109     aBox.Get (Xmin, Ymin, Zmin,
2110               Xmax, Ymax, Zmax);
2111     gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
2112     {
2113       gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
2114       gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
2115       gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
2116       gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
2117     };
2118
2119     for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
2120     {
2121       const gp_Pnt& aBndPnt    = aPnts[aPntIt];
2122       const gp_Pnt  aProjected = myCamera->Project (aBndPnt);
2123       if (Abs (aProjected.X()) <= 1.0
2124        && Abs (aProjected.Y()) <= 1.0)
2125       {
2126         aResult += aBndPnt.XYZ();
2127         ++aNbPoints;
2128       }
2129     }
2130   }
2131
2132   if (aNbPoints == 0)
2133   {
2134     for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
2135          aStructIter.More(); aStructIter.Next())
2136     {
2137       const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
2138       if (aStruct->IsEmpty())
2139       {
2140         continue;
2141       }
2142
2143       Bnd_Box aBox = aStruct->MinMaxValues();
2144       if (aBox.IsVoid() || aStruct->IsInfinite())
2145       {
2146         continue;
2147       }
2148
2149       aBox.Get (Xmin, Ymin, Zmin,
2150                 Xmax, Ymax, Zmax);
2151       gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
2152       {
2153         gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
2154         gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
2155         gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
2156         gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
2157       };
2158
2159       for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
2160       {
2161         const gp_Pnt& aBndPnt = aPnts[aPntIt];
2162         aResult += aBndPnt.XYZ();
2163         ++aNbPoints;
2164       }
2165     }
2166   }
2167
2168   if (aNbPoints > 0)
2169   {
2170     aResult /= aNbPoints;
2171   }
2172   theX = aResult.X();
2173   theY = aResult.Y();
2174   theZ = aResult.Z();
2175 }
2176
2177 //=======================================================================
2178 //function : Eye
2179 //purpose  :
2180 //=======================================================================
2181 void V3d_View::Eye(Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const
2182 {
2183   gp_Pnt aCameraEye = myCamera->Eye();
2184   X = aCameraEye.X();
2185   Y = aCameraEye.Y();
2186   Z = aCameraEye.Z();
2187 }
2188
2189 //=============================================================================
2190 //function : FocalReferencePoint
2191 //purpose  :
2192 //=============================================================================
2193 void V3d_View::FocalReferencePoint(Standard_Real& X, Standard_Real& Y,Standard_Real& Z) const
2194 {
2195   Eye (X,Y,Z);
2196 }
2197
2198 //=============================================================================
2199 //function : ProjReferenceAxe
2200 //purpose  :
2201 //=============================================================================
2202 void V3d_View::ProjReferenceAxe(const Standard_Integer Xpix,
2203                                 const Standard_Integer Ypix,
2204                                 Standard_Real& XP,
2205                                 Standard_Real& YP,
2206                                 Standard_Real& ZP,
2207                                 Standard_Real& VX,
2208                                 Standard_Real& VY,
2209                                 Standard_Real& VZ) const
2210 {
2211   Standard_Real Xo,Yo,Zo;
2212
2213   Convert (Xpix, Ypix, XP, YP, ZP);
2214   if ( Type() == V3d_PERSPECTIVE ) 
2215   {
2216     FocalReferencePoint (Xo,Yo,Zo);
2217     VX = Xo - XP;
2218     VY = Yo - YP;
2219     VZ = Zo - ZP;
2220   }
2221   else 
2222   {
2223     Proj (VX,VY,VZ);
2224   }
2225 }
2226
2227 //=============================================================================
2228 //function : Depth
2229 //purpose  :
2230 //=============================================================================
2231 Standard_Real V3d_View::Depth() const
2232 {
2233   return myCamera->Distance();
2234 }
2235
2236 //=============================================================================
2237 //function : Proj
2238 //purpose  :
2239 //=============================================================================
2240 void V3d_View::Proj(Standard_Real& Dx, Standard_Real& Dy, Standard_Real& Dz) const
2241 {
2242   gp_Dir aCameraDir = myCamera->Direction().Reversed();
2243   Dx = aCameraDir.X();
2244   Dy = aCameraDir.Y();
2245   Dz = aCameraDir.Z();
2246 }
2247
2248 //=============================================================================
2249 //function : At
2250 //purpose  :
2251 //=============================================================================
2252 void V3d_View::At(Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const
2253 {
2254   gp_Pnt aCameraCenter = myCamera->Center();
2255   X = aCameraCenter.X();
2256   Y = aCameraCenter.Y();
2257   Z = aCameraCenter.Z();
2258 }
2259
2260 //=============================================================================
2261 //function : Up
2262 //purpose  :
2263 //=============================================================================
2264 void V3d_View::Up(Standard_Real& Vx, Standard_Real& Vy, Standard_Real& Vz) const
2265 {
2266   gp_Dir aCameraUp = myCamera->Up();
2267   Vx = aCameraUp.X();
2268   Vy = aCameraUp.Y();
2269   Vz = aCameraUp.Z();
2270 }
2271
2272 //=============================================================================
2273 //function : Twist
2274 //purpose  :
2275 //=============================================================================
2276 Standard_Real V3d_View::Twist() const
2277 {
2278   Standard_Real Xup,Yup,Zup,Xpn,Ypn,Zpn,X0,Y0,Z0 ;
2279   Standard_Real pvx,pvy,pvz,pvn,sca,angle ;
2280   Graphic3d_Vector Xaxis,Yaxis,Zaxis ;
2281   Standard_Boolean TheStatus ;
2282
2283   gp_Dir aReferencePlane (myCamera->Direction().Reversed());
2284   gp_Dir anUp;
2285
2286   Proj(Xpn,Ypn,Zpn);
2287   anUp = gp_Dir (0.,0.,1.) ;
2288   TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2289   if( !TheStatus ) {
2290     anUp = gp_Dir (0.,1.,0.) ;
2291     TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2292   }
2293   if( !TheStatus ) {
2294     anUp = gp_Dir (1.,0.,0.) ;
2295     TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2296   }
2297   Yaxis.Coord(X0,Y0,Z0) ;
2298
2299   Up(Xup,Yup,Zup) ;
2300   /* Compute Cross Vector From Up & Origin */
2301   pvx = Y0*Zup - Z0*Yup ;
2302   pvy = Z0*Xup - X0*Zup ;
2303   pvz = X0*Yup - Y0*Xup ;
2304   pvn = pvx*pvx + pvy*pvy + pvz*pvz ;
2305   sca = X0*Xup + Y0*Yup + Z0*Zup ;
2306   /* Compute Angle */
2307   angle = Sqrt(pvn) ;
2308   if( angle > 1. ) angle = 1. ;
2309   else if( angle < -1. ) angle = -1. ;
2310   angle = asin(angle) ;
2311   if( sca < 0. ) angle = M_PI - angle ;
2312   if( angle > 0. && angle < M_PI ) {
2313     sca = pvx*Xpn + pvy*Ypn + pvz*Zpn ;
2314     if( sca < 0. ) angle = DEUXPI - angle ;
2315   }
2316   return angle ;
2317 }
2318
2319 //=============================================================================
2320 //function : ShadingModel
2321 //purpose  :
2322 //=============================================================================
2323 V3d_TypeOfShadingModel V3d_View::ShadingModel() const
2324 {
2325   V3d_TypeOfShadingModel SM = (V3d_TypeOfShadingModel)MyViewContext.Model() ;
2326   return SM ;
2327 }
2328
2329 //=============================================================================
2330 //function : SurfaceDetail
2331 //purpose  :
2332 //=============================================================================
2333 V3d_TypeOfSurfaceDetail V3d_View::SurfaceDetail() const
2334 {
2335   V3d_TypeOfSurfaceDetail SM = (V3d_TypeOfSurfaceDetail)MyViewContext.SurfaceDetail() ;
2336   return SM ;
2337 }
2338
2339 //=============================================================================
2340 //function : TextureEnv
2341 //purpose  :
2342 //=============================================================================
2343 Handle(Graphic3d_TextureEnv) V3d_View::TextureEnv() const
2344 {
2345   Handle(Graphic3d_TextureEnv) SM = MyViewContext.TextureEnv() ;
2346   return SM ;
2347 }
2348
2349 //=============================================================================
2350 //function : Visualization
2351 //purpose  :
2352 //=============================================================================
2353 V3d_TypeOfVisualization V3d_View::Visualization() const
2354 {
2355   V3d_TypeOfVisualization V =
2356     (V3d_TypeOfVisualization)MyViewContext.Visualization() ;
2357   return V ;
2358 }
2359
2360 //=============================================================================
2361 //function : Antialiasing
2362 //purpose  :
2363 //=============================================================================
2364 Standard_Boolean V3d_View::Antialiasing() const
2365 {
2366   Standard_Boolean A = MyViewContext.AliasingIsOn() ;
2367   return A ;
2368 }
2369
2370 //=============================================================================
2371 //function : Viewer
2372 //purpose  :
2373 //=============================================================================
2374 Handle(V3d_Viewer) V3d_View::Viewer() const
2375 {
2376   return MyViewer ;
2377 }
2378
2379 //=============================================================================
2380 //function : IfWindow
2381 //purpose  :
2382 //=============================================================================
2383 Standard_Boolean V3d_View::IfWindow() const
2384 {
2385   Standard_Boolean TheStatus = MyView->IsDefined() ;
2386   return TheStatus ;
2387 }
2388
2389 //=============================================================================
2390 //function : Window
2391 //purpose  :
2392 //=============================================================================
2393 Handle(Aspect_Window) V3d_View::Window() const
2394 {
2395   return MyWindow;
2396 }
2397
2398 //=============================================================================
2399 //function : Type
2400 //purpose  :
2401 //=============================================================================
2402 V3d_TypeOfView V3d_View::Type() const
2403 {
2404   return myCamera->IsOrthographic() ? V3d_ORTHOGRAPHIC : V3d_PERSPECTIVE;
2405 }
2406
2407 //=============================================================================
2408 //function : SetFocale
2409 //purpose  :
2410 //=============================================================================
2411 void V3d_View::SetFocale( const Standard_Real focale )
2412 {
2413   if (myCamera->IsOrthographic())
2414   {
2415     return;
2416   }
2417
2418   Standard_Real aFOVyRad = ATan (focale / (myCamera->Distance() * 2.0));
2419
2420   myCamera->SetFOVy (aFOVyRad * (360 / M_PI));
2421
2422   ImmediateUpdate();
2423 }
2424
2425 //=============================================================================
2426 //function : Focale
2427 //purpose  :
2428 //=============================================================================
2429 Standard_Real V3d_View::Focale() const
2430 {
2431   if (myCamera->IsOrthographic())
2432   {
2433     return 0.0;
2434   }
2435
2436   return myCamera->Distance() * 2.0 * Tan(myCamera->FOVy() * M_PI / 360.0);
2437 }
2438
2439 //=============================================================================
2440 //function : View
2441 //purpose  :
2442 //=============================================================================
2443 Handle(Visual3d_View) V3d_View::View() const
2444 {
2445   return MyView ;
2446 }
2447
2448 //=============================================================================
2449 //function : ScreenAxis
2450 //purpose  :
2451 //=============================================================================
2452 Standard_Boolean V3d_View::ScreenAxis( const gp_Dir &Vpn, const gp_Dir &Vup, Graphic3d_Vector &Xaxe, Graphic3d_Vector &Yaxe, Graphic3d_Vector &Zaxe)
2453 {
2454   Standard_Real Xpn, Ypn, Zpn, Xup, Yup, Zup;
2455   Standard_Real dx1, dy1, dz1, xx, yy, zz;
2456
2457   Xpn = Vpn.X(); Ypn = Vpn.Y(); Zpn = Vpn.Z();
2458   Xup = Vup.X(); Yup = Vup.Y(); Zup = Vup.Z();
2459   xx = Yup*Zpn - Zup*Ypn;
2460   yy = Zup*Xpn - Xup*Zpn;
2461   zz = Xup*Ypn - Yup*Xpn;
2462   Xaxe.SetCoord (xx, yy, zz);
2463   if (Xaxe.LengthZero()) return Standard_False;
2464   Xaxe.Normalize(); 
2465   Xaxe.Coord(dx1, dy1, dz1);
2466   xx = Ypn*dz1 - Zpn*dy1;
2467   yy = Zpn*dx1 - Xpn*dz1;
2468   zz = Xpn*dy1 - Ypn*dx1;
2469   Yaxe.SetCoord (xx, yy, zz) ;
2470   if (Yaxe.LengthZero()) return Standard_False;
2471   Yaxe.Normalize(); 
2472
2473   Zaxe.SetCoord (Xpn, Ypn, Zpn);
2474   Zaxe.Normalize();
2475   return Standard_True;
2476 }
2477
2478 //=============================================================================
2479 //function : TrsPoint
2480 //purpose  :
2481 //=============================================================================
2482 Graphic3d_Vertex V3d_View::TrsPoint( const Graphic3d_Vertex &P, const TColStd_Array2OfReal &Matrix )
2483 {
2484   Graphic3d_Vertex PP ;
2485   Standard_Real X,Y,Z,XX,YY,ZZ ;
2486
2487   // CAL. S3892
2488   Standard_Integer lr, ur, lc, uc;
2489   lr    = Matrix.LowerRow ();
2490   ur    = Matrix.UpperRow ();
2491   lc    = Matrix.LowerCol ();
2492   uc    = Matrix.UpperCol ();
2493   if ((ur - lr + 1 != 4) || (uc - lc + 1 != 4) ) {
2494     P.Coord(X,Y,Z) ;
2495     PP.SetCoord(X,Y,Z) ;
2496     return PP ;
2497   }
2498   P.Coord(X,Y,Z) ;
2499   XX = (Matrix(lr,lc+3) + X*Matrix(lr,lc) + Y*Matrix(lr,lc+1)+
2500     Z*Matrix(lr,lc+2))/Matrix(lr+3,lc+3) ;
2501
2502   YY = (Matrix(lr+1,lc+3) + X*Matrix(lr+1,lc) + Y*Matrix(lr+1,lc+1) +
2503     Z*Matrix(lr+1,lc+2))/Matrix(lr+3,lc+3) ;
2504
2505   ZZ = (Matrix(lr+2,lc+3) + X*Matrix(lr+2,lc) + Y*Matrix(lr+2,lc+1) +
2506     Z*Matrix(lr+2,lc+2))/Matrix(lr+3,lc+3) ;
2507   PP.SetCoord(XX,YY,ZZ) ;
2508   return PP ;
2509 }
2510
2511 //=======================================================================
2512 //function : Pan
2513 //purpose  :
2514 //=======================================================================
2515 void V3d_View::Pan (const Standard_Integer theDXp,
2516                     const Standard_Integer theDYp,
2517                     const Quantity_Factor  theZoomFactor,
2518                     const Standard_Boolean theToStart)
2519 {
2520   Panning (Convert (theDXp), Convert (theDYp), theZoomFactor, theToStart);
2521 }
2522
2523 //=======================================================================
2524 //function : Panning
2525 //purpose  :
2526 //=======================================================================
2527 void V3d_View::Panning (const Standard_Real theDXv,
2528                         const Standard_Real theDYv,
2529                         const Quantity_Factor theZoomFactor,
2530                         const Standard_Boolean theToStart)
2531 {
2532   Standard_ASSERT_RAISE (theZoomFactor > 0.0, "Bad zoom factor");
2533
2534   if (theToStart)
2535   {
2536     myCamStartOpEye = myCamera->Eye();
2537     myCamStartOpCenter = myCamera->Center();
2538   }
2539
2540   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
2541
2542   gp_Pnt aViewDims = myCamera->ViewDimensions();
2543
2544   myCamera->SetEye (myCamStartOpEye);
2545   myCamera->SetCenter (myCamStartOpCenter);
2546   Translate (myCamera, -theDXv, -theDYv);
2547   Scale (myCamera, aViewDims.X() / theZoomFactor, aViewDims.Y() / theZoomFactor);
2548
2549   SetImmediateUpdate (wasUpdateEnabled);
2550
2551   ImmediateUpdate();
2552 }
2553
2554 //=======================================================================
2555 //function : Zoom
2556 //purpose  :
2557 //=======================================================================
2558 void V3d_View::Zoom (const Standard_Integer theXp1,
2559                      const Standard_Integer theYp1,
2560                      const Standard_Integer theXp2,
2561                      const Standard_Integer theYp2)
2562 {
2563   Standard_Integer aDx = theXp2 - theXp1;
2564   Standard_Integer aDy = theYp2 - theYp1;
2565   if (aDx != 0 || aDy != 0)
2566   {
2567     Standard_Real aCoeff = Sqrt( (Standard_Real)(aDx * aDx + aDy * aDy) ) / 100.0 + 1.0;
2568     aCoeff = (aDx > 0) ? aCoeff : 1.0 / aCoeff;
2569     SetZoom (aCoeff, Standard_True);
2570   }
2571 }
2572
2573 //=======================================================================
2574 //function : StartZoomAtPoint
2575 //purpose  :
2576 //=======================================================================
2577 void V3d_View::StartZoomAtPoint (const Standard_Integer theXp,
2578                                  const Standard_Integer theYp)
2579 {
2580   MyZoomAtPointX = theXp;
2581   MyZoomAtPointY = theYp;
2582 }
2583
2584 //=======================================================================
2585 //function : ZoomAtPoint
2586 //purpose  :
2587 //=======================================================================
2588 void V3d_View::ZoomAtPoint (const Standard_Integer theMouseStartX,
2589                             const Standard_Integer theMouseStartY,
2590                             const Standard_Integer theMouseEndX,
2591                             const Standard_Integer theMouseEndY)
2592 {
2593   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
2594
2595   // zoom
2596   Standard_Real aDxy = Standard_Real ((theMouseEndX + theMouseEndY) - (theMouseStartX + theMouseStartY));
2597   Standard_Real aDZoom = Abs (aDxy) / 100.0 + 1.0;
2598   aDZoom = (aDxy > 0.0) ?  aDZoom : 1.0 / aDZoom;
2599
2600   V3d_BadValue_Raise_if (aDZoom <= 0.0, "V3d_View::ZoomAtPoint, bad coefficient");
2601
2602   Standard_Real aViewWidth  = myCamera->ViewDimensions().X();
2603   Standard_Real aViewHeight = myCamera->ViewDimensions().Y();
2604
2605   // ensure that zoom will not be too small or too big.
2606   Standard_Real aCoef = aDZoom;
2607   if (aViewWidth < aCoef * Precision::Confusion())
2608   {
2609     aCoef = aViewWidth / Precision::Confusion();
2610   }
2611   else if (aViewWidth > aCoef * 1e12)
2612   {
2613     aCoef = aViewWidth / 1e12;
2614   }
2615   if (aViewHeight < aCoef * Precision::Confusion())
2616   {
2617     aCoef = aViewHeight / Precision::Confusion();
2618   }
2619   else if (aViewHeight > aCoef * 1e12)
2620   {
2621     aCoef = aViewHeight / 1e12;
2622   }
2623
2624   Standard_Real aZoomAtPointXv = 0.0;
2625   Standard_Real aZoomAtPointYv = 0.0;
2626   Convert (MyZoomAtPointX, MyZoomAtPointY, aZoomAtPointXv, aZoomAtPointYv);
2627
2628   V3d_Coordinate aDxv = aZoomAtPointXv / aCoef;
2629   V3d_Coordinate aDyv = aZoomAtPointYv / aCoef;
2630
2631   myCamera->SetScale (myCamera->Scale() / aCoef);
2632   Translate (myCamera, aZoomAtPointXv - aDxv, aZoomAtPointYv - aDyv);
2633
2634   View()->AutoZFit();
2635
2636   SetImmediateUpdate (wasUpdateEnabled);
2637
2638   ImmediateUpdate();
2639 }
2640
2641 //=============================================================================
2642 //function : AxialScale
2643 //purpose  :
2644 //=============================================================================
2645 void V3d_View::AxialScale (const Standard_Integer Dx,
2646                            const Standard_Integer Dy,
2647                            const V3d_TypeOfAxe Axis)
2648 {
2649   if( Dx != 0. || Dy != 0. ) {
2650     Standard_Real Sx, Sy, Sz;
2651     AxialScale( Sx, Sy, Sz );
2652     Standard_Real dscale = Sqrt(Dx*Dx + Dy*Dy) / 100. + 1;
2653     dscale = (Dx > 0) ?  dscale : 1./dscale;
2654     if( Axis == V3d_X ) Sx = dscale;
2655     if( Axis == V3d_Y ) Sy = dscale;
2656     if( Axis == V3d_Z ) Sz = dscale;
2657     SetAxialScale( Sx, Sy, Sz );
2658   }
2659 }
2660
2661 //=============================================================================
2662 //function : FitAll
2663 //purpose  :
2664 //=============================================================================
2665 void V3d_View::FitAll(const Handle(Aspect_Window)& aWindow,
2666                       const Standard_Real Xmin,
2667                       const Standard_Real Ymin,
2668                       const Standard_Real Xmax,
2669                       const Standard_Real Ymax)
2670 {
2671   Standard_Integer aWinWidth, aWinHeight;
2672   aWindow->Size (aWinWidth, aWinHeight);
2673
2674   Standard_Real aWinAspect = (Standard_Real)aWinWidth / aWinHeight;
2675   Standard_Real aFitSizeU  = Abs (Xmax - Xmin);
2676   Standard_Real aFitSizeV  = Abs (Ymax - Ymin);
2677   Standard_Real aFitAspect = aFitSizeU / aFitSizeV;
2678   if (aFitAspect >= aWinAspect)
2679   {
2680     aFitSizeV = aFitSizeU / aWinAspect;
2681   }
2682   else
2683   {
2684     aFitSizeU = aFitSizeV * aWinAspect;
2685   }
2686
2687   myCamera->SetAspect (aWinAspect);
2688   Translate (myCamera, (Xmin + Xmax) * 0.5, (Ymin + Ymax) * 0.5);
2689   Scale (myCamera, aFitSizeU, aFitSizeV);
2690   View()->AutoZFit();
2691
2692   ImmediateUpdate();
2693 }
2694
2695 //=============================================================================
2696 //function : StartRotation
2697 //purpose  :
2698 //=============================================================================
2699 static Standard_Boolean zRotation = Standard_False;
2700 void V3d_View::StartRotation(const Standard_Integer X,
2701                              const Standard_Integer Y,
2702                              const Quantity_Ratio zRotationThreshold)
2703 {
2704   sx = X; sy = Y;
2705   Standard_Real x,y;
2706   Size(x,y);
2707   rx = Standard_Real(Convert(x));
2708   ry = Standard_Real(Convert(y));
2709   Gravity(gx,gy,gz);
2710   Rotate(0.,0.,0.,gx,gy,gz,Standard_True);
2711   zRotation = Standard_False;
2712   if( zRotationThreshold > 0. ) {
2713     Standard_Real dx = Abs(sx - rx/2.);
2714     Standard_Real dy = Abs(sy - ry/2.);
2715     //  if( dx > rx/3. || dy > ry/3. ) zRotation = Standard_True;
2716     Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
2717     if( dx > dd || dy > dd ) zRotation = Standard_True;
2718   }
2719
2720 }
2721
2722 //=============================================================================
2723 //function : Rotation
2724 //purpose  :
2725 //=============================================================================
2726 void V3d_View::Rotation(const Standard_Integer X,
2727                         const Standard_Integer Y)
2728 {
2729   if( rx == 0. || ry == 0. ) {
2730     StartRotation(X,Y);
2731     return;
2732   }
2733   Standard_Real dx=0.,dy=0.,dz=0.;
2734   if( zRotation ) {
2735     dz = atan2(Standard_Real(X)-rx/2., ry/2.-Standard_Real(Y)) -
2736       atan2(sx-rx/2.,ry/2.-sy);
2737   } else {
2738     dx = (Standard_Real(X) - sx) * M_PI / rx;
2739     dy = (sy - Standard_Real(Y)) * M_PI / ry;
2740   }
2741
2742   Rotate(dx, dy, dz, gx, gy, gz, Standard_False);
2743 }
2744
2745 //=============================================================================
2746 //function : SetComputedMode
2747 //purpose  :
2748 //=============================================================================
2749 void V3d_View::SetComputedMode (const Standard_Boolean aMode)
2750 {
2751   if (aMode)
2752   {
2753     if (myComputedMode)
2754     {
2755       MyView->SetComputedMode (Standard_True);
2756       Update();
2757     }
2758   } 
2759   else 
2760   {
2761     MyView->SetComputedMode (Standard_False);
2762     Update();
2763   }
2764 }
2765
2766 //=============================================================================
2767 //function : ComputedMode
2768 //purpose  :
2769 //=============================================================================
2770 Standard_Boolean V3d_View::ComputedMode() const
2771 {
2772   return MyView->ComputedMode();
2773 }
2774
2775 //=============================================================================
2776 //function : SetBackFacingModel
2777 //purpose  :
2778 //=============================================================================
2779 void V3d_View::SetBackFacingModel (const V3d_TypeOfBackfacingModel aModel)
2780 {
2781   MyView->SetBackFacingModel (Visual3d_TypeOfBackfacingModel(aModel));
2782   Redraw();
2783 }
2784
2785 //=============================================================================
2786 //function : BackFacingModel
2787 //purpose  :
2788 //=============================================================================
2789 V3d_TypeOfBackfacingModel V3d_View::BackFacingModel() const
2790 {
2791   return V3d_TypeOfBackfacingModel(MyView -> BackFacingModel ());
2792 }
2793
2794 void V3d_View::Init()
2795 {
2796   myComputedMode = MyViewer->ComputedMode();
2797   if( !myComputedMode || !MyViewer->DefaultComputedMode() ) {
2798     SetComputedMode(Standard_False);
2799   }
2800 }
2801
2802 //=============================================================================
2803 //function : Dump
2804 //purpose  :
2805 //=============================================================================
2806 Standard_Boolean V3d_View::Dump (const Standard_CString      theFile,
2807                                  const Graphic3d_BufferType& theBufferType)
2808 {
2809   Standard_Integer aWinWidth, aWinHeight;
2810   MyWindow->Size (aWinWidth, aWinHeight);
2811   Image_AlienPixMap anImage;
2812
2813   return ToPixMap (anImage, aWinWidth, aWinHeight, theBufferType) && anImage.Save (theFile);
2814 }
2815
2816 //=============================================================================
2817 //function : ToPixMap
2818 //purpose  :
2819 //=============================================================================
2820 Standard_Boolean V3d_View::ToPixMap (Image_PixMap&               theImage,
2821                                      const Standard_Integer      theWidth,
2822                                      const Standard_Integer      theHeight,
2823                                      const Graphic3d_BufferType& theBufferType,
2824                                      const Standard_Boolean      theToKeepAspect,
2825                                      const V3d_StereoDumpOptions theStereoOptions)
2826 {
2827   Graphic3d_CView* cView = (Graphic3d_CView* )MyView->CView();
2828
2829   // always prefer hardware accelerated offscreen buffer
2830   Graphic3d_PtrFrameBuffer aFBOPtr = NULL;
2831   Graphic3d_PtrFrameBuffer aPrevFBOPtr = (Graphic3d_PtrFrameBuffer )cView->ptrFBO;
2832   Standard_Integer aFBOVPSizeX (theWidth), aFBOVPSizeY (theHeight), aFBOSizeXMax (0), aFBOSizeYMax (0);
2833   Standard_Integer aPrevFBOVPSizeX (0), aPrevFBOVPSizeY (0), aPrevFBOSizeXMax (0), aPrevFBOSizeYMax (0);
2834   if (aPrevFBOPtr != NULL)
2835   {
2836     MyView->FBOGetDimensions (aPrevFBOPtr,
2837                               aPrevFBOVPSizeX, aPrevFBOVPSizeY,
2838                               aPrevFBOSizeXMax, aPrevFBOSizeYMax);
2839     if (aFBOVPSizeX <= aPrevFBOSizeXMax && aFBOVPSizeY <= aPrevFBOSizeYMax)
2840     {
2841       MyView->FBOChangeViewport (aPrevFBOPtr, aFBOVPSizeX, aFBOVPSizeY);
2842       aFBOPtr = aPrevFBOPtr;
2843     }
2844   }
2845
2846   if (aFBOPtr == NULL)
2847   {
2848     // Try to create hardware accelerated buffer
2849     aFBOPtr = MyView->FBOCreate (aFBOVPSizeX, aFBOVPSizeY);
2850     if (aFBOPtr != NULL)
2851     {
2852       MyView->FBOGetDimensions (aFBOPtr,
2853                                 aFBOVPSizeX,  aFBOVPSizeY,
2854                                 aFBOSizeXMax, aFBOSizeYMax);
2855       // reduce viewport in case of hardware limits
2856       if (aFBOVPSizeX > aFBOSizeXMax) aFBOVPSizeX = aFBOSizeXMax;
2857       if (aFBOVPSizeY > aFBOSizeYMax) aFBOVPSizeY = aFBOSizeYMax;
2858       MyView->FBOChangeViewport (aFBOPtr, aFBOVPSizeX, aFBOVPSizeY);
2859     }
2860   }
2861   cView->ptrFBO = aFBOPtr;
2862
2863   // If hardware accelerated buffer - try to use onscreen buffer
2864   // Results may be bad!
2865   if (aFBOPtr == NULL)
2866   {
2867     // retrieve window sizes
2868     Standard_Integer aWinWidth, aWinHeight;
2869     MyWindow->Size (aWinWidth, aWinHeight);
2870
2871     // technically we can reduce existing viewport...
2872     // but currently allow only dumping the window itself
2873     if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight)
2874     {
2875       return Standard_False;
2876     }
2877   }
2878
2879   Handle(Graphic3d_Camera) aStoreMapping = new Graphic3d_Camera();
2880
2881   aStoreMapping->Copy (myCamera);
2882
2883   if (myCamera->IsStereo())
2884   {
2885     switch (theStereoOptions)
2886     {
2887       case V3d_SDO_MONO:
2888       {
2889         myCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
2890         break;
2891       }
2892       case V3d_SDO_LEFT_EYE:
2893       {
2894         myCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
2895         break;
2896       }
2897       case V3d_SDO_RIGHT_EYE:
2898       {
2899         myCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
2900         break;
2901       }
2902       case V3d_SDO_BLENDED:
2903       {
2904         break; // dump as is
2905       }
2906     }
2907   }
2908
2909   // render immediate structures into back buffer rather than front
2910   Handle(Graphic3d_GraphicDriver) aDriver = Handle(Graphic3d_GraphicDriver)::DownCast (MyView->GraphicDriver());
2911   const Standard_Boolean aPrevImmediateMode = aDriver.IsNull() ? Standard_True : aDriver->SetImmediateModeDrawToFront (*cView, Standard_False);
2912
2913   const Standard_Boolean toAutoUpdate = myImmediateUpdate;
2914   myImmediateUpdate = Standard_False;
2915   View()->AutoZFit();
2916   myImmediateUpdate = toAutoUpdate;
2917
2918   if (theToKeepAspect)
2919   {
2920     myCamera->SetAspect ((Standard_Real) aFBOVPSizeX / aFBOVPSizeY);
2921   }
2922
2923   //workaround for rendering list of Over and Under Layers
2924   if (!MyLayerMgr.IsNull())
2925   {
2926     MyLayerMgr->Compute();
2927   }
2928
2929   Redraw();
2930
2931   if (!aDriver.IsNull())
2932   {
2933     aDriver->SetImmediateModeDrawToFront (*cView, aPrevImmediateMode);
2934   }
2935
2936   myCamera->Copy (aStoreMapping);
2937
2938   Standard_Boolean isSuccess = Standard_True;
2939
2940   // allocate image buffer for dumping
2941   if (theImage.IsEmpty()
2942    || (Standard_Size )aFBOVPSizeX != theImage.SizeX()
2943    || (Standard_Size )aFBOVPSizeY != theImage.SizeY())
2944   {
2945     bool isBigEndian = Image_PixMap::IsBigEndianHost();
2946     Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN;
2947     switch (theBufferType)
2948     {
2949       case Graphic3d_BT_RGB:   aFormat = isBigEndian ? Image_PixMap::ImgRGB  : Image_PixMap::ImgBGR;  break;
2950       case Graphic3d_BT_RGBA:  aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break;
2951       case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break;
2952     }
2953
2954     isSuccess = isSuccess && theImage.InitZero (aFormat, aFBOVPSizeX, aFBOVPSizeY);
2955   }
2956   isSuccess = isSuccess && MyView->BufferDump (theImage, theBufferType);
2957
2958   // FBO now useless, free resources
2959   if (aFBOPtr != aPrevFBOPtr)
2960   {
2961     MyView->FBORelease (aFBOPtr);
2962   }
2963   else if (aPrevFBOPtr != NULL)
2964   {
2965     MyView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSizeX, aPrevFBOVPSizeY);
2966   }
2967   cView->ptrFBO = aPrevFBOPtr;
2968   return isSuccess;
2969 }
2970
2971 void V3d_View::ImmediateUpdate() const
2972 {
2973   if (myImmediateUpdate) Update();
2974 }
2975
2976 Standard_Boolean V3d_View::SetImmediateUpdate (const Standard_Boolean theImmediateUpdate)
2977 {
2978   Standard_Boolean aPreviousMode = myImmediateUpdate;
2979   myImmediateUpdate = theImmediateUpdate;
2980   return aPreviousMode;
2981 }
2982
2983 // =======================================================================
2984 // function : SetCamera
2985 // purpose  :
2986 // =======================================================================
2987 void V3d_View::SetCamera (const Handle(Graphic3d_Camera)& theCamera)
2988 {
2989   Standard_ASSERT_RAISE (!theCamera.IsNull(), "Void camera is not allowed");
2990
2991   myCamera = theCamera;
2992
2993   MyView->SetCamera (theCamera);
2994 }
2995
2996 // =======================================================================
2997 // function : GetCamera
2998 // purpose  :
2999 // =======================================================================
3000 const Handle(Graphic3d_Camera)& V3d_View::Camera() const
3001 {
3002   return myCamera;
3003 }
3004
3005 // =======================================================================
3006 // function : FitMinMax
3007 // purpose  : Internal
3008 // =======================================================================
3009 Standard_Boolean V3d_View::FitMinMax (const Handle(Graphic3d_Camera)& theCamera,
3010                                       const Bnd_Box& theBox,
3011                                       const Standard_Real theMargin,
3012                                       const Standard_Real theResolution,
3013                                       const Standard_Boolean theToEnlargeIfLine) const
3014 {
3015   // Check bounding box for validness
3016   if (theBox.IsVoid())
3017   {
3018     return Standard_False; // bounding box is out of bounds...
3019   }
3020
3021   // Apply "axial scaling" to the bounding points.
3022   // It is not the best approach to make this scaling as a part of fit all operation,
3023   // but the axial scale is integrated into camera orientation matrix and the other
3024   // option is to perform frustum plane adjustment algorithm in view camera space,
3025   // which will lead to a number of additional world-view space conversions and
3026   // loosing precision as well.
3027   gp_Pnt aBndMin = theBox.CornerMin().XYZ().Multiplied (theCamera->AxialScale());
3028   gp_Pnt aBndMax = theBox.CornerMax().XYZ().Multiplied (theCamera->AxialScale());
3029
3030   if (aBndMax.IsEqual (aBndMin, RealEpsilon()))
3031   {
3032     return Standard_False; // nothing to fit all
3033   }
3034
3035   // Prepare camera frustum planes.
3036   NCollection_Array1<gp_Pln> aFrustumPlane (1, 6);
3037   theCamera->Frustum (aFrustumPlane.ChangeValue (1),
3038                       aFrustumPlane.ChangeValue (2),
3039                       aFrustumPlane.ChangeValue (3),
3040                       aFrustumPlane.ChangeValue (4),
3041                       aFrustumPlane.ChangeValue (5),
3042                       aFrustumPlane.ChangeValue (6));
3043
3044   // Prepare camera up, side, direction vectors.
3045   gp_Dir aCamUp  = theCamera->OrthogonalizedUp();
3046   gp_Dir aCamDir = theCamera->Direction();
3047   gp_Dir aCamSide = aCamDir ^ aCamUp;
3048
3049   // Prepare scene bounding box parameters.
3050   gp_Pnt aBndCenter = (aBndMin.XYZ() + aBndMax.XYZ()) / 2.0;
3051
3052   NCollection_Array1<gp_Pnt> aBndCorner (1, 8);
3053   aBndCorner.ChangeValue (1) = gp_Pnt (aBndMin.X(), aBndMin.Y(), aBndMin.Z());
3054   aBndCorner.ChangeValue (2) = gp_Pnt (aBndMin.X(), aBndMin.Y(), aBndMax.Z());
3055   aBndCorner.ChangeValue (3) = gp_Pnt (aBndMin.X(), aBndMax.Y(), aBndMin.Z());
3056   aBndCorner.ChangeValue (4) = gp_Pnt (aBndMin.X(), aBndMax.Y(), aBndMax.Z());
3057   aBndCorner.ChangeValue (5) = gp_Pnt (aBndMax.X(), aBndMin.Y(), aBndMin.Z());
3058   aBndCorner.ChangeValue (6) = gp_Pnt (aBndMax.X(), aBndMin.Y(), aBndMax.Z());
3059   aBndCorner.ChangeValue (7) = gp_Pnt (aBndMax.X(), aBndMax.Y(), aBndMin.Z());
3060   aBndCorner.ChangeValue (8) = gp_Pnt (aBndMax.X(), aBndMax.Y(), aBndMax.Z());
3061
3062   // Perspective-correct camera projection vector, matching the bounding box is determined geometrically.
3063   // Knowing the initial shape of a frustum it is possible to match it to a bounding box.
3064   // Then, knowing the relation of camera projection vector to the frustum shape it is possible to
3065   // set up perspective-correct camera projection matching the bounding box.
3066   // These steps support non-asymmetric transformations of view-projection space provided by camera.
3067   // The zooming can be done by calculating view plane size matching the bounding box at center of
3068   // the bounding box. The only limitation here is that the scale of camera should define size of
3069   // its view plane passing through the camera center, and the center of camera should be on the
3070   // same line with the center of bounding box.
3071
3072   // The following method is applied:
3073   // 1) Determine normalized asymmetry of camera projection vector by frustum planes.
3074   // 2) Determine new location of frustum planes, "matching" the bounding box.
3075   // 3) Determine new camera projection vector using the normalized asymmetry.
3076   // 4) Determine new zooming in view space.
3077
3078   // 1. Determine normalized projection asymmetry (if any).
3079   Standard_Real anAssymX = Tan ( aCamSide.Angle (aFrustumPlane (1).Axis().Direction()))
3080                          - Tan (-aCamSide.Angle (aFrustumPlane (2).Axis().Direction()));
3081   Standard_Real anAssymY = Tan ( aCamUp.Angle   (aFrustumPlane (3).Axis().Direction()))
3082                          - Tan (-aCamUp.Angle   (aFrustumPlane (4).Axis().Direction()));
3083
3084   // 2. Determine how far should be the frustum planes placed from center
3085   //    of bounding box, in order to match the bounding box closely.
3086   NCollection_Array1<Standard_Real> aFitDistance (1, 6);
3087   aFitDistance.ChangeValue (1) = 0.0;
3088   aFitDistance.ChangeValue (2) = 0.0;
3089   aFitDistance.ChangeValue (3) = 0.0;
3090   aFitDistance.ChangeValue (4) = 0.0;
3091   aFitDistance.ChangeValue (5) = 0.0;
3092   aFitDistance.ChangeValue (6) = 0.0;
3093
3094   for (Standard_Integer anI = aFrustumPlane.Lower(); anI <= aFrustumPlane.Upper(); ++anI)
3095   {
3096     // Measure distances from center of bounding box to its corners towards the frustum plane.
3097     const gp_Dir& aPlaneN = aFrustumPlane.ChangeValue (anI).Axis().Direction();
3098
3099     Standard_Real& aFitDist = aFitDistance.ChangeValue (anI);
3100
3101     for (Standard_Integer aJ = aBndCorner.Lower(); aJ <= aBndCorner.Upper(); ++aJ)
3102     {
3103       aFitDist = Max (aFitDist, gp_Vec (aBndCenter, aBndCorner (aJ)).Dot (aPlaneN));
3104     }
3105   }
3106   // The center of camera is placed on the same line with center of bounding box.
3107   // The view plane section crosses the bounding box at its center.
3108   // To compute view plane size, evaluate coefficients converting "point -> plane distance"
3109   // into view section size between the point and the frustum plane.
3110   //       proj
3111   //       /|\   right half of frame     //
3112   //        |                           //
3113   //  point o<--  distance * coeff  -->//---- (view plane section)
3114   //         \                        //
3115   //      (distance)                 // 
3116   //                ~               //
3117   //                 (distance)    //
3118   //                           \/\//
3119   //                            \//
3120   //                            //
3121   //                      (frustum plane)
3122   aFitDistance.ChangeValue (1) *= Sqrt(1 + Pow (Tan ( aCamSide.Angle (aFrustumPlane (1).Axis().Direction())), 2.0));
3123   aFitDistance.ChangeValue (2) *= Sqrt(1 + Pow (Tan (-aCamSide.Angle (aFrustumPlane (2).Axis().Direction())), 2.0));
3124   aFitDistance.ChangeValue (3) *= Sqrt(1 + Pow (Tan ( aCamUp.Angle   (aFrustumPlane (3).Axis().Direction())), 2.0));
3125   aFitDistance.ChangeValue (4) *= Sqrt(1 + Pow (Tan (-aCamUp.Angle   (aFrustumPlane (4).Axis().Direction())), 2.0));
3126   aFitDistance.ChangeValue (5) *= Sqrt(1 + Pow (Tan ( aCamDir.Angle  (aFrustumPlane (5).Axis().Direction())), 2.0));
3127   aFitDistance.ChangeValue (6) *= Sqrt(1 + Pow (Tan (-aCamDir.Angle  (aFrustumPlane (6).Axis().Direction())), 2.0));
3128
3129   Standard_Real aViewSizeXv = aFitDistance (1) + aFitDistance (2);
3130   Standard_Real aViewSizeYv = aFitDistance (3) + aFitDistance (4);
3131   Standard_Real aViewSizeZv = aFitDistance (5) + aFitDistance (6);
3132
3133   // 3. Place center of camera on the same line with center of bounding
3134   //    box applying corresponding projection asymmetry (if any).
3135   Standard_Real anAssymXv = anAssymX * aViewSizeXv * 0.5;
3136   Standard_Real anAssymYv = anAssymY * aViewSizeYv * 0.5;
3137   Standard_Real anOffsetXv = (aFitDistance (2) - aFitDistance (1)) * 0.5 + anAssymXv;
3138   Standard_Real anOffsetYv = (aFitDistance (4) - aFitDistance (3)) * 0.5 + anAssymYv;
3139   gp_Vec aTranslateSide = gp_Vec (aCamSide) * anOffsetXv;
3140   gp_Vec aTranslateUp   = gp_Vec (aCamUp)   * anOffsetYv;
3141   gp_Pnt aCamNewCenter  = aBndCenter.Translated (aTranslateSide).Translated (aTranslateUp);
3142
3143   gp_Trsf aCenterTrsf;
3144   aCenterTrsf.SetTranslation (theCamera->Center(), aCamNewCenter);
3145   theCamera->Transform (aCenterTrsf);
3146   theCamera->SetDistance (aFitDistance (6) + aFitDistance (5));
3147
3148   // Bounding box collapses to a point or thin line going in depth of the screen
3149   if (aViewSizeXv < theResolution && aViewSizeYv < theResolution)
3150   {
3151     if (aViewSizeXv < theResolution || !theToEnlargeIfLine)
3152     {
3153       return Standard_True; // This is just one point or line and zooming has no effect.
3154     }
3155
3156     // Looking along line and "theToEnlargeIfLine" is requested.
3157     // Fit view to see whole scene on rotation.
3158     aViewSizeXv = aViewSizeZv;
3159     aViewSizeYv = aViewSizeZv;
3160   }
3161
3162   Scale (theCamera, aViewSizeXv * (1.0 + theMargin), aViewSizeYv * (1.0 + theMargin));
3163
3164   return Standard_True;
3165 }
3166
3167 // =======================================================================
3168 // function : Scale
3169 // purpose  : Internal
3170 // =======================================================================
3171 void V3d_View::Scale (const Handle(Graphic3d_Camera)& theCamera,
3172                       const Standard_Real theSizeXv,
3173                       const Standard_Real theSizeYv) const
3174 {
3175   Standard_Real anAspect = theCamera->Aspect();
3176   if (anAspect > 1.0)
3177   {
3178     theCamera->SetScale (Max (theSizeXv / anAspect, theSizeYv));
3179   }
3180   else
3181   {
3182     theCamera->SetScale (Max (theSizeXv, theSizeYv * anAspect));
3183   }
3184 }
3185
3186 // =======================================================================
3187 // function : Translate
3188 // purpose  : Internal
3189 // =======================================================================
3190 void V3d_View::Translate (const Handle(Graphic3d_Camera)& theCamera,
3191                           const Standard_Real theDXv,
3192                           const Standard_Real theDYv) const
3193 {
3194   const gp_Pnt& aCenter = theCamera->Center();
3195   const gp_Dir& aDir = theCamera->Direction();
3196   const gp_Dir& anUp = theCamera->Up();
3197   gp_Ax3 aCameraCS (aCenter, aDir.Reversed(), aDir ^ anUp);
3198
3199   gp_Vec aCameraPanXv = gp_Vec (aCameraCS.XDirection()) * theDXv;
3200   gp_Vec aCameraPanYv = gp_Vec (aCameraCS.YDirection()) * theDYv;
3201   gp_Vec aCameraPan = aCameraPanXv + aCameraPanYv;
3202   gp_Trsf aPanTrsf;
3203   aPanTrsf.SetTranslation (aCameraPan);
3204
3205   theCamera->Transform (aPanTrsf);
3206 }
3207
3208 // =======================================================================
3209 // function : IsCullingEnabled
3210 // purpose  :
3211 // =======================================================================
3212 Standard_Boolean V3d_View::IsCullingEnabled() const
3213 {
3214   Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView();
3215   return aView->IsCullingEnabled;
3216 }
3217
3218 // =======================================================================
3219 // function : SetFrustumCulling
3220 // purpose  :
3221 // =======================================================================
3222 void V3d_View::SetFrustumCulling (const Standard_Boolean theToClip)
3223 {
3224   Graphic3d_CView* aView = (Graphic3d_CView* )MyView->CView();
3225   aView->IsCullingEnabled = theToClip;
3226 }