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