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