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