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