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