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