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