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