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