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