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