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