0028889: Visualization, V3d_View - View specific Graphic3d_Structure should be remove...
[occt.git] / src / V3d / V3d_View.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <V3d_View.hxx>
15
16 #include <Aspect_GradientBackground.hxx>
17 #include <Aspect_Grid.hxx>
18 #include <Aspect_Window.hxx>
19 #include <Bnd_Box.hxx>
20 #include <gp_Ax3.hxx>
21 #include <gp_Dir.hxx>
22 #include <gp_Pln.hxx>
23 #include <Graphic3d_AspectMarker3d.hxx>
24 #include <Graphic3d_GraphicDriver.hxx>
25 #include <Graphic3d_Group.hxx>
26 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
27 #include <Graphic3d_MapOfStructure.hxx>
28 #include <Graphic3d_Structure.hxx>
29 #include <Graphic3d_TextureEnv.hxx>
30 #include <Graphic3d_Vector.hxx>
31 #include <Image_AlienPixMap.hxx>
32 #include <Message.hxx>
33 #include <Message_Messenger.hxx>
34 #include <NCollection_Array1.hxx>
35 #include <Precision.hxx>
36 #include <Quantity_Color.hxx>
37 #include <Standard_Assert.hxx>
38 #include <Standard_DivideByZero.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_MultiplyDefined.hxx>
41 #include <Standard_ShortReal.hxx>
42 #include <Standard_Type.hxx>
43 #include <Standard_TypeMismatch.hxx>
44 #include <TColgp_Array1OfPnt.hxx>
45 #include <TColStd_Array2OfReal.hxx>
46 #include <TColStd_HSequenceOfInteger.hxx>
47 #include <V3d.hxx>
48 #include <V3d_BadValue.hxx>
49 #include <V3d_Light.hxx>
50 #include <V3d_StereoDumpOptions.hxx>
51 #include <V3d_UnMapped.hxx>
52 #include <V3d_Viewer.hxx>
53
54 IMPLEMENT_STANDARD_RTTIEXT(V3d_View,Standard_Transient)
55
56 #define DEUXPI (2. * M_PI)
57
58 namespace
59 {
60   static const Standard_Integer THE_NB_BOUND_POINTS = 8;
61 }
62
63 //=============================================================================
64 //function : Constructor
65 //purpose  :
66 //=============================================================================
67 V3d_View::V3d_View (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType)
68 : MyViewer (theViewer.operator->()),
69   SwitchSetFront (Standard_False),
70   myZRotation (Standard_False),
71   myTrihedron (new V3d_Trihedron()),
72   MyTrsf (1, 4, 1, 4)
73 {
74   myView = theViewer->Driver()->CreateView (theViewer->StructureManager());
75
76   myView->SetBackground         (theViewer->GetBackgroundColor());
77   myView->SetGradientBackground (theViewer->GetGradientBackground());
78
79   ChangeRenderingParams() = theViewer->DefaultRenderingParams();
80
81   // camera init
82   Handle(Graphic3d_Camera) aCamera = new Graphic3d_Camera();
83   aCamera->SetFOVy (45.0);
84   aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, 0.05);
85   aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, 1.0);
86   aCamera->SetProjectionType ((theType == V3d_ORTHOGRAPHIC)
87     ? Graphic3d_Camera::Projection_Orthographic
88     : Graphic3d_Camera::Projection_Perspective);
89
90   myDefaultCamera = new Graphic3d_Camera();
91
92   myImmediateUpdate = Standard_False;
93   SetAutoZFitMode (Standard_True, 1.0);
94   SetBackFacingModel (V3d_TOBM_AUTOMATIC);
95   SetCamera (aCamera);
96   SetAxis (0.,0.,0.,1.,1.,1.);
97   SetVisualization (theViewer->DefaultVisualization());
98   SetShadingModel (theViewer->DefaultShadingModel());
99   SetTwist (0.);
100   SetAt (0.,0.,0.);
101   SetProj (theViewer->DefaultViewProj());
102   SetSize (theViewer->DefaultViewSize());
103   Standard_Real zsize = theViewer->DefaultViewSize();
104   SetZSize (2.*zsize);
105   SetDepth (theViewer->DefaultViewSize() / 2.0);
106   SetViewMappingDefault();
107   SetViewOrientationDefault();
108   theViewer->AddView (this);
109   Init();
110   myImmediateUpdate = Standard_True;
111 }
112
113 //=============================================================================
114 //function : Constructor
115 //purpose  :
116 //=============================================================================
117 V3d_View::V3d_View (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
118 : MyViewer (theViewer.operator->()),
119   SwitchSetFront(Standard_False),
120   myZRotation (Standard_False),
121   MyTrsf (1, 4, 1, 4)
122 {
123   myView = theViewer->Driver()->CreateView (theViewer->StructureManager());
124
125   myView->CopySettings (theView->View());
126
127   myDefaultCamera = new Graphic3d_Camera();
128
129   myImmediateUpdate = Standard_False;
130   SetAutoZFitMode (theView->AutoZFitMode(), theView->AutoZFitScaleFactor());
131   SetAxis (0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
132   SetViewMappingDefault();
133   SetViewOrientationDefault();
134   theViewer->AddView (this);
135   Init();
136   myImmediateUpdate = Standard_True;
137 }
138
139 //=============================================================================
140 //function : Destructor
141 //purpose  :
142 //=============================================================================
143 V3d_View::~V3d_View()
144 {
145   if (!myView->IsRemoved())
146   {
147     myView->Remove();
148   }
149 }
150
151 //=============================================================================
152 //function : SetMagnify
153 //purpose  :
154 //=============================================================================
155 void V3d_View::SetMagnify (const Handle(Aspect_Window)& theWindow,
156                            const Handle(V3d_View)& thePreviousView,
157                            const Standard_Integer theX1,
158                            const Standard_Integer theY1,
159                            const Standard_Integer theX2,
160                            const Standard_Integer theY2)
161 {
162   if (!myView->IsRemoved() && !myView->IsDefined())
163   {
164     Standard_Real aU1, aV1, aU2, aV2;
165     thePreviousView->Convert (theX1, theY1, aU1, aV1);
166     thePreviousView->Convert (theX2, theY2, aU2, aV2);
167     myView->SetWindow (theWindow);
168     FitAll (aU1, aV1, aU2, aV2);
169     MyViewer->SetViewOn (this);
170     MyWindow = theWindow;
171     SetRatio();
172     Redraw();
173     SetViewMappingDefault();
174   }
175 }
176
177 //=============================================================================
178 //function : SetWindow
179 //purpose  :
180 //=============================================================================
181 void V3d_View::SetWindow (const Handle(Aspect_Window)&  theWindow,
182                           const Aspect_RenderingContext theContext)
183 {
184   if (myView->IsRemoved())
185   {
186     return;
187   }
188
189   // method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw()
190   MyWindow = theWindow;
191   myView->SetWindow (theWindow, theContext);
192   MyViewer->SetViewOn (this);
193   SetRatio();
194   Redraw();
195 }
196
197 //=============================================================================
198 //function : Remove
199 //purpose  :
200 //=============================================================================
201 void V3d_View::Remove() const
202 {
203   if (!MyGrid.IsNull())
204   {
205     MyGrid->Erase();
206   }
207   if (!myTrihedron.IsNull())
208   {
209     myTrihedron->Erase();
210   }
211
212   MyViewer->DelView (this);
213   myView->Remove();
214   Handle(Aspect_Window)& aWin = const_cast<Handle(Aspect_Window)&> (MyWindow);
215   aWin.Nullify();
216 }
217
218 //=============================================================================
219 //function : Update
220 //purpose  :
221 //=============================================================================
222 void V3d_View::Update() const
223 {
224   if (!myView->IsDefined()
225    || !myView->IsActive())
226   {
227     return;
228   }
229
230   myView->Update();
231   myView->Compute();
232   myView->Redraw();
233 }
234
235 //=============================================================================
236 //function : Redraw
237 //purpose  :
238 //=============================================================================
239 void V3d_View::Redraw() const
240 {
241   if (!myView->IsDefined()
242    || !myView->IsActive())
243   {
244     return;
245   }
246
247   Handle(Graphic3d_GraphicDriver)    aGraphicDriver = MyViewer->Driver();
248   Handle(Graphic3d_StructureManager) aStructureMgr  = MyViewer->StructureManager();
249   for (Standard_Integer aRetryIter = 0; aRetryIter < 2; ++aRetryIter)
250   {
251     if (aGraphicDriver->IsDeviceLost())
252     {
253       aStructureMgr->RecomputeStructures();
254       aGraphicDriver->ResetDeviceLostFlag();
255     }
256
257     AutoZFit();
258
259     myView->Redraw();
260
261     if (!aGraphicDriver->IsDeviceLost())
262     {
263       return;
264     }
265   }
266 }
267
268 //=============================================================================
269 //function : RedrawImmediate
270 //purpose  :
271 //=============================================================================
272 void V3d_View::RedrawImmediate() const
273 {
274   if (!myView->IsDefined()
275    || !myView->IsActive())
276   {
277     return;
278   }
279
280   myView->RedrawImmediate();
281 }
282
283 //=============================================================================
284 //function : Invalidate
285 //purpose  :
286 //=============================================================================
287 void V3d_View::Invalidate() const
288 {
289   if (!myView->IsDefined())
290   {
291     return;
292   }
293
294   myView->Invalidate();
295 }
296
297 //=============================================================================
298 //function : IsInvalidated
299 //purpose  :
300 //=============================================================================
301 Standard_Boolean V3d_View::IsInvalidated() const
302 {
303   return !myView->IsDefined()
304        || myView->IsInvalidated();
305 }
306
307 // ========================================================================
308 // function : SetAutoZFitMode
309 // purpose  :
310 // ========================================================================
311 void V3d_View::SetAutoZFitMode (const Standard_Boolean theIsOn,
312                                 const Standard_Real    theScaleFactor)
313 {
314   Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
315   myAutoZFitScaleFactor = theScaleFactor;
316   myAutoZFitIsOn = theIsOn;
317 }
318
319 // ========================================================================
320 // function : AutoZFitMode
321 // purpose  :
322 // ========================================================================
323 Standard_Boolean V3d_View::AutoZFitMode() const
324 {
325   return myAutoZFitIsOn;
326 }
327
328 // ========================================================================
329 // function : AutoZFitScaleFactor
330 // purpose  :
331 // ========================================================================
332 Standard_Real V3d_View::AutoZFitScaleFactor() const
333 {
334   return myAutoZFitScaleFactor;
335 }
336
337 //=============================================================================
338 //function : AutoZFit
339 //purpose  :
340 //=============================================================================
341 void V3d_View::AutoZFit() const
342 {
343   if (!AutoZFitMode())
344   {
345     return;
346   }
347
348   ZFitAll (myAutoZFitScaleFactor);
349 }
350
351 //=============================================================================
352 //function : ZFitAll
353 //purpose  :
354 //=============================================================================
355 void V3d_View::ZFitAll (const Standard_Real theScaleFactor) const
356 {
357   Bnd_Box aMinMaxBox   = myView->MinMaxValues (Standard_False); // applicative min max boundaries
358   Bnd_Box aGraphicBox  = myView->MinMaxValues (Standard_True);  // real graphical boundaries (not accounting infinite flag).
359
360   myView->Camera()->ZFitAll (theScaleFactor, aMinMaxBox, aGraphicBox);
361 }
362
363 //=============================================================================
364 //function : IsEmpty
365 //purpose  :
366 //=============================================================================
367 Standard_Boolean V3d_View::IsEmpty() const
368 {
369   Standard_Boolean TheStatus = Standard_True ;
370   if( myView->IsDefined() ) {
371     Standard_Integer Nstruct = myView->NumberOfDisplayedStructures() ;
372     if( Nstruct > 0 ) TheStatus = Standard_False ;
373   }
374   return (TheStatus) ;
375 }
376
377 //=============================================================================
378 //function : UpdateLights
379 //purpose  :
380 //=============================================================================
381 void V3d_View::UpdateLights() const
382 {
383   Graphic3d_ListOfCLight aLights;
384   for (V3d_ListOfLight::Iterator anActiveLightIter (myActiveLights); anActiveLightIter.More(); anActiveLightIter.Next())
385   {
386     aLights.Append (anActiveLightIter.Value()->Light());
387   }
388   myView->SetLights (aLights);
389   Update();
390 }
391
392 //=============================================================================
393 //function : DoMapping
394 //purpose  :
395 //=============================================================================
396 void V3d_View::DoMapping()
397 {
398   if (!myView->IsDefined())
399   {
400     return;
401   }
402
403   myView->Window()->DoMapping();
404 }
405
406 //=============================================================================
407 //function : MustBeResized
408 //purpose  :
409 //=============================================================================
410 void V3d_View::MustBeResized()
411 {
412   if (!myView->IsDefined())
413   {
414     return;
415   }
416
417   myView->Resized();
418
419   SetRatio();
420
421   Redraw();
422 }
423
424 //=============================================================================
425 //function : SetBackgroundColor
426 //purpose  :
427 //=============================================================================
428 void V3d_View::SetBackgroundColor (const Quantity_TypeOfColor theType,
429                                    const Standard_Real theV1,
430                                    const Standard_Real theV2,
431                                    const Standard_Real theV3)
432 {
433   Standard_Real aV1 = Max (Min (theV1, 1.0), 0.0);
434   Standard_Real aV2 = Max (Min (theV2, 1.0), 0.0);
435   Standard_Real aV3 = Max (Min (theV3, 1.0), 0.0);
436
437   SetBackgroundColor (Quantity_Color (aV1, aV2, aV3, theType));
438 }
439
440 //=============================================================================
441 //function : SetBackgroundColor
442 //purpose  :
443 //=============================================================================
444 void V3d_View::SetBackgroundColor (const Quantity_Color& theColor)
445 {
446   myView->SetBackground (Aspect_Background (theColor));
447
448   if (myImmediateUpdate)
449   {
450     Redraw();
451   }
452 }
453
454 //=============================================================================
455 //function : SetBgGradientColors
456 //purpose  :
457 //=============================================================================
458 void V3d_View::SetBgGradientColors (const Quantity_Color& theColor1,
459                                     const Quantity_Color& theColor2,
460                                     const Aspect_GradientFillMethod theFillStyle,
461                                     const Standard_Boolean theToUpdate)
462 {
463   Aspect_GradientBackground aGradientBg (theColor1, theColor2, theFillStyle);
464
465   myView->SetGradientBackground (aGradientBg);
466
467   if (myImmediateUpdate || theToUpdate)
468   {
469     Redraw();
470   }
471 }
472
473 //=============================================================================
474 //function : SetBgGradientStyle
475 //purpose  :
476 //=============================================================================
477 void V3d_View::SetBgGradientStyle (const Aspect_GradientFillMethod theFillStyle, const Standard_Boolean theToUpdate)
478 {
479   Quantity_Color aColor1;
480   Quantity_Color aColor2;
481   GradientBackground().Colors (aColor1, aColor2);
482
483   SetBgGradientColors (aColor1, aColor2, theFillStyle, theToUpdate);
484 }
485
486 //=============================================================================
487 //function : SetBackgroundImage
488 //purpose  :
489 //=============================================================================
490 void V3d_View::SetBackgroundImage (const Standard_CString theFileName,
491                                    const Aspect_FillMethod theFillStyle,
492                                    const Standard_Boolean theToUpdate)
493 {
494   myView->SetBackgroundImage (theFileName);
495   myView->SetBackgroundImageStyle (theFillStyle);
496
497   if (myImmediateUpdate || theToUpdate)
498   {
499     Redraw();
500   }
501 }
502
503 //=============================================================================
504 //function : SetBgImageStyle
505 //purpose  :
506 //=============================================================================
507 void V3d_View::SetBgImageStyle (const Aspect_FillMethod theFillStyle, const Standard_Boolean theToUpdate)
508 {
509   myView->SetBackgroundImageStyle (theFillStyle);
510
511   if (myImmediateUpdate || theToUpdate)
512   {
513     Redraw();
514   }
515 }
516
517 //=============================================================================
518 //function : SetAxis
519 //purpose  :
520 //=============================================================================
521 void V3d_View::SetAxis(const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Real Vx, const Standard_Real Vy, const Standard_Real Vz)
522 {
523   Standard_Real D,Nx = Vx,Ny = Vy,Nz = Vz ;
524
525   D = Sqrt( Vx*Vx + Vy*Vy + Vz*Vz ) ;
526   V3d_BadValue_Raise_if ( D <= 0. , "V3d_View::SetAxis, bad axis");
527   Nx /= D ; Ny /= D ; Nz /= D ;
528   MyDefaultViewPoint.SetCoord(X,Y,Z) ;
529   MyDefaultViewAxis.SetCoord(Nx,Ny,Nz) ;
530 }
531
532 //=============================================================================
533 //function : SetShadingModel
534 //purpose  :
535 //=============================================================================
536 void V3d_View::SetShadingModel (const V3d_TypeOfShadingModel theShadingModel)
537 {
538   myView->SetShadingModel (static_cast<Graphic3d_TypeOfShadingModel> (theShadingModel));
539 }
540
541 //=============================================================================
542 //function : SetTextureEnv
543 //purpose  :
544 //=============================================================================
545 void V3d_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTexture)
546 {
547   myView->SetTextureEnv (theTexture);
548
549   if (myImmediateUpdate)
550   {
551     Redraw();
552   }
553 }
554
555 //=============================================================================
556 //function : SetVisualization
557 //purpose  :
558 //=============================================================================
559 void V3d_View::SetVisualization (const V3d_TypeOfVisualization theType)
560 {
561   myView->SetVisualizationType (static_cast <Graphic3d_TypeOfVisualization> (theType));
562
563   if (myImmediateUpdate)
564   {
565     Redraw();
566   }
567 }
568
569 //=============================================================================
570 //function : SetFront
571 //purpose  :
572 //=============================================================================
573 void V3d_View::SetFront()
574 {
575   gp_Ax3 a = MyViewer->PrivilegedPlane();
576   Standard_Real xo, yo, zo, vx, vy, vz, xu, yu, zu;
577
578   a.Direction().Coord(vx,vy,vz);
579   a.YDirection().Coord(xu,yu,zu);
580   a.Location().Coord(xo,yo,zo);
581
582   Handle(Graphic3d_Camera) aCamera = Camera();
583
584   aCamera->SetCenter (gp_Pnt (xo, yo, zo));
585
586   if(SwitchSetFront)
587   {
588     aCamera->SetDirection (gp_Dir (vx, vy, vz));
589   }
590   else
591   {
592     aCamera->SetDirection (gp_Dir (vx, vy, vz).Reversed());
593   }
594
595   aCamera->SetUp (gp_Dir (xu, yu, zu));
596
597   AutoZFit();
598
599   SwitchSetFront = !SwitchSetFront;
600
601   ImmediateUpdate();
602 }
603
604 //=============================================================================
605 //function : Rotate
606 //purpose  :
607 //=============================================================================
608 void V3d_View::Rotate (const Standard_Real ax, 
609                        const Standard_Real ay, 
610                        const Standard_Real az, 
611                        const Standard_Boolean Start)
612 {
613   Standard_Real Ax = ax;
614   Standard_Real Ay = ay;
615   Standard_Real Az = az;
616
617   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI;
618   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI;
619   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI;
620   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI;
621   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI;
622   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI;
623
624   Handle(Graphic3d_Camera) aCamera = Camera();
625
626   if (Start)
627   {
628     myCamStartOpUp     = aCamera->Up();
629     myCamStartOpEye    = aCamera->Eye();
630     myCamStartOpCenter = aCamera->Center();
631   }
632
633   aCamera->SetUp     (myCamStartOpUp);
634   aCamera->SetEye    (myCamStartOpEye);
635   aCamera->SetCenter (myCamStartOpCenter);
636
637   // rotate camera around 3 initial axes
638   gp_Dir aBackDir (gp_Vec (myCamStartOpCenter, myCamStartOpEye));
639   gp_Dir aXAxis (myCamStartOpUp.Crossed (aBackDir));
640   gp_Dir aYAxis (aBackDir.Crossed (aXAxis));
641   gp_Dir aZAxis (aXAxis.Crossed (aYAxis));
642
643   gp_Trsf aRot[3], aTrsf;
644   aRot[0].SetRotation (gp_Ax1 (myCamStartOpCenter, aYAxis), -Ax);
645   aRot[1].SetRotation (gp_Ax1 (myCamStartOpCenter, aXAxis), Ay);
646   aRot[2].SetRotation (gp_Ax1 (myCamStartOpCenter, aZAxis), Az);
647   aTrsf.Multiply (aRot[0]);
648   aTrsf.Multiply (aRot[1]);
649   aTrsf.Multiply (aRot[2]);
650
651   aCamera->Transform (aTrsf);
652
653   AutoZFit();
654
655   ImmediateUpdate();
656 }
657
658 //=============================================================================
659 //function : Rotate
660 //purpose  :
661 //=============================================================================
662 void V3d_View::Rotate(const Standard_Real ax, const Standard_Real ay, const Standard_Real az,
663                       const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Boolean Start)
664 {
665
666   Standard_Real Ax = ax ;
667   Standard_Real Ay = ay ;
668   Standard_Real Az = az ;
669
670   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI ;
671   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI ;
672   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI ;
673   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI ;
674   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI ;
675   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI ;
676
677   Handle(Graphic3d_Camera) aCamera = Camera();
678
679   if (Start)
680   {
681     myGravityReferencePoint.SetCoord (X, Y, Z);
682     myCamStartOpUp     = aCamera->Up();
683     myCamStartOpEye    = aCamera->Eye();
684     myCamStartOpCenter = aCamera->Center();
685   }
686
687   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
688
689   aCamera->SetUp     (myCamStartOpUp);
690   aCamera->SetEye    (myCamStartOpEye);
691   aCamera->SetCenter (myCamStartOpCenter);
692
693   // rotate camera around 3 initial axes
694   gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z());
695
696   gp_Dir aZAxis (aCamera->Direction().Reversed());
697   gp_Dir aYAxis (aCamera->Up());
698   gp_Dir aXAxis (aYAxis.Crossed (aZAxis)); 
699
700   gp_Trsf aRot[3], aTrsf;
701   aRot[0].SetRotation (gp_Ax1 (aRCenter, aYAxis), -Ax);
702   aRot[1].SetRotation (gp_Ax1 (aRCenter, aXAxis), Ay);
703   aRot[2].SetRotation (gp_Ax1 (aRCenter, aZAxis), Az);
704   aTrsf.Multiply (aRot[0]);
705   aTrsf.Multiply (aRot[1]);
706   aTrsf.Multiply (aRot[2]);
707
708   aCamera->Transform (aTrsf);
709
710   AutoZFit();
711
712   ImmediateUpdate();
713 }
714
715 //=============================================================================
716 //function : Rotate
717 //purpose  :
718 //=============================================================================
719 void V3d_View::Rotate(const V3d_TypeOfAxe Axe, const Standard_Real angle, const Standard_Boolean Start)
720 {
721   switch (Axe) {
722   case V3d_X :
723     Rotate(angle,0.,0.,Start);
724     break ;
725   case V3d_Y :
726     Rotate(0.,angle,0.,Start);
727     break ;
728   case V3d_Z :
729     Rotate(0.,0.,angle,Start);
730     break ;
731   }
732 }
733
734 //=============================================================================
735 //function : Rotate
736 //purpose  :
737 //=============================================================================
738 void V3d_View::Rotate(const V3d_TypeOfAxe Axe, const Standard_Real angle,
739                       const Standard_Real X, const Standard_Real Y, const Standard_Real Z, const Standard_Boolean Start)
740 {
741   Standard_Real Angle = angle ;
742
743   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
744   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
745
746   Handle(Graphic3d_Camera) aCamera = Camera();
747
748   if (Start)
749   {
750     myGravityReferencePoint.SetCoord (X, Y, Z);
751     myCamStartOpUp     = aCamera->Up();
752     myCamStartOpEye    = aCamera->Eye();
753     myCamStartOpCenter = aCamera->Center();
754
755     switch (Axe) {
756     case V3d_X :
757       myViewAxis.SetCoord(1.,0.,0.) ;
758       break ;
759     case V3d_Y :
760       myViewAxis.SetCoord(0.,1.,0.) ;
761       break ;
762     case V3d_Z :
763       myViewAxis.SetCoord(0.,0.,1.) ;
764       break ;
765     }
766
767     myCamStartOpUp     = aCamera->Up();
768     myCamStartOpEye    = aCamera->Eye();
769     myCamStartOpCenter = aCamera->Center();
770   }
771
772   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
773
774   aCamera->SetUp     (myCamStartOpUp);
775   aCamera->SetEye    (myCamStartOpEye);
776   aCamera->SetCenter (myCamStartOpCenter);
777
778   // rotate camera around passed axis
779   gp_Trsf aRotation;
780   gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z());
781   gp_Dir aRAxis ((Axe == V3d_X) ? 1.0 : 0.0,
782                   (Axe == V3d_Y) ? 1.0 : 0.0,
783                   (Axe == V3d_Z) ? 1.0 : 0.0);
784
785   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
786
787   aCamera->Transform (aRotation);
788
789   AutoZFit();
790
791   ImmediateUpdate();
792 }
793
794 //=============================================================================
795 //function : Rotate
796 //purpose  :
797 //=============================================================================
798 void V3d_View::Rotate(const Standard_Real angle, const Standard_Boolean Start)
799 {
800   Standard_Real Angle = angle;
801
802   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
803   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
804
805   Handle(Graphic3d_Camera) aCamera = Camera();
806
807   if( Start ) {
808     myCamStartOpUp     = aCamera->Up();
809     myCamStartOpEye    = aCamera->Eye();
810     myCamStartOpCenter = aCamera->Center();
811   }
812
813   const Graphic3d_Vertex& aPnt = MyDefaultViewPoint;
814   const Graphic3d_Vector& anAxis = MyDefaultViewAxis;
815
816   aCamera->SetUp     (myCamStartOpUp);
817   aCamera->SetEye    (myCamStartOpEye);
818   aCamera->SetCenter (myCamStartOpCenter);
819
820   gp_Trsf aRotation;
821   gp_Pnt aRCenter (aPnt.X(), aPnt.Y(), aPnt.Z());
822   gp_Dir aRAxis (anAxis.X(), anAxis.Y(), anAxis.Z());
823   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
824
825   aCamera->Transform (aRotation);
826
827   AutoZFit();
828
829   ImmediateUpdate();
830 }
831
832 //=============================================================================
833 //function : Turn
834 //purpose  :
835 //=============================================================================
836 void V3d_View::Turn(const Standard_Real ax, const Standard_Real ay, const Standard_Real az, const Standard_Boolean Start)
837 {
838   Standard_Real Ax = ax;
839   Standard_Real Ay = ay;
840   Standard_Real Az = az;
841
842   if( Ax > 0. ) while ( Ax > DEUXPI ) Ax -= DEUXPI ;
843   else if( Ax < 0. ) while ( Ax < -DEUXPI ) Ax += DEUXPI ;
844   if( Ay > 0. ) while ( Ay > DEUXPI ) Ay -= DEUXPI ;
845   else if( Ay < 0. ) while ( Ay < -DEUXPI ) Ay += DEUXPI ;
846   if( Az > 0. ) while ( Az > DEUXPI ) Az -= DEUXPI ;
847   else if( Az < 0. ) while ( Az < -DEUXPI ) Az += DEUXPI ;
848
849   Handle(Graphic3d_Camera) aCamera = Camera();
850
851   if( Start ) {
852     myCamStartOpUp     = aCamera->Up();
853     myCamStartOpEye    = aCamera->Eye();
854     myCamStartOpCenter = aCamera->Center();
855   }
856
857   aCamera->SetUp     (myCamStartOpUp);
858   aCamera->SetEye    (myCamStartOpEye);
859   aCamera->SetCenter (myCamStartOpCenter);
860
861   // rotate camera around 3 initial axes
862   gp_Pnt aRCenter = aCamera->Eye();
863   gp_Dir aZAxis (aCamera->Direction().Reversed());
864   gp_Dir aYAxis (aCamera->Up());
865   gp_Dir aXAxis (aYAxis.Crossed (aZAxis)); 
866
867   gp_Trsf aRot[3], aTrsf;
868   aRot[0].SetRotation (gp_Ax1 (aRCenter, aYAxis), -Ax);
869   aRot[1].SetRotation (gp_Ax1 (aRCenter, aXAxis), Ay);
870   aRot[2].SetRotation (gp_Ax1 (aRCenter, aZAxis), Az);
871   aTrsf.Multiply (aRot[0]);
872   aTrsf.Multiply (aRot[1]);
873   aTrsf.Multiply (aRot[2]);
874
875   aCamera->Transform (aTrsf);
876
877   AutoZFit();
878
879   ImmediateUpdate();
880 }
881
882 //=============================================================================
883 //function : Turn
884 //purpose  :
885 //=============================================================================
886 void V3d_View::Turn(const V3d_TypeOfAxe Axe, const Standard_Real angle, const Standard_Boolean Start)
887 {
888   switch (Axe) {
889   case V3d_X :
890     Turn(angle,0.,0.,Start);
891     break ;
892   case V3d_Y :
893     Turn(0.,angle,0.,Start);
894     break ;
895   case V3d_Z :
896     Turn(0.,0.,angle,Start);
897     break ;
898   }
899 }
900
901 //=============================================================================
902 //function : Turn
903 //purpose  :
904 //=============================================================================
905 void V3d_View::Turn(const Standard_Real angle, const Standard_Boolean Start)
906 {
907   Standard_Real Angle = angle ;
908
909   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
910   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
911
912   Handle(Graphic3d_Camera) aCamera = Camera();
913
914   if( Start ) {
915     myCamStartOpUp     = aCamera->Up();
916     myCamStartOpEye    = aCamera->Eye();
917     myCamStartOpCenter = aCamera->Center();
918   }
919
920   aCamera->SetUp     (myCamStartOpUp);
921   aCamera->SetEye    (myCamStartOpEye);
922   aCamera->SetCenter (myCamStartOpCenter);
923
924   const Graphic3d_Vector& anAxis = MyDefaultViewAxis;
925
926   gp_Trsf aRotation;
927   gp_Pnt aRCenter = aCamera->Eye();
928   gp_Dir aRAxis (anAxis.X(), anAxis.Y(), anAxis.Z());
929   aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
930
931   aCamera->Transform (aRotation);
932
933   AutoZFit();
934
935   ImmediateUpdate();
936 }
937
938 //=============================================================================
939 //function : SetTwist
940 //purpose  :
941 //=============================================================================
942 void V3d_View::SetTwist(const Standard_Real angle)
943 {
944   Standard_Real Angle = angle ;
945   Standard_Boolean TheStatus;
946
947   if( Angle > 0. ) while ( Angle > DEUXPI ) Angle -= DEUXPI ;
948   else if( Angle < 0. ) while ( Angle < -DEUXPI ) Angle += DEUXPI ;
949
950   Handle(Graphic3d_Camera) aCamera = Camera();
951
952   gp_Dir aReferencePlane (aCamera->Direction().Reversed());
953   gp_Dir anUp;
954
955   anUp = gp_Dir (0.0, 0.0, 1.0);
956
957   TheStatus = ScreenAxis(aReferencePlane, anUp,
958     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
959   if( !TheStatus ) {
960     anUp = gp_Dir (0.0, 1.0, 0.0);
961     TheStatus = ScreenAxis(aReferencePlane, anUp,
962       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
963   }
964   if( !TheStatus ) {
965     anUp = gp_Dir (1.0, 0.0, 0.0);
966     TheStatus = ScreenAxis(aReferencePlane, anUp,
967       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
968   }
969
970   V3d_BadValue_Raise_if( !TheStatus,"V3d_ViewSetTwist, alignment of Eye,At,Up,");
971   
972   gp_Pnt aRCenter = aCamera->Center();
973   gp_Dir aZAxis (aCamera->Direction().Reversed());
974
975   gp_Trsf aTrsf;
976   aTrsf.SetRotation (gp_Ax1 (aRCenter, aZAxis), Angle);
977
978   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
979   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
980
981   aCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
982   aCamera->Transform (aTrsf);
983
984   AutoZFit();
985
986   ImmediateUpdate();
987 }
988
989 //=============================================================================
990 //function : SetEye
991 //purpose  :
992 //=============================================================================
993 void V3d_View::SetEye(const Standard_Real X,const Standard_Real Y,const Standard_Real Z)
994 {
995   Standard_Real aTwistBefore = Twist();
996
997   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
998
999   Handle(Graphic3d_Camera) aCamera = Camera();
1000
1001   aCamera->SetEye (gp_Pnt (X, Y, Z));
1002
1003   SetTwist (aTwistBefore);
1004
1005   AutoZFit();
1006
1007   SetImmediateUpdate (wasUpdateEnabled);
1008
1009   ImmediateUpdate();
1010 }
1011
1012 //=============================================================================
1013 //function : SetDepth
1014 //purpose  :
1015 //=============================================================================
1016 void V3d_View::SetDepth(const Standard_Real Depth)
1017 {
1018   V3d_BadValue_Raise_if (Depth == 0. ,"V3d_View::SetDepth, bad depth");
1019
1020   Handle(Graphic3d_Camera) aCamera = Camera();
1021
1022   if( Depth > 0. )
1023   {
1024     // Move eye using center (target) as anchor.
1025     aCamera->SetDistance (Depth);
1026   }
1027   else
1028   {
1029     // Move the view ref point instead of the eye.
1030     gp_Vec aDir (aCamera->Direction());
1031     gp_Pnt aCameraEye = aCamera->Eye();
1032     gp_Pnt aCameraCenter = aCameraEye.Translated (aDir.Multiplied (Abs (Depth)));
1033
1034     aCamera->SetCenter (aCameraCenter);
1035   }
1036
1037   AutoZFit();
1038
1039   ImmediateUpdate();
1040 }
1041
1042 //=============================================================================
1043 //function : SetProj
1044 //purpose  :
1045 //=============================================================================
1046 void V3d_View::SetProj( const Standard_Real Vx,const Standard_Real Vy, const Standard_Real Vz )
1047 {
1048   V3d_BadValue_Raise_if( Sqrt(Vx*Vx + Vy*Vy + Vz*Vz) <= 0.,
1049     "V3d_View::SetProj, null projection vector");
1050
1051   Standard_Real aTwistBefore = Twist();
1052
1053   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1054
1055   Camera()->SetDirection (gp_Dir (Vx, Vy, Vz).Reversed());
1056
1057   SetTwist(aTwistBefore);
1058
1059   AutoZFit();
1060
1061   SetImmediateUpdate (wasUpdateEnabled);
1062
1063   ImmediateUpdate();
1064 }
1065
1066 //=============================================================================
1067 //function : SetProj
1068 //purpose  :
1069 //=============================================================================
1070 void V3d_View::SetProj( const V3d_TypeOfOrientation Orientation )
1071 {
1072   Standard_Real Xpn=0;
1073   Standard_Real Ypn=0;
1074   Standard_Real Zpn=0;
1075
1076   switch (Orientation) {
1077   case V3d_Zpos :
1078     Ypn = 1.;
1079     break;
1080   case V3d_Zneg :
1081     Ypn = -1.;
1082     break;
1083   default:
1084     Zpn = 1.;
1085   }
1086
1087   const Graphic3d_Vector& aBck = V3d::GetProjAxis (Orientation);
1088
1089   // retain camera panning from origin when switching projection
1090   Handle(Graphic3d_Camera) aCamera = Camera();
1091
1092   gp_Pnt anOriginVCS  = aCamera->ConvertWorld2View (gp::Origin());
1093   Standard_Real aPanX = anOriginVCS.X();
1094   Standard_Real aPanY = anOriginVCS.Y();
1095
1096   aCamera->SetCenter (gp_Pnt (0, 0, 0));
1097   aCamera->SetDirection (gp_Dir (aBck.X(), aBck.Y(), aBck.Z()).Reversed());
1098   aCamera->SetUp (gp_Dir (Xpn, Ypn, Zpn));
1099   aCamera->OrthogonalizeUp();
1100
1101   Panning (aPanX, aPanY);
1102
1103   AutoZFit();
1104
1105   ImmediateUpdate();
1106 }
1107
1108 //=============================================================================
1109 //function : SetAt
1110 //purpose  :
1111 //=============================================================================
1112 void V3d_View::SetAt(const Standard_Real X,const Standard_Real Y,const Standard_Real Z)
1113 {
1114   Standard_Real aTwistBefore = Twist();
1115
1116   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1117
1118   Camera()->SetCenter (gp_Pnt (X, Y, Z));
1119
1120   SetTwist (aTwistBefore);
1121
1122   AutoZFit();
1123
1124   SetImmediateUpdate (wasUpdateEnabled);
1125
1126   ImmediateUpdate();
1127 }
1128
1129 //=============================================================================
1130 //function : SetUp
1131 //purpose  :
1132 //=============================================================================
1133 void V3d_View::SetUp(const Standard_Real Vx,const Standard_Real Vy,const Standard_Real Vz)
1134 {
1135   Standard_Boolean TheStatus ;
1136   V3d_BadValue_Raise_if( Sqrt(Vx*Vx + Vy*Vy + Vz*Vz) <= 0. ,
1137     "V3d_View::SetUp, nullUp vector");
1138
1139   Handle(Graphic3d_Camera) aCamera = Camera();
1140
1141   gp_Dir aReferencePlane (aCamera->Direction().Reversed());
1142   gp_Dir anUp (Vx, Vy, Vz);
1143
1144   TheStatus = ScreenAxis(aReferencePlane,anUp,
1145     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1146   if( !TheStatus ) {
1147     anUp = gp_Dir (0.0, 0.0, 1.0);
1148     TheStatus = ScreenAxis(aReferencePlane,anUp,
1149       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1150   }
1151   if( !TheStatus ) {
1152     anUp = gp_Dir (0.0, 1.0, 0.0);
1153     TheStatus = ScreenAxis(aReferencePlane,anUp,
1154       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1155   }
1156   if( !TheStatus ) {
1157     anUp = gp_Dir (1.0, 0.0, 0.0);
1158     TheStatus = ScreenAxis(aReferencePlane,anUp,
1159       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1160   }
1161   V3d_BadValue_Raise_if( !TheStatus,"V3d_View::Setup, alignment of Eye,At,Up");
1162
1163   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
1164   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
1165
1166   aCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
1167
1168   AutoZFit();
1169
1170   ImmediateUpdate();
1171 }
1172
1173 //=============================================================================
1174 //function : SetUp
1175 //purpose  :
1176 //=============================================================================
1177 void V3d_View::SetUp( const V3d_TypeOfOrientation Orientation )
1178 {
1179   Standard_Boolean TheStatus ;
1180
1181   Handle(Graphic3d_Camera) aCamera = Camera();
1182
1183   gp_Dir aReferencePlane (aCamera->Direction().Reversed());
1184   gp_Dir anUp;
1185
1186   const Graphic3d_Vector& aViewReferenceUp = V3d::GetProjAxis(Orientation) ;
1187   anUp = gp_Dir (aViewReferenceUp.X(), aViewReferenceUp.Y(), aViewReferenceUp.Z());
1188
1189   TheStatus = ScreenAxis(aReferencePlane,anUp,
1190     myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1191   if( !TheStatus ) {
1192     anUp = gp_Dir (0.,0.,1.);
1193     TheStatus = ScreenAxis(aReferencePlane,anUp,
1194       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1195   }
1196   if( !TheStatus ) {
1197     anUp = gp_Dir (0.,1.,0.);
1198     TheStatus = ScreenAxis(aReferencePlane,anUp,
1199       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1200   }
1201   if( !TheStatus ) {
1202     anUp = gp_Dir (1.,0.,0.);
1203     TheStatus = ScreenAxis(aReferencePlane,anUp,
1204       myXscreenAxis,myYscreenAxis,myZscreenAxis) ;
1205   }
1206   V3d_BadValue_Raise_if( !TheStatus, "V3d_View::SetUp, alignment of Eye,At,Up");
1207
1208   Standard_Real myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ;
1209   myYscreenAxis.Coord (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ);
1210
1211   aCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
1212
1213   AutoZFit();
1214
1215   ImmediateUpdate();
1216 }
1217
1218 //=============================================================================
1219 //function : SetViewOrientationDefault
1220 //purpose  :
1221 //=============================================================================
1222 void V3d_View::SetViewOrientationDefault()
1223 {
1224   myDefaultCamera->CopyOrientationData (Camera());
1225 }
1226
1227 //=======================================================================
1228 //function : SetViewMappingDefault
1229 //purpose  :
1230 //=======================================================================
1231 void V3d_View::SetViewMappingDefault()
1232 {
1233   myDefaultCamera->CopyMappingData (Camera());
1234 }
1235
1236 //=============================================================================
1237 //function : ResetViewOrientation
1238 //purpose  :
1239 //=============================================================================
1240 void V3d_View::ResetViewOrientation()
1241 {
1242   Camera()->CopyOrientationData (myDefaultCamera);
1243
1244   AutoZFit();
1245
1246   ImmediateUpdate();
1247 }
1248
1249 //=======================================================================
1250 //function : ResetViewMapping
1251 //purpose  :
1252 //=======================================================================
1253 void V3d_View::ResetViewMapping()
1254 {
1255   Camera()->CopyMappingData (myDefaultCamera);
1256
1257   AutoZFit();
1258
1259   ImmediateUpdate();
1260 }
1261
1262 //=============================================================================
1263 //function : Reset
1264 //purpose  :
1265 //=============================================================================
1266 void V3d_View::Reset (const Standard_Boolean theToUpdate)
1267 {
1268   Camera()->Copy (myDefaultCamera);
1269
1270   AutoZFit();
1271
1272   SwitchSetFront = Standard_False;
1273
1274   if (myImmediateUpdate || theToUpdate)
1275   {
1276     Update();
1277   }
1278 }
1279
1280 //=======================================================================
1281 //function : SetCenter
1282 //purpose  :
1283 //=======================================================================
1284 void V3d_View::SetCenter (const Standard_Integer theXp,
1285                           const Standard_Integer theYp)
1286 {
1287   Standard_Real aXv, aYv;
1288   Convert (theXp, theYp, aXv, aYv);
1289   Translate (Camera(), aXv, aYv);
1290
1291   ImmediateUpdate();
1292 }
1293
1294 //=============================================================================
1295 //function : SetSize
1296 //purpose  :
1297 //=============================================================================
1298 void V3d_View::SetSize (const Standard_Real theSize)
1299 {
1300   V3d_BadValue_Raise_if (theSize <= 0.0, "V3d_View::SetSize, Window Size is NULL");
1301
1302   Handle(Graphic3d_Camera) aCamera = Camera();
1303
1304   aCamera->SetScale (aCamera->Aspect() >= 1.0 ? theSize / aCamera->Aspect() : theSize);
1305
1306   AutoZFit();
1307
1308   ImmediateUpdate();
1309 }
1310
1311 //=============================================================================
1312 //function : SetZSize
1313 //purpose  :
1314 //=============================================================================
1315 void V3d_View::SetZSize (const Standard_Real theSize)
1316 {
1317   Handle(Graphic3d_Camera) aCamera = Camera();
1318
1319   Standard_Real Zmax = theSize / 2.;
1320
1321   Standard_Real aDistance = aCamera->Distance();
1322
1323   if (theSize <= 0.)
1324   {
1325     Zmax = aDistance;
1326   }
1327
1328   // ShortReal precision factor used to add meaningful tolerance to
1329   // ZNear, ZFar values in order to avoid equality after type conversion
1330   // to ShortReal matrices type.
1331   const Standard_Real aPrecision = 1.0 / Pow (10.0, ShortRealDigits() - 1);
1332
1333   Standard_Real aZFar  =  Zmax  + aDistance * 2.0;
1334   Standard_Real aZNear = -Zmax  + aDistance;
1335   aZNear              -= Abs (aZNear) * aPrecision;
1336   aZFar               += Abs (aZFar)  * aPrecision;
1337
1338   if (!aCamera->IsOrthographic())
1339   {
1340     if (aZFar < aPrecision)
1341     {
1342       // Invalid case when both values are negative
1343       aZNear = aPrecision;
1344       aZFar  = aPrecision * 2.0;
1345     }
1346     else if (aZNear < Abs (aZFar) * aPrecision)
1347     {
1348       // Z is less than 0.0, try to fix it using any appropriate z-scale
1349       aZNear = Abs (aZFar) * aPrecision;
1350     }
1351   }
1352
1353   // If range is too small
1354   if (aZFar < (aZNear + Abs (aZFar) * aPrecision))
1355   {
1356     aZFar = aZNear + Abs (aZFar) * aPrecision;
1357   }
1358
1359   aCamera->SetZRange (aZNear, aZFar);
1360
1361   if (myImmediateUpdate)
1362   {
1363     Redraw();
1364   }
1365 }
1366
1367 //=============================================================================
1368 //function : SetZoom
1369 //purpose  :
1370 //=============================================================================
1371 void V3d_View::SetZoom (const Standard_Real theCoef,const Standard_Boolean theToStart)
1372 {
1373   V3d_BadValue_Raise_if (theCoef <= 0., "V3d_View::SetZoom, bad coefficient");
1374
1375   Handle(Graphic3d_Camera) aCamera = Camera();
1376
1377   if (theToStart)
1378   {
1379     myCamStartOpEye    = aCamera->Eye();
1380     myCamStartOpCenter = aCamera->Center();
1381   }
1382
1383   Standard_Real aViewWidth  = aCamera->ViewDimensions().X();
1384   Standard_Real aViewHeight = aCamera->ViewDimensions().Y();
1385
1386   // ensure that zoom will not be too small or too big
1387   Standard_Real aCoef = theCoef;
1388   if (aViewWidth < aCoef * Precision::Confusion())
1389   {
1390     aCoef = aViewWidth / Precision::Confusion();
1391   }
1392   else if (aViewWidth > aCoef * 1e12)
1393   {
1394     aCoef = aViewWidth / 1e12;
1395   }
1396   if (aViewHeight < aCoef * Precision::Confusion())
1397   {
1398     aCoef = aViewHeight / Precision::Confusion();
1399   }
1400   else if (aViewHeight > aCoef * 1e12)
1401   {
1402     aCoef = aViewHeight / 1e12;
1403   }
1404
1405   aCamera->SetEye (myCamStartOpEye);
1406   aCamera->SetCenter (myCamStartOpCenter);
1407   aCamera->SetScale (aCamera->Scale() / aCoef);
1408
1409   AutoZFit();
1410
1411   ImmediateUpdate();
1412 }
1413
1414 //=============================================================================
1415 //function : SetScale
1416 //purpose  :
1417 //=============================================================================
1418 void V3d_View::SetScale( const Standard_Real Coef )
1419 {
1420   V3d_BadValue_Raise_if( Coef <= 0. ,"V3d_View::SetScale, bad coefficient");
1421
1422   Handle(Graphic3d_Camera) aCamera = Camera();
1423
1424   Standard_Real aDefaultScale = myDefaultCamera->Scale();
1425   aCamera->SetAspect (myDefaultCamera->Aspect());
1426   aCamera->SetScale (aDefaultScale / Coef);
1427
1428   AutoZFit();
1429
1430   ImmediateUpdate();
1431 }
1432
1433 //=============================================================================
1434 //function : SetAxialScale
1435 //purpose  :
1436 //=============================================================================
1437 void V3d_View::SetAxialScale( const Standard_Real Sx, const Standard_Real Sy, const Standard_Real Sz )
1438 {
1439   V3d_BadValue_Raise_if( Sx <= 0. || Sy <= 0. || Sz <= 0.,"V3d_View::SetAxialScale, bad coefficient");
1440
1441   Camera()->SetAxialScale (gp_XYZ (Sx, Sy, Sz));
1442
1443   AutoZFit();
1444 }
1445
1446 //=============================================================================
1447 //function : SetRatio
1448 //purpose  :
1449 //=============================================================================
1450 void V3d_View::SetRatio()
1451 {
1452   if (MyWindow.IsNull())
1453   {
1454     return;
1455   }
1456
1457   Standard_Integer aWidth  = 0;
1458   Standard_Integer aHeight = 0;
1459   MyWindow->Size (aWidth, aHeight);
1460   if (aWidth > 0 && aHeight > 0)
1461   {
1462     Standard_Real aRatio = static_cast<Standard_Real> (aWidth) /
1463                            static_cast<Standard_Real> (aHeight);
1464
1465     Camera()       ->SetAspect (aRatio);
1466     myDefaultCamera->SetAspect (aRatio);
1467   }
1468 }
1469
1470 //=============================================================================
1471 //function : FitAll
1472 //purpose  :
1473 //=============================================================================
1474 void V3d_View::FitAll (const Standard_Real theMargin, const Standard_Boolean theToUpdate)
1475 {
1476   FitAll (myView->MinMaxValues(), theMargin, theToUpdate);
1477 }
1478
1479 //=============================================================================
1480 //function : FitAll
1481 //purpose  :
1482 //=============================================================================
1483 void V3d_View::FitAll (const Bnd_Box& theBox, const Standard_Real theMargin, const Standard_Boolean theToUpdate)
1484 {
1485   Standard_ASSERT_RAISE(theMargin >= 0.0 && theMargin < 1.0, "Invalid margin coefficient");
1486
1487   if (myView->NumberOfDisplayedStructures() == 0)
1488   {
1489     return;
1490   }
1491
1492   if (!FitMinMax (Camera(), theBox, theMargin, 10.0 * Precision::Confusion()))
1493   {
1494     return;
1495   }
1496
1497   AutoZFit();
1498
1499   if (myImmediateUpdate || theToUpdate)
1500   {
1501     Update();
1502   }
1503 }
1504
1505 //=============================================================================
1506 //function : DepthFitAll
1507 //purpose  :
1508 //=============================================================================
1509 void V3d_View::DepthFitAll(const Standard_Real Aspect,
1510                            const Standard_Real Margin)
1511 {
1512   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,U,V,W,U1,V1,W1 ;
1513   Standard_Real Umin,Vmin,Wmin,Umax,Vmax,Wmax ;
1514   Standard_Real Dx,Dy,Dz,Size;
1515
1516   Standard_Integer Nstruct = myView->NumberOfDisplayedStructures() ;
1517
1518   if((Nstruct <= 0) || (Aspect < 0.) || (Margin < 0.) || (Margin > 1.)) {
1519     ImmediateUpdate();
1520     return ;
1521   }
1522
1523   Bnd_Box aBox = myView->MinMaxValues();
1524   if (aBox.IsVoid())
1525   {
1526     ImmediateUpdate();
1527     return ;
1528   }
1529     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
1530     Project (Xmin,Ymin,Zmin,U,V,W) ;
1531     Project (Xmax,Ymax,Zmax,U1,V1,W1) ;
1532     Umin = Min(U,U1) ; Umax = Max(U,U1) ;
1533     Vmin = Min(V,V1) ; Vmax = Max(V,V1) ;
1534     Wmin = Min(W,W1) ; Wmax = Max(W,W1) ;
1535     Project (Xmin,Ymin,Zmax,U,V,W) ;
1536     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1537     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1538     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1539     Project (Xmax,Ymin,Zmax,U,V,W) ;
1540     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1541     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1542     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1543     Project (Xmax,Ymin,Zmin,U,V,W) ;
1544     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1545     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1546     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1547     Project (Xmax,Ymax,Zmin,U,V,W) ;
1548     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1549     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1550     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1551     Project (Xmin,Ymax,Zmax,U,V,W) ;
1552     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1553     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1554     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1555     Project (Xmin,Ymax,Zmin,U,V,W) ;
1556     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
1557     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
1558     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
1559
1560     // Adjust Z size
1561     Wmax = Max(Abs(Wmin),Abs(Wmax)) ;
1562     Dz = 2.*Wmax + Margin * Wmax;
1563
1564     // Compute depth value
1565     Dx = Abs(Umax - Umin) ; Dy = Abs(Vmax - Vmin) ; // Dz = Abs(Wmax - Wmin);
1566     Dx += Margin * Dx; Dy += Margin * Dy;
1567     Size = Sqrt(Dx*Dx + Dy*Dy + Dz*Dz);
1568     if( Size > 0. ) {
1569       SetZSize(Size) ;
1570       SetDepth( Aspect * Size / 2.);
1571     }
1572
1573     ImmediateUpdate();
1574 }
1575
1576 //=============================================================================
1577 //function : WindowFitAll
1578 //purpose  :
1579 //=============================================================================
1580 void V3d_View::WindowFitAll(const Standard_Integer Xmin,
1581                             const Standard_Integer Ymin,
1582                             const Standard_Integer Xmax,
1583                             const Standard_Integer Ymax)
1584 {
1585   WindowFit(Xmin,Ymin,Xmax,Ymax);
1586 }
1587
1588 //=======================================================================
1589 //function : WindowFit
1590 //purpose  :
1591 //=======================================================================
1592 void V3d_View::WindowFit (const Standard_Integer theMinXp,
1593                           const Standard_Integer theMinYp,
1594                           const Standard_Integer theMaxXp,
1595                           const Standard_Integer theMaxYp)
1596 {
1597   Standard_Boolean wasUpdateEnabled = SetImmediateUpdate (Standard_False);
1598
1599   Handle(Graphic3d_Camera) aCamera = Camera();
1600
1601   if (!aCamera->IsOrthographic())
1602   {
1603     // normalize view coordinates
1604     Standard_Integer aWinWidth, aWinHeight;
1605     MyWindow->Size (aWinWidth, aWinHeight);
1606
1607     // z coordinate of camera center
1608     Standard_Real aDepth = aCamera->Project (aCamera->Center()).Z();
1609
1610     // camera projection coordinate are in NDC which are normalized [-1, 1]
1611     Standard_Real aUMin = (2.0 / aWinWidth) * theMinXp  - 1.0;
1612     Standard_Real aUMax = (2.0 / aWinWidth) * theMaxXp  - 1.0;
1613     Standard_Real aVMin = (2.0 / aWinHeight) * theMinYp - 1.0;
1614     Standard_Real aVMax = (2.0 / aWinHeight) * theMaxYp - 1.0;
1615
1616     // compute camera panning
1617     gp_Pnt aScreenCenter (0.0, 0.0, aDepth);
1618     gp_Pnt aFitCenter ((aUMin + aUMax) * 0.5, (aVMin + aVMax) * 0.5, aDepth);
1619     gp_Pnt aPanTo = aCamera->ConvertProj2View (aFitCenter);
1620     gp_Pnt aPanFrom = aCamera->ConvertProj2View (aScreenCenter);
1621     gp_Vec aPanVec (aPanFrom, aPanTo);
1622
1623     // compute section size
1624     gp_Pnt aFitTopRight (aUMax, aVMax, aDepth);
1625     gp_Pnt aFitBotLeft (aUMin, aVMin, aDepth);
1626     gp_Pnt aViewBotLeft = aCamera->ConvertProj2View (aFitBotLeft);
1627     gp_Pnt aViewTopRight = aCamera->ConvertProj2View (aFitTopRight);
1628
1629     Standard_Real aUSize = aViewTopRight.X() - aViewBotLeft.X();
1630     Standard_Real aVSize = aViewTopRight.Y() - aViewBotLeft.Y();
1631
1632     Translate (aCamera, aPanVec.X(), -aPanVec.Y());
1633     Scale (aCamera, aUSize, aVSize);
1634     AutoZFit();
1635   }
1636   else
1637   {
1638     Standard_Real aX1, aY1, aX2, aY2;
1639     Convert (theMinXp, theMinYp, aX1, aY1);
1640     Convert (theMaxXp, theMaxYp, aX2, aY2);
1641     FitAll (aX1, aY1, aX2, aY2);
1642   }
1643
1644   SetImmediateUpdate (wasUpdateEnabled);
1645
1646   ImmediateUpdate();
1647 }
1648
1649 //=======================================================================
1650 //function : ConvertToGrid
1651 //purpose  :
1652 //=======================================================================
1653 void V3d_View::ConvertToGrid(const Standard_Integer Xp,
1654                              const Standard_Integer Yp,
1655                              Standard_Real& Xg,
1656                              Standard_Real& Yg,
1657                              Standard_Real& Zg) const
1658 {
1659   Graphic3d_Vertex aVrp;
1660   Standard_Real anX, anY, aZ;
1661   Convert (Xp, Yp, anX, anY, aZ);
1662   aVrp.SetCoord (anX, anY, aZ);
1663
1664   if( MyViewer->Grid()->IsActive() ) {
1665     Graphic3d_Vertex aNewVrp = Compute (aVrp) ;
1666     aNewVrp.Coord (Xg,Yg,Zg) ;
1667   } else
1668     aVrp.Coord (Xg,Yg,Zg) ;
1669 }
1670
1671 //=======================================================================
1672 //function : ConvertToGrid
1673 //purpose  :
1674 //=======================================================================
1675 void V3d_View::ConvertToGrid(const Standard_Real X,
1676                              const Standard_Real Y,
1677                              const Standard_Real Z,
1678                              Standard_Real& Xg,
1679                              Standard_Real& Yg,
1680                              Standard_Real& Zg) const
1681 {
1682   if( MyViewer->Grid()->IsActive() ) {
1683     Graphic3d_Vertex aVrp (X,Y,Z) ;
1684     Graphic3d_Vertex aNewVrp = Compute (aVrp) ;
1685     aNewVrp.Coord(Xg,Yg,Zg) ;
1686   } else {
1687     Xg = X; Yg = Y; Zg = Z;
1688   }
1689 }
1690
1691 //=======================================================================
1692 //function : Convert
1693 //purpose  :
1694 //=======================================================================
1695 Standard_Real V3d_View::Convert(const Standard_Integer Vp) const
1696 {
1697   Standard_Integer aDxw, aDyw ;
1698
1699   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1700
1701   MyWindow->Size (aDxw, aDyw);
1702   Standard_Real aValue;
1703
1704   gp_Pnt aViewDims = Camera()->ViewDimensions();
1705   aValue = aViewDims.X() * (Standard_Real)Vp / (Standard_Real)aDxw;
1706
1707   return aValue;
1708 }
1709
1710 //=======================================================================
1711 //function : Convert
1712 //purpose  :
1713 //=======================================================================
1714 void V3d_View::Convert(const Standard_Integer Xp,
1715                        const Standard_Integer Yp,
1716                        Standard_Real& Xv,
1717                        Standard_Real& Yv) const
1718 {
1719   Standard_Integer aDxw, aDyw;
1720
1721   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1722
1723   MyWindow->Size (aDxw, aDyw);
1724
1725   gp_Pnt aPoint (Xp * 2.0 / aDxw - 1.0, (aDyw - Yp) * 2.0 / aDyw - 1.0, 0.0);
1726   aPoint = Camera()->ConvertProj2View (aPoint);
1727
1728   Xv = aPoint.X();
1729   Yv = aPoint.Y();
1730 }
1731
1732 //=======================================================================
1733 //function : Convert
1734 //purpose  :
1735 //=======================================================================
1736 Standard_Integer V3d_View::Convert(const Standard_Real Vv) const
1737 {
1738   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1739
1740   Standard_Integer aDxw, aDyw;
1741   MyWindow->Size (aDxw, aDyw);
1742
1743   gp_Pnt aViewDims = Camera()->ViewDimensions();
1744   Standard_Integer aValue = RealToInt (aDxw * Vv / (aViewDims.X()));
1745
1746   return aValue;
1747 }
1748
1749 //=======================================================================
1750 //function : Convert
1751 //purpose  :
1752 //=======================================================================
1753 void V3d_View::Convert(const Standard_Real Xv,
1754                        const Standard_Real Yv,
1755                        Standard_Integer& Xp,
1756                        Standard_Integer& Yp) const
1757 {
1758   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1759
1760   Standard_Integer aDxw, aDyw;
1761   MyWindow->Size (aDxw, aDyw);
1762
1763   gp_Pnt aPoint (Xv, Yv, 0.0);
1764   aPoint = Camera()->ConvertView2Proj (aPoint);
1765   aPoint = gp_Pnt ((aPoint.X() + 1.0) * aDxw / 2.0, aDyw - (aPoint.Y() + 1.0) * aDyw / 2.0, 0.0);
1766
1767   Xp = RealToInt (aPoint.X());
1768   Yp = RealToInt (aPoint.Y());
1769 }
1770
1771 //=======================================================================
1772 //function : Convert
1773 //purpose  :
1774 //=======================================================================
1775 void V3d_View::Convert(const Standard_Integer Xp,
1776                        const Standard_Integer Yp,
1777                        Standard_Real& X,
1778                        Standard_Real& Y,
1779                        Standard_Real& Z) const
1780 {
1781   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1782   Standard_Integer aHeight, aWidth;
1783   MyWindow->Size (aWidth, aHeight);
1784
1785   Standard_Real anX = 2.0 * Xp / aWidth - 1.0;
1786   Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0;
1787   Standard_Real  aZ = 2.0 * 0.0 - 1.0;
1788
1789   gp_Pnt aResult = Camera()->UnProject (gp_Pnt (anX, anY, aZ));
1790
1791   X = aResult.X();
1792   Y = aResult.Y();
1793   Z = aResult.Z();
1794 }
1795
1796 //=======================================================================
1797 //function : ConvertWithProj
1798 //purpose  :
1799 //=======================================================================
1800 void V3d_View::ConvertWithProj(const Standard_Integer Xp,
1801                                const Standard_Integer Yp,
1802                                Standard_Real& X,
1803                                Standard_Real& Y,
1804                                Standard_Real& Z,
1805                                Standard_Real& Dx,
1806                                Standard_Real& Dy,
1807                                Standard_Real& Dz) const
1808 {
1809   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1810   Standard_Integer aHeight, aWidth;
1811   MyWindow->Size (aWidth, aHeight);
1812
1813   Standard_Real anX = 2.0 * Xp / aWidth - 1.0;
1814   Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0;
1815   Standard_Real  aZ = 2.0 * 0.0 - 1.0;
1816
1817   Handle(Graphic3d_Camera) aCamera = Camera();
1818
1819   gp_Pnt aResult = aCamera->UnProject (gp_Pnt (anX, anY, aZ));
1820
1821   X = aResult.X();
1822   Y = aResult.Y();
1823   Z = aResult.Z();
1824
1825   Graphic3d_Vertex aVrp;
1826   aVrp.SetCoord (X, Y, Z);
1827
1828   aResult = aCamera->UnProject (gp_Pnt (anX, anY, aZ - 10.0));
1829
1830   Graphic3d_Vec3d aNormDir;
1831   aNormDir.x() = X - aResult.X();
1832   aNormDir.y() = Y - aResult.Y();
1833   aNormDir.z() = Z - aResult.Z();
1834   aNormDir.Normalize();
1835
1836   Dx = aNormDir.x();
1837   Dy = aNormDir.y();
1838   Dz = aNormDir.z();
1839 }
1840
1841 //=======================================================================
1842 //function : Convert
1843 //purpose  :
1844 //=======================================================================
1845 void V3d_View::Convert(const Standard_Real X,
1846                        const Standard_Real Y,
1847                        const Standard_Real Z,
1848                        Standard_Integer& Xp,
1849                        Standard_Integer& Yp) const
1850 {
1851   V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window");
1852   Standard_Integer aHeight, aWidth;
1853   MyWindow->Size (aWidth, aHeight);
1854
1855   gp_Pnt aPoint = Camera()->Project (gp_Pnt (X, Y, Z));
1856
1857   Xp = RealToInt ((aPoint.X() + 1) * 0.5 * aWidth);
1858   Yp = RealToInt (aHeight - 1 - (aPoint.Y() + 1) * 0.5 * aHeight);
1859 }
1860
1861 //=======================================================================
1862 //function : Project
1863 //purpose  :
1864 //=======================================================================
1865 void V3d_View::Project (const Standard_Real theX,
1866                         const Standard_Real theY,
1867                         const Standard_Real theZ,
1868                         Standard_Real& theXp,
1869                         Standard_Real& theYp) const
1870 {
1871   Standard_Real aZp;
1872   Project (theX, theY, theZ, theXp, theYp, aZp);
1873 }
1874
1875 //=======================================================================
1876 //function : Project
1877 //purpose  :
1878 //=======================================================================
1879 void V3d_View::Project (const Standard_Real theX,
1880                         const Standard_Real theY,
1881                         const Standard_Real theZ,
1882                         Standard_Real& theXp,
1883                         Standard_Real& theYp,
1884                         Standard_Real& theZp) const
1885 {
1886   Handle(Graphic3d_Camera) aCamera = Camera();
1887
1888   gp_XYZ aViewSpaceDimensions = aCamera->ViewDimensions();
1889   Standard_Real aXSize = aViewSpaceDimensions.X();
1890   Standard_Real aYSize = aViewSpaceDimensions.Y();
1891   Standard_Real aZSize = aViewSpaceDimensions.Z();
1892
1893   gp_Pnt aPoint = aCamera->Project (gp_Pnt (theX, theY, theZ));
1894
1895   // NDC [-1, 1] --> PROJ [ -size / 2, +size / 2 ]
1896   theXp = aPoint.X() * aXSize * 0.5;
1897   theYp = aPoint.Y() * aYSize * 0.5;
1898   theZp = aPoint.Z() * aZSize * 0.5;
1899 }
1900
1901 //=======================================================================
1902 //function : BackgroundColor
1903 //purpose  :
1904 //=======================================================================
1905 void V3d_View::BackgroundColor(const Quantity_TypeOfColor Type,
1906                                Standard_Real& V1,
1907                                Standard_Real& V2,
1908                                Standard_Real& V3) const
1909 {
1910   Quantity_Color C = BackgroundColor() ;
1911   C.Values(V1,V2,V3,Type) ;
1912 }
1913
1914 //=======================================================================
1915 //function : BackgroundColor
1916 //purpose  :
1917 //=======================================================================
1918 Quantity_Color V3d_View::BackgroundColor() const
1919 {
1920   return myView->Background().Color() ;
1921 }
1922
1923 //=======================================================================
1924 //function : GradientBackgroundColors
1925 //purpose  :
1926 //=======================================================================
1927 void V3d_View::GradientBackgroundColors (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1928 {
1929   myView->GradientBackground().Colors (theColor1, theColor2);
1930 }
1931
1932 //=======================================================================
1933 //function : GradientBackground
1934 //purpose  :
1935 //=======================================================================
1936 Aspect_GradientBackground V3d_View::GradientBackground() const
1937 {
1938   return myView->GradientBackground();
1939 }
1940
1941 //=======================================================================
1942 //function : Scale
1943 //purpose  :
1944 //=======================================================================
1945 Standard_Real V3d_View::Scale() const
1946 {
1947   return myDefaultCamera->Scale() / Camera()->Scale();
1948 }
1949
1950 //=======================================================================
1951 //function : AxialScale
1952 //purpose  :
1953 //=======================================================================
1954 void V3d_View::AxialScale(Standard_Real& Sx, Standard_Real& Sy, Standard_Real& Sz) const
1955 {
1956   gp_Pnt anAxialScale = Camera()->AxialScale();
1957   Sx = anAxialScale.X();
1958   Sy = anAxialScale.Y();
1959   Sz = anAxialScale.Z();
1960 }
1961
1962 //=======================================================================
1963 //function : Size
1964 //purpose  :
1965 //=======================================================================
1966 void V3d_View::Size(Standard_Real& Width, Standard_Real& Height) const
1967 {
1968   gp_Pnt aViewDims = Camera()->ViewDimensions();
1969
1970   Width = aViewDims.X();
1971   Height = aViewDims.Y();
1972 }
1973
1974 //=======================================================================
1975 //function : ZSize
1976 //purpose  :
1977 //=======================================================================
1978 Standard_Real V3d_View::ZSize() const
1979 {
1980   gp_Pnt aViewDims = Camera()->ViewDimensions();
1981
1982   return aViewDims.Z();
1983 }
1984
1985 //=======================================================================
1986 //function : MinMax
1987 //purpose  :
1988 //=======================================================================
1989 Standard_Integer V3d_View::MinMax(Standard_Real& Umin,
1990                                   Standard_Real& Vmin,
1991                                   Standard_Real& Umax,
1992                                   Standard_Real& Vmax) const
1993 {
1994   Standard_Real Wmin,Wmax,U,V,W ;
1995   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax ;
1996   // CAL 6/11/98
1997   Standard_Integer Nstruct = myView->NumberOfDisplayedStructures() ;
1998
1999   if( Nstruct ) {
2000     Bnd_Box aBox = myView->MinMaxValues();
2001     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
2002     Project (Xmin,Ymin,Zmin,Umin,Vmin,Wmin) ;
2003     Project (Xmax,Ymax,Zmax,Umax,Vmax,Wmax) ;
2004     Project (Xmin,Ymin,Zmax,U,V,W) ;
2005     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2006     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2007     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2008     Project (Xmax,Ymin,Zmax,U,V,W) ;
2009     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2010     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2011     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2012     Project (Xmax,Ymin,Zmin,U,V,W) ;
2013     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2014     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2015     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2016     Project (Xmax,Ymax,Zmin,U,V,W) ;
2017     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2018     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2019     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2020     Project (Xmin,Ymax,Zmax,U,V,W) ;
2021     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2022     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2023     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2024     Project (Xmin,Ymax,Zmin,U,V,W) ;
2025     Umin = Min(U,Umin) ; Umax = Max(U,Umax) ;
2026     Vmin = Min(V,Vmin) ; Vmax = Max(V,Vmax) ;
2027     Wmin = Min(W,Wmin) ; Wmax = Max(W,Wmax) ;
2028   }
2029   return Nstruct ;
2030 }
2031
2032 //=======================================================================
2033 //function : MinMax
2034 //purpose  :
2035 //=======================================================================
2036 Standard_Integer V3d_View::MinMax(Standard_Real& Xmin,
2037                                   Standard_Real& Ymin,
2038                                   Standard_Real& Zmin,
2039                                   Standard_Real& Xmax,
2040                                   Standard_Real& Ymax,
2041                                   Standard_Real& Zmax) const
2042 {
2043   // CAL 6/11/98
2044   // Standard_Integer Nstruct = (MyView->DisplayedStructures())->Extent() ;
2045   Standard_Integer Nstruct = myView->NumberOfDisplayedStructures() ;
2046
2047   if( Nstruct ) {
2048     Bnd_Box aBox = myView->MinMaxValues();
2049     aBox.Get (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
2050   }
2051   return Nstruct ;
2052 }
2053
2054 //=======================================================================
2055 //function : Gravity
2056 //purpose  :
2057 //=======================================================================
2058 void V3d_View::Gravity (Standard_Real& theX,
2059                         Standard_Real& theY,
2060                         Standard_Real& theZ) const
2061 {
2062   Graphic3d_MapOfStructure aSetOfStructures;
2063   myView->DisplayedStructures (aSetOfStructures);
2064
2065   Standard_Boolean hasSelection = Standard_False;
2066   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
2067        aStructIter.More(); aStructIter.Next())
2068   {
2069     if (aStructIter.Key()->IsHighlighted()
2070      && aStructIter.Key()->IsVisible())
2071     {
2072       hasSelection = Standard_True;
2073       break;
2074     }
2075   }
2076
2077   Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2078   Standard_Integer aNbPoints = 0;
2079   gp_XYZ aResult (0.0, 0.0, 0.0);
2080   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aSetOfStructures);
2081        aStructIter.More(); aStructIter.Next())
2082   {
2083     const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
2084     if (!aStruct->IsVisible()
2085       || aStruct->IsInfinite()
2086       || (hasSelection && !aStruct->IsHighlighted()))
2087     {
2088       continue;
2089     }
2090
2091     const Graphic3d_BndBox3d& aBox = aStruct->CStructure()->BoundingBox();
2092     if (!aBox.IsValid())
2093     {
2094       continue;
2095     }
2096
2097     // skip transformation-persistent objects
2098     if (!aStruct->TransformPersistence().IsNull())
2099     {
2100       continue;
2101     }
2102
2103     // use camera projection to find gravity point
2104     Xmin = aBox.CornerMin().x();
2105     Ymin = aBox.CornerMin().y();
2106     Zmin = aBox.CornerMin().z();
2107     Xmax = aBox.CornerMax().x();
2108     Ymax = aBox.CornerMax().y();
2109     Zmax = aBox.CornerMax().z();
2110     gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
2111     {
2112       gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
2113       gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
2114       gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
2115       gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
2116     };
2117
2118     for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
2119     {
2120       const gp_Pnt& aBndPnt    = aPnts[aPntIt];
2121       const gp_Pnt  aProjected = Camera()->Project (aBndPnt);
2122       if (Abs (aProjected.X()) <= 1.0
2123        && Abs (aProjected.Y()) <= 1.0)
2124       {
2125         aResult += aBndPnt.XYZ();
2126         ++aNbPoints;
2127       }
2128     }
2129   }
2130
2131   if (aNbPoints == 0)
2132   {
2133     // fallback - just use bounding box of entire scene
2134     Bnd_Box aBox = myView->MinMaxValues();
2135     if (!aBox.IsVoid())
2136     {
2137       aBox.Get (Xmin, Ymin, Zmin,
2138                 Xmax, Ymax, Zmax);
2139       gp_Pnt aPnts[THE_NB_BOUND_POINTS] =
2140       {
2141         gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
2142         gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
2143         gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
2144         gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
2145       };
2146
2147       for (Standard_Integer aPntIt = 0; aPntIt < THE_NB_BOUND_POINTS; ++aPntIt)
2148       {
2149         const gp_Pnt& aBndPnt = aPnts[aPntIt];
2150         aResult += aBndPnt.XYZ();
2151         ++aNbPoints;
2152       }
2153     }
2154   }
2155
2156   if (aNbPoints > 0)
2157   {
2158     aResult /= aNbPoints;
2159   }
2160   theX = aResult.X();
2161   theY = aResult.Y();
2162   theZ = aResult.Z();
2163 }
2164
2165 //=======================================================================
2166 //function : Eye
2167 //purpose  :
2168 //=======================================================================
2169 void V3d_View::Eye(Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const
2170 {
2171   gp_Pnt aCameraEye = Camera()->Eye();
2172   X = aCameraEye.X();
2173   Y = aCameraEye.Y();
2174   Z = aCameraEye.Z();
2175 }
2176
2177 //=============================================================================
2178 //function : FocalReferencePoint
2179 //purpose  :
2180 //=============================================================================
2181 void V3d_View::FocalReferencePoint(Standard_Real& X, Standard_Real& Y,Standard_Real& Z) const
2182 {
2183   Eye (X,Y,Z);
2184 }
2185
2186 //=============================================================================
2187 //function : ProjReferenceAxe
2188 //purpose  :
2189 //=============================================================================
2190 void V3d_View::ProjReferenceAxe(const Standard_Integer Xpix,
2191                                 const Standard_Integer Ypix,
2192                                 Standard_Real& XP,
2193                                 Standard_Real& YP,
2194                                 Standard_Real& ZP,
2195                                 Standard_Real& VX,
2196                                 Standard_Real& VY,
2197                                 Standard_Real& VZ) const
2198 {
2199   Standard_Real Xo,Yo,Zo;
2200
2201   Convert (Xpix, Ypix, XP, YP, ZP);
2202   if ( Type() == V3d_PERSPECTIVE ) 
2203   {
2204     FocalReferencePoint (Xo,Yo,Zo);
2205     VX = Xo - XP;
2206     VY = Yo - YP;
2207     VZ = Zo - ZP;
2208   }
2209   else 
2210   {
2211     Proj (VX,VY,VZ);
2212   }
2213 }
2214
2215 //=============================================================================
2216 //function : Depth
2217 //purpose  :
2218 //=============================================================================
2219 Standard_Real V3d_View::Depth() const
2220 {
2221   return Camera()->Distance();
2222 }
2223
2224 //=============================================================================
2225 //function : Proj
2226 //purpose  :
2227 //=============================================================================
2228 void V3d_View::Proj(Standard_Real& Dx, Standard_Real& Dy, Standard_Real& Dz) const
2229 {
2230   gp_Dir aCameraDir = Camera()->Direction().Reversed();
2231   Dx = aCameraDir.X();
2232   Dy = aCameraDir.Y();
2233   Dz = aCameraDir.Z();
2234 }
2235
2236 //=============================================================================
2237 //function : At
2238 //purpose  :
2239 //=============================================================================
2240 void V3d_View::At(Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const
2241 {
2242   gp_Pnt aCameraCenter = Camera()->Center();
2243   X = aCameraCenter.X();
2244   Y = aCameraCenter.Y();
2245   Z = aCameraCenter.Z();
2246 }
2247
2248 //=============================================================================
2249 //function : Up
2250 //purpose  :
2251 //=============================================================================
2252 void V3d_View::Up(Standard_Real& Vx, Standard_Real& Vy, Standard_Real& Vz) const
2253 {
2254   gp_Dir aCameraUp = Camera()->Up();
2255   Vx = aCameraUp.X();
2256   Vy = aCameraUp.Y();
2257   Vz = aCameraUp.Z();
2258 }
2259
2260 //=============================================================================
2261 //function : Twist
2262 //purpose  :
2263 //=============================================================================
2264 Standard_Real V3d_View::Twist() const
2265 {
2266   Standard_Real Xup,Yup,Zup,Xpn,Ypn,Zpn,X0,Y0,Z0 ;
2267   Standard_Real pvx,pvy,pvz,pvn,sca,angle ;
2268   Graphic3d_Vector Xaxis,Yaxis,Zaxis ;
2269   Standard_Boolean TheStatus ;
2270
2271   gp_Dir aReferencePlane (Camera()->Direction().Reversed());
2272   gp_Dir anUp;
2273
2274   Proj(Xpn,Ypn,Zpn);
2275   anUp = gp_Dir (0.,0.,1.) ;
2276   TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2277   if( !TheStatus ) {
2278     anUp = gp_Dir (0.,1.,0.) ;
2279     TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2280   }
2281   if( !TheStatus ) {
2282     anUp = gp_Dir (1.,0.,0.) ;
2283     TheStatus = ScreenAxis (aReferencePlane, anUp,Xaxis,Yaxis,Zaxis) ;
2284   }
2285   Yaxis.Coord(X0,Y0,Z0) ;
2286
2287   Up(Xup,Yup,Zup) ;
2288   /* Compute Cross Vector From Up & Origin */
2289   pvx = Y0*Zup - Z0*Yup ;
2290   pvy = Z0*Xup - X0*Zup ;
2291   pvz = X0*Yup - Y0*Xup ;
2292   pvn = pvx*pvx + pvy*pvy + pvz*pvz ;
2293   sca = X0*Xup + Y0*Yup + Z0*Zup ;
2294   /* Compute Angle */
2295   angle = Sqrt(pvn) ;
2296   if( angle > 1. ) angle = 1. ;
2297   else if( angle < -1. ) angle = -1. ;
2298   angle = asin(angle) ;
2299   if( sca < 0. ) angle = M_PI - angle ;
2300   if( angle > 0. && angle < M_PI ) {
2301     sca = pvx*Xpn + pvy*Ypn + pvz*Zpn ;
2302     if( sca < 0. ) angle = DEUXPI - angle ;
2303   }
2304   return angle ;
2305 }
2306
2307 //=============================================================================
2308 //function : ShadingModel
2309 //purpose  :
2310 //=============================================================================
2311 V3d_TypeOfShadingModel V3d_View::ShadingModel() const
2312 {
2313   return static_cast<V3d_TypeOfShadingModel> (myView->ShadingModel());
2314 }
2315
2316 //=============================================================================
2317 //function : TextureEnv
2318 //purpose  :
2319 //=============================================================================
2320 Handle(Graphic3d_TextureEnv) V3d_View::TextureEnv() const
2321 {
2322   return myView->TextureEnv();
2323 }
2324
2325 //=============================================================================
2326 //function : Visualization
2327 //purpose  :
2328 //=============================================================================
2329 V3d_TypeOfVisualization V3d_View::Visualization() const
2330 {
2331   return static_cast<V3d_TypeOfVisualization> (myView->VisualizationType());
2332 }
2333
2334 //=============================================================================
2335 //function : Viewer
2336 //purpose  :
2337 //=============================================================================
2338 Handle(V3d_Viewer) V3d_View::Viewer() const
2339 {
2340   return MyViewer;
2341 }
2342
2343 //=============================================================================
2344 //function : IfWindow
2345 //purpose  :
2346 //=============================================================================
2347 Standard_Boolean V3d_View::IfWindow() const
2348 {
2349   return myView->IsDefined();
2350 }
2351
2352 //=============================================================================
2353 //function : Window
2354 //purpose  :
2355 //=============================================================================
2356 Handle(Aspect_Window) V3d_View::Window() const
2357 {
2358   return MyWindow;
2359 }
2360
2361 //=============================================================================
2362 //function : Type
2363 //purpose  :
2364 //=============================================================================
2365 V3d_TypeOfView V3d_View::Type() const
2366 {
2367   return Camera()->IsOrthographic() ? V3d_ORTHOGRAPHIC : V3d_PERSPECTIVE;
2368 }
2369
2370 //=============================================================================
2371 //function : SetFocale
2372 //purpose  :
2373 //=============================================================================
2374 void V3d_View::SetFocale( const Standard_Real focale )
2375 {
2376   Handle(Graphic3d_Camera) aCamera = Camera();
2377
2378   if (aCamera->IsOrthographic())
2379   {
2380     return;
2381   }
2382
2383   Standard_Real aFOVyRad = ATan (focale / (aCamera->Distance() * 2.0));
2384
2385   aCamera->SetFOVy (aFOVyRad * (360 / M_PI));
2386
2387   ImmediateUpdate();
2388 }
2389
2390 //=============================================================================
2391 //function : Focale
2392 //purpose  :
2393 //=============================================================================
2394 Standard_Real V3d_View::Focale() const
2395 {
2396   Handle(Graphic3d_Camera) aCamera = Camera();
2397
2398   if (aCamera->IsOrthographic())
2399   {
2400     return 0.0;
2401   }
2402
2403   return aCamera->Distance() * 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
2404 }
2405
2406 //=============================================================================
2407 //function : View
2408 //purpose  :
2409 //=============================================================================
2410 Handle(Graphic3d_CView) V3d_View::View() const
2411 {
2412   return myView;
2413 }
2414
2415 //=============================================================================
2416 //function : ScreenAxis
2417 //purpose  :
2418 //=============================================================================
2419 Standard_Boolean V3d_View::ScreenAxis( const gp_Dir &Vpn, const gp_Dir &Vup, Graphic3d_Vector &Xaxe, Graphic3d_Vector &Yaxe, Graphic3d_Vector &Zaxe)
2420 {
2421   Standard_Real Xpn, Ypn, Zpn, Xup, Yup, Zup;
2422   Standard_Real dx1, dy1, dz1, xx, yy, zz;
2423
2424   Xpn = Vpn.X(); Ypn = Vpn.Y(); Zpn = Vpn.Z();
2425   Xup = Vup.X(); Yup = Vup.Y(); Zup = Vup.Z();
2426   xx = Yup*Zpn - Zup*Ypn;
2427   yy = Zup*Xpn - Xup*Zpn;
2428   zz = Xup*Ypn - Yup*Xpn;
2429   Xaxe.SetCoord (xx, yy, zz);
2430   if (Xaxe.LengthZero()) return Standard_False;
2431   Xaxe.Normalize(); 
2432   Xaxe.Coord(dx1, dy1, dz1);
2433   xx = Ypn*dz1 - Zpn*dy1;
2434   yy = Zpn*dx1 - Xpn*dz1;
2435   zz = Xpn*dy1 - Ypn*dx1;
2436   Yaxe.SetCoord (xx, yy, zz) ;
2437   if (Yaxe.LengthZero()) return Standard_False;
2438   Yaxe.Normalize(); 
2439
2440   Zaxe.SetCoord (Xpn, Ypn, Zpn);
2441   Zaxe.Normalize();
2442   return Standard_True;
2443 }
2444
2445 //=============================================================================
2446 //function : TrsPoint
2447 //purpose  :
2448 //=============================================================================
2449 gp_XYZ V3d_View::TrsPoint (const Graphic3d_Vertex& thePnt, const TColStd_Array2OfReal& theMat)
2450 {
2451   // CAL. S3892
2452   const Standard_Integer lr = theMat.LowerRow();
2453   const Standard_Integer ur = theMat.UpperRow();
2454   const Standard_Integer lc = theMat.LowerCol();
2455   const Standard_Integer uc = theMat.UpperCol();
2456   if ((ur - lr + 1 != 4) || (uc - lc + 1 != 4))
2457   {
2458     return gp_XYZ (thePnt.X(), thePnt.Y(), thePnt.Z());
2459   }
2460
2461   Standard_Real X, Y, Z;
2462   thePnt.Coord (X,Y,Z);
2463   const Standard_Real XX = (theMat(lr,lc+3)   + X*theMat(lr,lc)   + Y*theMat(lr,lc+1)   + Z*theMat(lr,lc+2)) / theMat(lr+3,lc+3);
2464   const Standard_Real YY = (theMat(lr+1,lc+3) + X*theMat(lr+1,lc) + Y*theMat(lr+1,lc+1) + Z*theMat(lr+1,lc+2))/theMat(lr+3,lc+3);
2465   const Standard_Real ZZ = (theMat(lr+2,lc+3) + X*theMat(lr+2,lc) + Y*theMat(lr+2,lc+1) + Z*theMat(lr+2,lc+2))/theMat(lr+3,lc+3);
2466   return gp_XYZ (XX, YY, ZZ);
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 Standard_Real    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 Standard_Real 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   Standard_Real aDxv = aZoomAtPointXv / aCoef;
2591   Standard_Real 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 Standard_Real 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 }