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