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