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