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