0023457: Slow text rendering
[occt.git] / src / OpenGl / OpenGl_GraduatedTrihedron.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <OpenGl_GlCore11.hxx>
21
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26
27 #include <InterfaceGraphic_Graphic3d.hxx>
28 #include <InterfaceGraphic_Aspect.hxx>
29 #include <InterfaceGraphic_Visual3d.hxx>
30
31 #ifdef HAVE_CONFIG_H
32   #include <config.h>
33 #endif
34 #ifdef HAVE_STRING_H
35   #include <string.h>
36 #endif
37
38 #include <OpenGl_Workspace.hxx>
39 #include <OpenGl_View.hxx>
40 #include <OpenGl_GraduatedTrihedron.hxx>
41 #include <OpenGl_AspectLine.hxx>
42
43 const OpenGl_AspectLine myDefaultAspectLine;
44
45 static const OpenGl_TextParam THE_LABEL_PARAMS =
46 {
47   16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
48 };
49
50 /* Bounding box */
51 float xmin = 0.0f, ymin = 0.0f, zmin = 0.0f, xmax = 100.0f, ymax = 100.0f, zmax = 100.0f;
52
53 /* Normal of the view (not normalized!) */
54 static float getNormal(float* normal)
55 {
56   GLint viewport[4];
57   GLdouble model_matrix[16], proj_matrix[16];
58
59   glGetDoublev(GL_MODELVIEW_MATRIX,  model_matrix);
60   glGetDoublev(GL_PROJECTION_MATRIX, proj_matrix);
61   glGetIntegerv(GL_VIEWPORT, viewport);
62
63   double x1, y1, z1, x2, y2, z2, x3, y3, z3;
64   gluUnProject(viewport[0], viewport[1], 0., model_matrix, proj_matrix, viewport, &x1, &y1, &z1);
65   gluUnProject(viewport[0] + viewport[2], viewport[1], 0., model_matrix, proj_matrix, viewport, &x2, &y2, &z2);
66   gluUnProject(viewport[0], viewport[1] + viewport[3], 0., model_matrix, proj_matrix, viewport, &x3, &y3, &z3);
67
68   /* Normal out of user is p1p3^p1p2 */
69   const double dx1 = x3 - x1;
70   const double dy1 = y3 - y1;
71   const double dz1 = z3 - z1;
72   const double dx2 = x2 - x1;
73   const double dy2 = y2 - y1;
74   const double dz2 = z2 - z1;
75   normal[0] = (float) (dy1 * dz2 - dz1 * dy2);
76   normal[1] = (float) (dz1 * dx2 - dx1 * dz2);
77   normal[2] = (float) (dx1 * dy2 - dy1 * dx2);
78
79   /* Distance corresponding to 1 pixel */
80   const float width = (float) sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);
81   return width / (float) viewport[2];
82 }
83
84 static float getDistance2Corner(float* normal, float* center, float x, float y, float z)
85 {
86     return normal[0] * (x - center[0]) + normal[1] * (y - center[1]) + normal[2] * (z - center[2]);
87 }
88
89 static char getFarestCorner(float d000, float d100, float d010, float d001,
90                             float d110, float d101, float d011, float d111)
91 {
92     if (d000 > 0.0f &&
93         d000 > d100 && d000 > d010 && d000 > d001 && d000 > d110 &&
94         d000 > d101 && d000 > d011 && d000 > d111)
95     {
96         return 1;
97     }
98     else if (d100 > 0.0f &&
99              d100 > d000 && d100 > d010 && d100 > d001 && d100 > d110 &&
100              d100 > d101 && d100 > d011 && d100 > d111)
101     {
102         return 2;
103     }
104     else if (d010 > 0.0f &&
105              d010 > d000 && d010 > d100 && d010 > d001 && d010 > d110 &&
106              d010 > d101 && d010 > d011 && d010 > d111)
107     {
108         return 3;
109     }
110     else if (d001 > 0.0f &&
111              d001 > d000 && d001 > d100 && d001 > d010 && d001 > d110 &&
112              d001 > d101 && d001 > d011 && d001 > d111)
113     {
114         return 4;
115     }
116     else if (d110 > 0.0f &&
117              d110 > d000 && d110 > d100 && d110 > d010 && d110 > d001 &&
118              d110 > d101 && d110 > d011 && d110 > d111)
119     {
120         return 5;
121     }
122     else if (d101 > 0.0f &&
123              d101 > d000 && d101 > d100 && d101 > d010 && d101 > d001 &&
124              d101 > d110 && d101 > d011 && d101 > d111)
125     {
126         return 6;
127     }
128     else if (d011 > 0.0f &&
129              d011 > d000 && d011 > d100 && d011 > d010 && d011 > d001 &&
130              d011 > d110 && d011 > d101 && d011 > d111)
131     {
132         return 7;
133     }
134     return 8; /* d111 */
135 }
136
137 static void drawArrow(float x1, float y1, float z1,
138                       float x2, float y2, float z2,
139                       float xn, float yn, float zn)
140 {
141     float h, r;
142     float xa, ya, za;
143     float x0, y0, z0;
144     float xr, yr, zr;
145     float xa1, ya1, za1, xa2, ya2, za2;
146
147     /* Start of arrow: at 10% from the end */
148     x0 = x1 + 0.9f * (x2 - x1); y0 = y1 + 0.9f * (y2 - y1); z0 = z1 + 0.9f * (z2 - z1);
149
150     /* Base of the arrow */
151     xa = (x2 - x0); ya = (y2 - y0); za = (z2 - z0);
152
153     /* Height of the arrow */
154     h = sqrtf(xa * xa + ya * ya + za * za);
155     if (h <= 0.0f)
156         return;
157     xa = xa / h; ya = ya / h; za = za / h;
158
159     /* Radial direction to the arrow */
160     xr = ya * zn - za * yn;
161     yr = za * xn - xa * zn;
162     zr = xa * yn - ya * xn;
163
164     /* Normalize the radial vector */
165     r = sqrtf(xr * xr + yr * yr + zr * zr);
166     if (r <= 0.0f)
167         return;
168     xr = xr / r; yr = yr / r; zr = zr / r;
169
170     /* First point of the base of the arrow */
171     r = 0.2f * h;
172     xr = r * xr; yr = r * yr; zr = r * zr;
173     xa1 = x0 + xr; ya1 = y0 + yr; za1 = z0 + zr;
174
175     /* Second point of the base of the arrow */
176     xa2 = x0 - xr; ya2 = y0 - yr; za2 = z0 - zr;
177
178     /* Draw a line to the arrow */
179     glBegin(GL_LINES);
180         glVertex3f(x1, y1, z1);
181         glVertex3f(x0, y0, z0);
182     glEnd();
183
184     /* Draw a triangle of the arrow */
185     glBegin(GL_LINE_LOOP);
186         glVertex3f(xa1, ya1, za1);
187         glVertex3f(xa2, ya2, za2);
188         glVertex3f(x2,  y2,  z2);
189     glEnd();
190 }
191
192 // =======================================================================
193 // function : Release
194 // purpose  :
195 // =======================================================================
196 void OpenGl_GraduatedTrihedron::Release (const Handle(OpenGl_Context)& theCtx)
197 {
198   myLabelX.Release (theCtx);
199   myLabelY.Release (theCtx);
200   myLabelZ.Release (theCtx);
201   myLabelValues.Release (theCtx);
202 }
203
204 OpenGl_GraduatedTrihedron::OpenGl_GraduatedTrihedron (const Graphic3d_CGraduatedTrihedron& theData)
205 : myLabelX (theData.xname, OpenGl_Vec3(1.0f, 0.0f, 0.0f), THE_LABEL_PARAMS),
206   myLabelY (theData.yname, OpenGl_Vec3(0.0f, 1.0f, 0.0f), THE_LABEL_PARAMS),
207   myLabelZ (theData.zname, OpenGl_Vec3(0.0f, 0.0f, 1.0f), THE_LABEL_PARAMS),
208   myToDrawXName (theData.xdrawname == Standard_True),
209   myToDrawYName (theData.ydrawname == Standard_True),
210   myToDrawZName (theData.zdrawname == Standard_True),
211   myToDrawXValues (theData.xdrawvalues == Standard_True),
212   myToDrawYValues (theData.ydrawvalues == Standard_True),
213   myToDrawZValues (theData.zdrawvalues == Standard_True),
214   myToDrawGrid (theData.drawgrid == Standard_True),
215   myToDrawAxes (theData.drawaxes == Standard_True),
216   myNbX (theData.nbx),
217   myNbY (theData.nby),
218   myNbZ (theData.nbz),
219   myXOffset (theData.xoffset),
220   myYOffset (theData.yoffset),
221   myZOffset (theData.zoffset),
222   myXAxisOffset (theData.xaxisoffset),
223   myYAxisOffset (theData.yaxisoffset),
224   myZAxisOffset (theData.zaxisoffset),
225   myDrawXTickmarks (theData.xdrawtickmarks),
226   myDrawYTickmarks (theData.ydrawtickmarks),
227   myDrawZTickmarks (theData.zdrawtickmarks),
228   myXTickmarkLength (theData.xtickmarklength),
229   myYTickmarkLength (theData.ytickmarklength),
230   myZTickmarkLength (theData.ztickmarklength),
231   myCbCubicAxes (theData.cbCubicAxes),
232   myPtrVisual3dView (theData.ptrVisual3dView)
233 {
234   myAspectLabels.ChangeFontName() = theData.fontOfNames;
235   myAspectValues.ChangeFontName() = theData.fontOfValues;
236   myAspectLabels.SetFontAspect (theData.styleOfNames);
237   myAspectValues.SetFontAspect (theData.styleOfValues);
238   myLabelX.SetFontSize (NULL, theData.sizeOfNames);
239   myLabelY.SetFontSize (NULL, theData.sizeOfNames);
240   myLabelZ.SetFontSize (NULL, theData.sizeOfNames);
241   myLabelValues.SetFontSize (NULL, theData.sizeOfValues);
242
243   // Grid color
244   myGridColor[0] = (float) theData.gridcolor.Red();
245   myGridColor[1] = (float) theData.gridcolor.Green();
246   myGridColor[2] = (float) theData.gridcolor.Blue();
247   // X name color
248   myXNameColor.rgb[0] = (float )theData.xnamecolor.Red();
249   myXNameColor.rgb[1] = (float )theData.xnamecolor.Green();
250   myXNameColor.rgb[2] = (float )theData.xnamecolor.Blue();
251   myXNameColor.rgb[3] = 1.0f;
252   // Y name color
253   myYNameColor.rgb[0] = (float )theData.ynamecolor.Red();
254   myYNameColor.rgb[1] = (float )theData.ynamecolor.Green();
255   myYNameColor.rgb[2] = (float )theData.ynamecolor.Blue();
256   myYNameColor.rgb[3] = 1.0f;
257   // Z name color
258   myZNameColor.rgb[0] = (float )theData.znamecolor.Red();
259   myZNameColor.rgb[1] = (float )theData.znamecolor.Green();
260   myZNameColor.rgb[2] = (float )theData.znamecolor.Blue();
261   myZNameColor.rgb[3] = 1.0f;
262   // X color of axis and values
263   myXColor.rgb[0] = (float )theData.xcolor.Red();
264   myXColor.rgb[1] = (float )theData.xcolor.Green();
265   myXColor.rgb[2] = (float )theData.xcolor.Blue();
266   myXColor.rgb[3] = 1.0f;
267   // Y color of axis and values
268   myYColor.rgb[0] = (float )theData.ycolor.Red();
269   myYColor.rgb[1] = (float )theData.ycolor.Green();
270   myYColor.rgb[2] = (float )theData.ycolor.Blue();
271   myYColor.rgb[3] = 1.0f;
272   // Z color of axis and values
273   myZColor.rgb[0] = (float )theData.zcolor.Red();
274   myZColor.rgb[1] = (float )theData.zcolor.Green();
275   myZColor.rgb[2] = (float )theData.zcolor.Blue();
276   myZColor.rgb[3] = 1.0f;
277 }
278
279 OpenGl_GraduatedTrihedron::~OpenGl_GraduatedTrihedron()
280 {
281   //
282 }
283
284 //call_graduatedtrihedron_redraw
285 void OpenGl_GraduatedTrihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
286 {
287   const OpenGl_AspectLine *oldAspectLine = theWorkspace->SetAspectLine(&myDefaultAspectLine);
288   theWorkspace->AspectLine(Standard_True);
289
290   /* Update boundary box */
291   if (myCbCubicAxes)
292     myCbCubicAxes(myPtrVisual3dView);
293
294   /* Disable lighting for lines */
295   GLboolean light = glIsEnabled(GL_LIGHTING);
296   if (light)
297     glDisable(GL_LIGHTING);
298
299   /* Find the farest point of bounding box */
300
301   /* Get normal of the view out of user. */
302   /* Also, the method return distance corresponding to 1 pixel */
303   float normal[3];
304   float dpix = getNormal(normal);
305
306   /* Normalize normal */
307   float d = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
308   normal[0] /= d;
309   normal[1] /= d;
310   normal[2] /= d;
311
312   /* Get central point of bounding box */
313   float center[3];
314   center[0] = 0.5f * (xmin + xmax);
315   center[1] = 0.5f * (ymin + ymax);
316   center[2] = 0.5f * (zmin + zmax);
317
318   /* Check distance to corners of bounding box along the normal */
319   float d000 = getDistance2Corner(normal, center, xmin, ymin, zmin);
320   float d100 = getDistance2Corner(normal, center, xmax, ymin, zmin);
321   float d010 = getDistance2Corner(normal, center, xmin, ymax, zmin);
322   float d001 = getDistance2Corner(normal, center, xmin, ymin, zmax);
323   float d110 = getDistance2Corner(normal, center, xmax, ymax, zmin);
324   float d101 = getDistance2Corner(normal, center, xmax, ymin, zmax);
325   float d011 = getDistance2Corner(normal, center, xmin, ymax, zmax);
326   float d111 = getDistance2Corner(normal, center, xmax, ymax, zmax);
327   unsigned char farestCorner = getFarestCorner(d000, d100, d010, d001, d110, d101, d011, d111);
328
329   /* Choose axes for the grid. */
330   float LX1[6], LX2[6], LX3[6]; /* Lines along X direction */
331   float LY1[6], LY2[6], LY3[6]; /* Lines along Y direction */
332   float LZ1[6], LZ2[6], LZ3[6]; /* Lines along Z direction */
333   unsigned char LX1draw, LX2draw, LX3draw; /* Allows drawing of X-line (000 - 100 is forbidden) */
334   unsigned char LY1draw, LY2draw, LY3draw; /* Allows drawing of Y-line (000 - 010 is forbidden) */
335   unsigned char LZ1draw, LZ2draw, LZ3draw; /* Allows drawing of Z-line (000 - 001 is forbidden) */
336
337   /* The first axis will be used for drawing the text and the values. */
338   switch (farestCorner)
339   {
340     case 1: /* d000 */
341     {
342       /* 001 - 101 */
343       LX1draw = 1;
344       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
345       /* 000 - 100 */
346       LX2draw = 0; /* forbidden! */
347       LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmin;
348       /* 010 - 110 */
349       LX3draw = 1;
350       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
351
352       /* 100 - 110 */
353       LY1draw = 1;
354       LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
355       /* 000 - 010 */
356       LY2draw = 0; /* forbidden! */
357       LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmin;
358       /* 001 - 011 */
359       LY3draw = 1;
360       LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
361
362       /* 100 - 101 */
363       LZ1draw = 1;
364       LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
365       /* 000 - 001 */
366       LZ2draw = 0; /* forbidden! */
367       LZ2[0] = xmin; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymin; LZ2[5] = zmax;
368       /* 010 - 011 */
369       LZ3draw = 1;
370       LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
371
372       break;
373     }
374     case 2: /* d100 */
375     {
376       /* 001 - 101 */
377       LX1draw = 1;
378       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
379       /* 000 - 100 */
380       LX2draw = 0; /* forbidden! */
381       LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmin;
382       /* 010 - 110 */
383       LX3draw = 1;
384       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
385
386       /* 000 - 010 */
387       LY1draw = 0; /* forbidden! */
388       LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
389       /* 100 - 110 */
390       LY2draw = 1;
391       LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmin;
392       /* 101 - 111 */
393       LY3draw = 1;
394       LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
395
396       /* 000 - 001 */
397       LZ1draw = 0; /* forbidden! */
398       LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
399       /* 100 - 101 */
400       LZ2draw = 1;
401       LZ2[0] = xmax; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymin; LZ2[5] = zmax;
402       /* 110 - 111 */
403       LZ3draw = 1;
404       LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
405
406       break;
407     }
408     case 3: /* d010 */
409     {
410       /* 000 - 100 */
411       LX1draw = 0; /* forbidden */
412       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
413       /* 010 - 110 */
414       LX2draw = 1;
415       LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmin;
416       /* 011 - 111 */
417       LX3draw = 1;
418       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
419
420       /* 100 - 110 */
421       LY1draw = 1;
422       LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
423       /* 000 - 010 */
424       LY2draw = 0; /* forbidden */
425       LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmin;
426       /* 001 - 011 */
427       LY3draw = 1;
428       LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
429
430       /* 110 - 111 */
431       LZ1draw = 1;
432       LZ1[0] = xmax; LZ1[1] = ymax; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymax; LZ1[5] = zmax;
433       /* 010 - 011 */
434       LZ2draw = 1;
435       LZ2[0] = xmin; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymax; LZ2[5] = zmax;
436       /* 000 - 001 */
437       LZ3draw = 0; /* forbidden */
438       LZ3[0] = xmin; LZ3[1] = ymin; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymin; LZ3[5] = zmax;
439
440       break;
441     }
442     case 4: /* d001 */
443     {
444       /* 000 - 100 */
445       LX1draw = 0; /* forbidden */
446       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
447       /* 001 - 101 */
448       LX2draw = 1;
449       LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmax;
450       /* 011 - 111 */
451       LX3draw = 1;
452       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
453
454       /* 000 - 010 */
455       LY1draw = 0; /* forbidden */
456       LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
457       /* 001 - 011 */
458       LY2draw = 1;
459       LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmax;
460       /* 101 - 111 */
461       LY3draw = 1;
462       LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
463
464       /* 100 - 101 */
465       LZ1draw = 1;
466       LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
467       /* 000 - 001 */
468       LZ2draw = 0; /* forbidden */
469       LZ2[0] = xmin; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymin; LZ2[5] = zmax;
470       /* 010 - 011 */
471       LZ3draw = 1;
472       LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
473
474       break;
475     }
476     case 5: /* d110 */
477     {
478       /* 000 - 100 */
479       LX1draw = 0; /* forbidden */
480       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
481       /* 010 - 110 */
482       LX2draw = 1;
483       LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmin;
484       /* 011 - 111 */
485       LX3draw = 1;
486       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
487
488       /* 000 - 010 */
489       LY1draw = 0; /* forbidden */
490       LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
491       /* 100 - 110 */
492       LY2draw = 1;
493       LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmin;
494       /* 101 - 111 */
495       LY3draw = 1;
496       LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
497
498       /* 100 - 101 */
499       LZ1draw = 1;
500       LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
501       /* 110 - 111 */
502       LZ2draw = 1;
503       LZ2[0] = xmax; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymax; LZ2[5] = zmax;
504       /* 010 - 011 */
505       LZ3draw = 1;
506       LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
507
508       break;
509     }
510     case 6: /* d101 */
511     {
512       /* 000 - 100 */
513       LX1draw = 0; /* forbidden */
514       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
515       /* 001 - 101 */
516       LX2draw = 1;
517       LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmax;
518       /* 011 - 111 */
519       LX3draw = 1;
520       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
521
522       /* 100 - 110 */
523       LY1draw = 1;
524       LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
525       /* 101 - 111 */
526       LY2draw = 1;
527       LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmax;
528       /* 001 - 011 */
529       LY3draw = 1;
530       LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
531
532       /* 000 - 001 */
533       LZ1draw = 0; /* forbidden */
534       LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
535       /* 100 - 101 */
536       LZ2draw = 1;
537       LZ2[0] = xmax; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymin; LZ2[5] = zmax;
538       /* 110 - 111 */
539       LZ3draw = 1;
540       LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
541
542       break;
543     }
544     case 7: /* d011 */
545     {
546       /* 001 - 101 */
547       LX1draw = 1;
548       LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
549       /* 011 - 111 */
550       LX2draw = 1;
551       LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmax;
552       /* 010 - 110 */
553       LX3draw = 1;
554       LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
555
556       /* 000 - 010 */
557       LY1draw = 0; /* forbidden */
558       LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
559       /* 001 - 011 */
560       LY2draw = 1;
561       LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmax;
562       /* 101 - 111 */
563       LY3draw = 1;
564       LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
565
566       /* 000 - 001 */
567       LZ1draw = 0; /* forbidden */
568       LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
569       /* 010 - 011 */
570       LZ2draw = 1;
571       LZ2[0] = xmin; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymax; LZ2[5] = zmax;
572       /* 110 - 111 */
573       LZ3draw = 1;
574       LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
575
576       break;
577     }
578     case 8: /* d111 */
579     {
580       /* 010 - 110 */
581       LX1draw = 1;
582       LX1[0] = xmin; LX1[1] = ymax; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymax; LX1[5] = zmin;
583       /* 011 - 111 */
584       LX2draw = 1;
585       LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmax;
586       /* 001 - 101 */
587       LX3draw = 1;
588       LX3[0] = xmin; LX3[1] = ymin; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymin; LX3[5] = zmax;
589
590       /* 100 - 110 */
591       LY1draw = 1;
592       LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
593       /* 101 - 111 */
594       LY2draw = 1;
595       LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmax;
596       /* 001 - 011 */
597       LY3draw = 1;
598       LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
599
600       /* 100 - 101 */
601       LZ1draw = 1;
602       LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
603       /* 110 - 111 */
604       LZ2draw = 1;
605       LZ2[0] = xmax; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymax; LZ2[5] = zmax;
606       /* 010 - 011 */
607       LZ3draw = 1;
608       LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
609
610       break;
611     }
612   }
613
614   // Draw the graduated trihedron
615   unsigned int i, offset;
616   float m1[3], m2[3];
617   float step, dx, dy, dz;
618
619   // Grid
620   if (myToDrawGrid)
621   {
622     glColor3fv(myGridColor);
623     glBegin(GL_LINES);
624     // Boundary grid-lines
625     if (LX1draw == 1)
626     {
627       glVertex3fv(&(LX1[0]));
628       glVertex3fv(&(LX1[3]));
629     }
630     if (LX2draw == 1)
631     {
632       glVertex3fv(&(LX2[0]));
633       glVertex3fv(&(LX2[3]));
634     }
635     if (LX3draw == 1)
636     {
637       glVertex3fv(&(LX3[0]));
638       glVertex3fv(&(LX3[3]));
639     }
640     if (LY1draw == 1)
641     {
642       glVertex3fv(&(LY1[0]));
643       glVertex3fv(&(LY1[3]));
644     }
645     if (LY2draw == 1)
646     {
647       glVertex3fv(&(LY2[0]));
648       glVertex3fv(&(LY2[3]));
649     }
650     if (LY3draw == 1)
651     {
652       glVertex3fv(&(LY3[0]));
653       glVertex3fv(&(LY3[3]));
654     }
655     if (LZ1draw == 1)
656     {
657       glVertex3fv(&(LZ1[0]));
658       glVertex3fv(&(LZ1[3]));
659     }
660     if (LZ2draw == 1)
661     {
662       glVertex3fv(&(LZ2[0]));
663       glVertex3fv(&(LZ2[3]));
664     }
665     if (LZ3draw == 1)
666     {
667       glVertex3fv(&(LZ3[0]));
668       glVertex3fv(&(LZ3[3]));
669     }
670     glEnd();
671
672     /* Intermediate grid-lines */
673     /* X-Grid lines */
674     if (myNbX > 0)
675     {
676       i = myToDrawAxes ? 1 : 0;
677       step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
678       while (i < myNbX)
679       {
680         glBegin(GL_LINE_STRIP);
681         glVertex3f(LX1[0] + i * step, LX1[1], LX1[2]);
682         glVertex3f(LX2[0] + i * step, LX2[1], LX2[2]);
683         glVertex3f(LX3[0] + i * step, LX3[1], LX3[2]);
684         glEnd();
685         i++;
686       }
687     }
688     /* Y-Grid lines */
689     if (myNbY > 0)
690     {
691       i = myToDrawAxes ? 1 : 0;
692       step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
693       while (i < myNbY)
694       {
695         glBegin(GL_LINE_STRIP);
696         glVertex3f(LY1[0], LY1[1] + i * step, LY1[2]);
697         glVertex3f(LY2[0], LY2[1] + i * step, LY2[2]);
698         glVertex3f(LY3[0], LY3[1] + i * step, LY3[2]);
699         glEnd();
700         i++;
701       }
702     }
703     /* Z-Grid lines */
704     if (myNbZ > 0)
705     {
706       i = myToDrawAxes ? 1 : 0;
707       step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
708
709       while (i < myNbZ)
710       {
711         glBegin(GL_LINE_STRIP);
712         glVertex3f(LZ1[0], LZ1[1], LZ1[2] + i * step);
713         glVertex3f(LZ2[0], LZ2[1], LZ2[2] + i * step);
714         glVertex3f(LZ3[0], LZ3[1], LZ3[2] + i * step);
715         glEnd();
716         i++;
717       }
718     }
719   }
720
721   // Axes (arrows)
722   if (myToDrawAxes)
723   {
724     // X-axis
725     glColor3fv(myXColor.rgb);
726     drawArrow(xmin, ymin, zmin, xmax, ymin, zmin, normal[0], normal[1], normal[2]);
727
728     // Y-axis
729     glColor3fv(myYColor.rgb);
730     drawArrow(xmin, ymin, zmin, xmin, ymax, zmin, normal[0], normal[1], normal[2]);
731
732     // Z-axis
733     glColor3fv(myZColor.rgb);
734     drawArrow(xmin, ymin, zmin, xmin, ymin, zmax, normal[0], normal[1], normal[2]);
735   }
736
737   // Names of axes & values
738   char textValue[128];
739
740   if (myToDrawXName || myToDrawXValues)
741   {
742     // Middle point of the first X-axis
743     m1[0] = 0.5f * (LX1[0] + LX1[3]);
744     m1[1] = 0.5f * (LX1[1] + LX1[4]);
745     m1[2] = 0.5f * (LX1[2] + LX1[5]);
746
747     // Middle point of the second X-axis
748     m2[0] = 0.5f * (LX2[0] + LX2[3]);
749     m2[1] = 0.5f * (LX2[1] + LX2[4]);
750     m2[2] = 0.5f * (LX2[2] + LX2[5]);
751
752     // Apply offset to m1
753     dy = m1[1] - m2[1];
754     if (fabsf(dy) > 1.e-7f)
755     {
756       dy = (dy > 0.0f)? 1.0f : -1.0f;
757     }
758     dz = m1[2] - m2[2];
759     if (fabsf(dz) > 1.e-7f)
760     {
761       dz = (dz > 0.0f)? 1.0f : -1.0f;
762     }
763     m2[1] = dpix * dy;
764     m2[2] = dpix * dz;
765
766     // Name of X-axis
767     if (myToDrawXName)
768     {
769       offset = myXAxisOffset + myXTickmarkLength;
770
771       // draw axes labels
772       myAspectLabels.ChangeColor() = myXNameColor;
773       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectLabels);
774       myLabelX.SetPosition (OpenGl_Vec3(m1[0], m1[1] + offset * m2[1], m1[2] + offset * m2[2]));
775       myLabelX.Render (theWorkspace);
776       theWorkspace->SetAspectText (aPrevAspectText);
777     }
778
779     // X-values
780     if (myToDrawXValues && myNbX > 0)
781     {
782       myAspectValues.ChangeColor() = myXColor;
783       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectValues);
784
785       step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
786       offset = myXOffset + myXTickmarkLength;
787       for (unsigned int anIter = 0; anIter <= myNbX; ++anIter)
788       {
789         sprintf (textValue, "%g", LX1[0] + anIter * step);
790         myLabelValues.Init (theWorkspace->GetGlContext(), textValue,
791                             OpenGl_Vec3(LX1[0] + anIter * step, m1[1] + offset * m2[1], m1[2] + offset * m2[2]));
792         myLabelValues.Render (theWorkspace);
793       }
794       theWorkspace->SetAspectText (aPrevAspectText);
795     }
796
797     // X-tickmark
798     if (myDrawXTickmarks && myNbX > 0)
799     {
800       glColor3fv(myGridColor);
801
802       step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
803       for (unsigned int anIter = 0; anIter <= myNbX; ++anIter)
804       {
805         glBegin(GL_LINES);
806         glVertex3f(LX1[0] + anIter * step, m1[1],                             m1[2]);
807         glVertex3f(LX1[0] + anIter * step, m1[1] + myXTickmarkLength * m2[1], m1[2] + myXTickmarkLength * m2[2]);
808         glEnd();
809       }
810     }
811   }
812
813   if (myToDrawYName || myToDrawYValues)
814   {
815     // Middle point of the first Y-axis
816     m1[0] = 0.5f * (LY1[0] + LY1[3]);
817     m1[1] = 0.5f * (LY1[1] + LY1[4]);
818     m1[2] = 0.5f * (LY1[2] + LY1[5]);
819
820     // Middle point of the second Y-axis
821     m2[0] = 0.5f * (LY2[0] + LY2[3]);
822     m2[1] = 0.5f * (LY2[1] + LY2[4]);
823     m2[2] = 0.5f * (LY2[2] + LY2[5]);
824
825     // Apply offset to m1
826     dx = m1[0] - m2[0];
827     if (fabsf(dx) > 1.e-7f)
828     {
829       dx = (dx > 0.0f)? 1.0f : -1.0f;
830     }
831     dz = m1[2] - m2[2];
832     if (fabsf(dz) > 1.e-7f)
833     {
834       dz = (dz > 0.0f)? 1.0f : -1.0f;
835     }
836
837     m2[0] = dpix * dx;
838     m2[2] = dpix * dz;
839
840     // Name of Y-axis
841     if (myToDrawYName)
842     {
843       offset = myYAxisOffset + myYTickmarkLength;
844
845       myAspectLabels.ChangeColor() = myYNameColor;
846       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectLabels);
847       myLabelY.SetPosition (OpenGl_Vec3(m1[0] + offset * m2[0], m1[1], m1[2] + offset * m2[2]));
848       myLabelY.Render (theWorkspace);
849       theWorkspace->SetAspectText (aPrevAspectText);
850     }
851
852     // Y-values
853     if (myToDrawYValues && myNbY > 0)
854     {
855       myAspectValues.ChangeColor() = myYColor;
856       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectValues);
857
858       step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
859       offset = myYOffset + myYTickmarkLength;
860       for (unsigned int anIter = 0; anIter <= myNbY; ++anIter)
861       {
862         sprintf (textValue, "%g", LY1[1] + anIter * step);
863         myLabelValues.Init (theWorkspace->GetGlContext(), textValue,
864                             OpenGl_Vec3(m1[0] + offset * m2[0], LY1[1] + anIter * step, m1[2] + offset * m2[2]));
865         myLabelValues.Render (theWorkspace);
866       }
867       theWorkspace->SetAspectText (aPrevAspectText);
868     }
869
870     // Y-tickmark
871     if (myDrawYTickmarks && myNbY > 0)
872     {
873       glColor3fv(myGridColor);
874
875       i = 0;
876       step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
877       while (i <= myNbY)
878       {
879         glBegin(GL_LINES);
880         glVertex3f(m1[0],                             LY1[1] + i * step, m1[2]);
881         glVertex3f(m1[0] + myYTickmarkLength * m2[0], LY1[1] + i * step, m1[2] + myYTickmarkLength * m2[2]);
882         glEnd();
883         i++;
884       }
885     }
886   }
887
888   if (myToDrawZName || myToDrawZValues)
889   {
890     // Middle point of the first Z-axis
891     m1[0] = 0.5f * (LZ1[0] + LZ1[3]);
892     m1[1] = 0.5f * (LZ1[1] + LZ1[4]);
893     m1[2] = 0.5f * (LZ1[2] + LZ1[5]);
894
895     // Middle point of the second Z-axis
896     m2[0] = 0.5f * (LZ2[0] + LZ2[3]);
897     m2[1] = 0.5f * (LZ2[1] + LZ2[4]);
898     m2[2] = 0.5f * (LZ2[2] + LZ2[5]);
899
900     // Apply offset to m1
901     dx = m1[0] - m2[0];
902     if (fabsf(dx) > 1.e-7f)
903     {
904       dx = (dx > 0.0f)? 1.0f : -1.0f;
905     }
906     dy = m1[1] - m2[1];
907     if (fabsf(dy) > 1.e-7f)
908     {
909       dy = (dy > 0.0f)? 1.0f : -1.0f;
910     }
911
912     m2[0] = dpix * dx;
913     m2[1] = dpix * dy;
914
915     // Name of Z-axis
916     if (myToDrawZName)
917     {
918       offset = myZAxisOffset + myZTickmarkLength;
919
920       myAspectLabels.ChangeColor() = myZNameColor;
921       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectLabels);
922       myLabelZ.SetPosition (OpenGl_Vec3(m1[0] + offset * m2[0], m1[1] + offset * m2[1], m1[2]));
923       myLabelZ.Render (theWorkspace);
924       theWorkspace->SetAspectText (aPrevAspectText);
925     }
926
927     // Z-values
928     if (myToDrawZValues && myNbZ > 0)
929     {
930       myAspectValues.ChangeColor() = myZColor;
931       const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectValues);
932
933       step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
934       offset = myZOffset + myZTickmarkLength;
935       for (unsigned int anIter = 0; anIter <= myNbZ; ++anIter)
936       {
937         sprintf (textValue, "%g", LZ1[2] + anIter * step);
938         myLabelValues.Init (theWorkspace->GetGlContext(), textValue,
939                             OpenGl_Vec3(m1[0] + offset * m2[0], m1[1] + offset * m2[1], LZ1[2] + anIter * step));
940         myLabelValues.Render (theWorkspace);
941       }
942       theWorkspace->SetAspectText (aPrevAspectText);
943     }
944
945     // Z-tickmark
946     if (myDrawZTickmarks && myNbZ > 0)
947     {
948       glColor3fv(myGridColor);
949
950       i = 0;
951       step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
952       while (i <= myNbZ)
953       {
954         glBegin(GL_LINES);
955         glVertex3f(m1[0],                             m1[1],                             LZ1[2] + i * step);
956         glVertex3f(m1[0] + myZTickmarkLength * m2[0], m1[1] + myZTickmarkLength * m2[1], LZ1[2] + i * step);
957         glEnd();
958         i++;
959       }
960     }
961   }
962
963   // Activate the lighting if it was turned off by this method call
964   if (light)
965     glEnable(GL_LIGHTING);
966
967   theWorkspace->SetAspectLine(oldAspectLine);
968 }
969
970 //call_graduatedtrihedron_minmaxvalues
971 void OpenGl_GraduatedTrihedron::SetMinMax (const Standard_ShortReal xMin, const Standard_ShortReal yMin, const Standard_ShortReal zMin,
972                                           const Standard_ShortReal xMax, const Standard_ShortReal yMax, const Standard_ShortReal zMax)
973 {
974   xmin = xMin;
975   ymin = yMin;
976   zmin = zMin;
977   xmax = xMax;
978   ymax = yMax;
979   zmax = zMax;
980 }