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