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