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