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