63da14d4f3f9d4fe29f47ff3f718e12486248ba8
[occt.git] / src / V3d / V3d_View_4.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <V3d_View.jxx>
15
16 #include <TColStd_Array2OfReal.hxx>
17
18 #include <gp_Dir2d.hxx>
19  
20 #include <V3d_RectangularGrid.hxx>
21 #include <V3d_CircularGrid.hxx>
22
23 #define MYEPSILON1 0.0001               // Comparison with 0.0
24 #define MYEPSILON2 M_PI / 180.  // Delta between 2 angles
25
26 /*----------------------------------------------------------------------*/
27
28 void V3d_View::SetGrid (const gp_Ax3& aPlane, const Handle(Aspect_Grid)& aGrid)
29 {
30   MyPlane       = aPlane;
31   MyGrid        = aGrid;
32
33   Standard_Real xl, yl, zl;
34   Standard_Real xdx, xdy, xdz;
35   Standard_Real ydx, ydy, ydz;
36   Standard_Real dx, dy, dz;
37   aPlane.Location ().Coord (xl, yl, zl);
38   aPlane.XDirection ().Coord (xdx, xdy, xdz);
39   aPlane.YDirection ().Coord (ydx, ydy, ydz);
40   aPlane.Direction ().Coord (dx, dy, dz);
41
42   Standard_Real CosAlpha = Cos (MyGrid->RotationAngle ());
43   Standard_Real SinAlpha = Sin (MyGrid->RotationAngle ());
44
45   TColStd_Array2OfReal Trsf1 (1, 4, 1, 4);
46   Trsf1 (4, 4) = 1.0;
47   Trsf1 (4, 1) = Trsf1 (4, 2) = Trsf1 (4, 3) = 0.0;
48   // Translation
49   Trsf1 (1, 4) = xl,
50   Trsf1 (2, 4) = yl,
51   Trsf1 (3, 4) = zl;
52   // Transformation change of marker
53   Trsf1 (1, 1) = xdx,
54   Trsf1 (2, 1) = xdy,
55   Trsf1 (3, 1) = xdz,
56   Trsf1 (1, 2) = ydx,
57   Trsf1 (2, 2) = ydy,
58   Trsf1 (3, 2) = ydz,
59   Trsf1 (1, 3) = dx,
60   Trsf1 (2, 3) = dy,
61   Trsf1 (3, 3) = dz;
62
63   TColStd_Array2OfReal Trsf2 (1, 4, 1, 4);
64   Trsf2 (4, 4) = 1.0;
65   Trsf2 (4, 1) = Trsf2 (4, 2) = Trsf2 (4, 3) = 0.0;
66   // Translation of the origin
67   Trsf2 (1, 4) = -MyGrid->XOrigin (),
68   Trsf2 (2, 4) = -MyGrid->YOrigin (),
69   Trsf2 (3, 4) = 0.0;
70   // Rotation Alpha around axis -Z
71   Trsf2 (1, 1) = CosAlpha,
72   Trsf2 (2, 1) = -SinAlpha,
73   Trsf2 (3, 1) = 0.0,
74   Trsf2 (1, 2) = SinAlpha,
75   Trsf2 (2, 2) = CosAlpha,
76   Trsf2 (3, 2) = 0.0,
77   Trsf2 (1, 3) = 0.0,
78   Trsf2 (2, 3) = 0.0,
79   Trsf2 (3, 3) = 1.0;
80
81   Standard_Real valuetrsf;
82   Standard_Real valueoldtrsf;
83   Standard_Real valuenewtrsf;
84   Standard_Integer i, j, k;
85   // Calculation of the product of matrices
86   for (i=1; i<=4; i++)
87       for (j=1; j<=4; j++) {
88     MyTrsf (i, j) = 0.0;
89     for (k=1; k<=4; k++) {
90         valueoldtrsf = Trsf1 (i, k);
91         valuetrsf        = Trsf2 (k, j);
92         valuenewtrsf = MyTrsf (i, j) + valueoldtrsf * valuetrsf;
93         MyTrsf (i, j) = valuenewtrsf;
94     }
95      }
96 }
97
98 void V3d_View::SetGridActivity (const Standard_Boolean AFlag)
99 {
100   if (AFlag) MyGrid->Activate ();
101   else MyGrid->Deactivate ();
102 }
103
104 void V3d_View::SetGridGraphicValues (const Handle(Aspect_Grid)& )
105 {
106 }
107
108
109 void toPolarCoords (const Standard_Real theX, const Standard_Real theY, 
110                           Standard_Real& theR, Standard_Real& thePhi)
111 {
112   theR = Sqrt (theX * theX + theY * theY);
113   thePhi = ATan2 (theY, theX);  
114 }
115
116 void toCartesianCoords (const Standard_Real theR, const Standard_Real thePhi, 
117                               Standard_Real& theX, Standard_Real& theY)
118 {
119   theX = theR * Cos (thePhi);
120   theY = theR * Sin (thePhi);
121 }
122
123 Graphic3d_Vertex V3d_View::Compute (const Graphic3d_Vertex & AVertex) const
124 {
125   Graphic3d_Vertex CurPoint, NewPoint;
126   Standard_Real X1, Y1, Z1, X2, Y2, Z2;
127   Standard_Real XPp, YPp;
128
129   gp_Dir aRefPlane = myCamera->Direction().Reversed();
130   X1 = aRefPlane.X(); Y1 = aRefPlane.Y(); Z1 = aRefPlane.Z();
131   MyPlane.Direction ().Coord (X2, Y2, Z2);
132
133   gp_Dir VPN (X1, Y1, Z1);
134   gp_Dir GPN (X2, Y2, Z2);
135
136   AVertex.Coord (X1, Y1, Z1);
137   Project (X1, Y1, Z1, XPp, YPp);
138
139   // Casw when the plane of the grid and the plane of the view
140   // are perpendicular to MYEPSILON2 close radians
141   if (Abs (VPN.Angle (GPN) - M_PI / 2.) < MYEPSILON2) {
142     NewPoint.SetCoord (X1, Y1, Z1);
143     return NewPoint;
144   }
145
146   Standard_Boolean IsRectangular = 
147     MyGrid->IsKind (STANDARD_TYPE (Aspect_RectangularGrid));
148
149   Graphic3d_Vertex P1;
150
151   Standard_Real x0, y0, z0, x1, y1, z1, x2, y2, z2;
152     
153   P1.SetCoord (0.0, 0.0, 0.0);
154   CurPoint = V3d_View::TrsPoint (P1, MyTrsf);
155   CurPoint.Coord (x0, y0, z0);
156     
157   // get grid axes in world space
158   P1.SetCoord (1.0, 0.0, 0.0);
159   CurPoint = V3d_View::TrsPoint (P1, MyTrsf);
160   CurPoint.Coord (x1, y1, z1);
161   gp_Vec aGridX (gp_Pnt (x0, y0, z0), gp_Pnt (x1, y1, z1));
162   aGridX.Normalize();
163
164   P1.SetCoord (0.0, 1.0, 0.0);
165   CurPoint = V3d_View::TrsPoint (P1, MyTrsf);
166   CurPoint.Coord (x2, y2, z2);
167   gp_Vec aGridY (gp_Pnt (x0, y0, z0), gp_Pnt (x2, y2, z2));
168   aGridY.Normalize();
169
170   // get grid normal
171   MyPlane.Direction().Coord (x2, y2, z2);
172   gp_Vec aPlaneNormal (x2, y2, z2);
173
174   gp_Vec aPointOnPlane = gp_Vec (0.0, 0.0, 0.0);
175
176   AVertex.Coord (x1, y1, z1);
177     
178   // project ray from camera onto grid plane
179   if (!myCamera->IsOrthographic())
180   {
181     gp_Vec aPointFromCamera = gp_Vec (myCamera->Eye(), gp_Pnt (x1, y1, z1));
182     aPointFromCamera.Normalize();
183
184     Standard_Real aT = - gp_Vec (myCamera->Eye().XYZ()).Dot (aPlaneNormal) / 
185                                   aPointFromCamera.Dot (aPlaneNormal);
186     aPointOnPlane = gp_Vec (myCamera->Eye().XYZ()) + aPointFromCamera * aT;
187   } else
188   {
189     gp_Vec aPointFromCamera (myCamera->Direction());
190     gp_Vec aPointOnCamera (gp_Vec (x1, y1, z1) - aPointFromCamera);
191
192     Standard_Real aT = - aPointOnCamera.Dot (aPlaneNormal) / 
193                           aPointFromCamera.Dot (aPlaneNormal);
194     aPointOnPlane = aPointOnCamera + aPointFromCamera * aT;
195   }
196
197   if (IsRectangular) {
198     Standard_Real XS, YS;
199     Handle(Aspect_RectangularGrid) theGrid =
200       *(Handle(Aspect_RectangularGrid) *) &MyGrid;
201     XS = theGrid->XStep (), YS = theGrid->YStep ();
202
203     // project point on plane to grid local space
204     gp_Vec aToPoint (gp_Pnt (x0, y0, z0), 
205                      gp_Pnt (aPointOnPlane.X(), aPointOnPlane.Y(), aPointOnPlane.Z()));
206     Standard_Real anXSteps = Round (aGridX.Dot (aToPoint) / XS);
207     Standard_Real anYSteps = Round (aGridY.Dot (aToPoint) / YS);
208
209     // clamp point to grid
210     gp_Vec aResult = aGridX * anXSteps * XS + aGridY * anYSteps * YS + gp_Vec (x0, y0, z0);
211     NewPoint.SetCoord (aResult.X(), aResult.Y(), aResult.Z());
212
213   } 
214   else // IsCircular
215   {
216     Standard_Real RS;
217     Standard_Integer DN;
218     Standard_Real Alpha;
219     Handle(Aspect_CircularGrid) theGrid =
220       *(Handle(Aspect_CircularGrid) *) &MyGrid;
221     RS = theGrid->RadiusStep ();
222     DN = theGrid->DivisionNumber ();
223     Alpha = M_PI / Standard_Real (DN);
224
225     // project point on plane to grid local space
226     gp_Vec aToPoint (gp_Pnt (x0, y0, z0), 
227                      gp_Pnt (aPointOnPlane.X(), aPointOnPlane.Y(), aPointOnPlane.Z()));
228
229     Standard_Real anR = 0.0, aPhi = 0.0;
230     Standard_Real aLocalX = aGridX.Dot (aToPoint);
231     Standard_Real aLocalY = aGridY.Dot (aToPoint);
232     toPolarCoords (aLocalX, aLocalY, anR, aPhi);
233
234     // clamp point to grid
235     Standard_Real anRSteps  = Round (anR / RS);
236     Standard_Real aPhiSteps = Round (aPhi / Alpha);
237     toCartesianCoords (anRSteps * RS, aPhiSteps * Alpha, aLocalX, aLocalY);
238
239     gp_Vec aResult = aGridX * aLocalX + aGridY * aLocalY + gp_Vec (x0, y0, z0);
240     NewPoint.SetCoord (aResult.X(), aResult.Y(), aResult.Z());
241   }
242
243   return NewPoint;
244 }
245
246 // Triedron methods : the Triedron is a non-zoomable object.
247
248 void V3d_View::ZBufferTriedronSetup(const Quantity_NameOfColor XColor,
249                                     const Quantity_NameOfColor YColor,
250                                     const Quantity_NameOfColor ZColor,
251                                     const Standard_Real        SizeRatio,
252                                     const Standard_Real        AxisDiametr,
253                                     const Standard_Integer     NbFacettes)
254 {
255   MyView->ZBufferTriedronSetup(XColor, YColor, ZColor, SizeRatio, AxisDiametr, NbFacettes);
256 }
257
258 void V3d_View::TriedronDisplay (const Aspect_TypeOfTriedronPosition APosition,
259  const Quantity_NameOfColor AColor, const Standard_Real AScale, const V3d_TypeOfVisualization AMode )
260 {
261   MyView->TriedronDisplay (APosition, AColor, AScale, (AMode == V3d_WIREFRAME));
262 }
263
264 void V3d_View::TriedronErase ( )
265 {
266   MyView->TriedronErase ( );
267 }
268
269 void V3d_View::TriedronEcho (const Aspect_TypeOfTriedronEcho AType )
270 {
271   MyView->TriedronEcho (AType);
272 }
273
274 void V3d_View::GetGraduatedTrihedron (Graphic3d_GraduatedTrihedron& theTrihedronData) const
275 {
276   MyView->GetGraduatedTrihedron (theTrihedronData);
277 }
278
279 void V3d_View::GraduatedTrihedronDisplay(const Graphic3d_GraduatedTrihedron& theTrihedronData)
280 {
281   MyView->GraduatedTrihedronDisplay(theTrihedronData);
282 }
283
284 void V3d_View::GraduatedTrihedronErase()
285 {
286   MyView->GraduatedTrihedronErase();
287 }