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