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