0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_GraduatedTrihedron.cxx
old mode 100644 (file)
new mode 100755 (executable)
index 183edb5..1bcefce
 // Created on: 2011-09-20
 // Created by: Sergey ZERCHANINOV
-// Copyright (c) 2011-2012 OPEN CASCADE SAS
+// Copyright (c) 2011-2013 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <OpenGl_GlCore11.hxx>
 
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <InterfaceGraphic_Graphic3d.hxx>
-#include <InterfaceGraphic_Aspect.hxx>
-#include <InterfaceGraphic_Visual3d.hxx>
-
-#include <GL/glu.h> // gluUnProject()
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
+#include <OpenGl_GraduatedTrihedron.hxx>
 
+#include <Graphic3d_ArrayOfPolylines.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_GraphicDriver.hxx>
+#include <Graphic3d_TransformPers.hxx>
+#include <Graphic3d_TransformUtils.hxx>
+#include <gp_Ax3.hxx>
 #include <OpenGl_Workspace.hxx>
 #include <OpenGl_View.hxx>
-#include <OpenGl_GraduatedTrihedron.hxx>
-#include <OpenGl_AspectLine.hxx>
+#include <Precision.hxx>
 
-IMPLEMENT_STANDARD_HANDLE(OpenGl_GraduatedTrihedron,MMgt_TShared)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraduatedTrihedron,MMgt_TShared)
+#ifndef _WIN32
+  #include <string.h>
+#endif
 
-const OpenGl_AspectLine myDefaultAspectLine;
+namespace
+{
+  static const OpenGl_TextParam THE_LABEL_PARAMS =
+  {
+    16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
+  };
+}
 
-/* Bounding box */
-float xmin = 0.0f, ymin = 0.0f, zmin = 0.0f, xmax = 100.0f, ymax = 100.0f, zmax = 100.0f;
+// =======================================================================
+// function : Constructor
+// purpose  :
+// =======================================================================
+OpenGl_GraduatedTrihedron::OpenGl_GraduatedTrihedron()
+: myMin (0.0f, 0.0f, 0.0f),
+  myMax (100.0f, 100.0f, 100.0f),
+  myIsInitialized (Standard_False)
+{
+  //
+}
 
-/* Normal of the view (not normalized!) */
-static float getNormal(float* normal) 
+// =======================================================================
+// function : SetValues
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::SetValues (const Graphic3d_GraduatedTrihedron& theData)
 {
-  GLint viewport[4];
-  GLdouble model_matrix[16], proj_matrix[16];
-
-  glGetDoublev(GL_MODELVIEW_MATRIX,  model_matrix);
-  glGetDoublev(GL_PROJECTION_MATRIX, proj_matrix);
-  glGetIntegerv(GL_VIEWPORT, viewport);
-
-  double x1, y1, z1, x2, y2, z2, x3, y3, z3;
-  gluUnProject(viewport[0], viewport[1], 0., model_matrix, proj_matrix, viewport, &x1, &y1, &z1);
-  gluUnProject(viewport[0] + viewport[2], viewport[1], 0., model_matrix, proj_matrix, viewport, &x2, &y2, &z2);
-  gluUnProject(viewport[0], viewport[1] + viewport[3], 0., model_matrix, proj_matrix, viewport, &x3, &y3, &z3);
-
-  /* Normal out of user is p1p3^p1p2 */
-  const double dx1 = x3 - x1;
-  const double dy1 = y3 - y1;
-  const double dz1 = z3 - z1;
-  const double dx2 = x2 - x1;
-  const double dy2 = y2 - y1;
-  const double dz2 = z2 - z1;
-  normal[0] = (float) (dy1 * dz2 - dz1 * dy2);
-  normal[1] = (float) (dz1 * dx2 - dx1 * dz2);
-  normal[2] = (float) (dx1 * dy2 - dy1 * dx2);
-
-  /* Distance corresponding to 1 pixel */
-  const float width = (float) sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);
-  return width / (float) viewport[2];
+  myData          = theData;
+  myIsInitialized = Standard_False;
 }
 
-static float getDistance2Corner(float* normal, float* center, float x, float y, float z)
+// =======================================================================
+// function : Destructor
+// purpose  :
+// =======================================================================
+OpenGl_GraduatedTrihedron::~OpenGl_GraduatedTrihedron()
 {
-    return normal[0] * (x - center[0]) + normal[1] * (y - center[1]) + normal[2] * (z - center[2]);
+  //
 }
 
-static char getFarestCorner(float d000, float d100, float d010, float d001, 
-                            float d110, float d101, float d011, float d111)
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Release (OpenGl_Context* theCtx)
 {
-    if (d000 > 0.0f && 
-        d000 > d100 && d000 > d010 && d000 > d001 && d000 > d110 && 
-        d000 > d101 && d000 > d011 && d000 > d111)
-    {
-        return 1;
-    }
-    else if (d100 > 0.0f &&
-             d100 > d000 && d100 > d010 && d100 > d001 && d100 > d110 && 
-             d100 > d101 && d100 > d011 && d100 > d111)
-    {
-        return 2;
-    }
-    else if (d010 > 0.0f &&
-             d010 > d000 && d010 > d100 && d010 > d001 && d010 > d110 && 
-             d010 > d101 && d010 > d011 && d010 > d111)
-    {
-        return 3;
-    }
-    else if (d001 > 0.0f &&
-             d001 > d000 && d001 > d100 && d001 > d010 && d001 > d110 && 
-             d001 > d101 && d001 > d011 && d001 > d111)
-    {
-        return 4;
-    }
-    else if (d110 > 0.0f &&
-             d110 > d000 && d110 > d100 && d110 > d010 && d110 > d001 && 
-             d110 > d101 && d110 > d011 && d110 > d111)
-    {
-        return 5;
-    }
-    else if (d101 > 0.0f &&
-             d101 > d000 && d101 > d100 && d101 > d010 && d101 > d001 && 
-             d101 > d110 && d101 > d011 && d101 > d111)
-    {
-        return 6;
-    }
-    else if (d011 > 0.0f &&
-             d011 > d000 && d011 > d100 && d011 > d010 && d011 > d001 && 
-             d011 > d110 && d011 > d101 && d011 > d111)
-    {
-        return 7;
-    }
-    return 8; /* d111 */
+  myAxes[0].Release (theCtx);
+  myAxes[1].Release (theCtx);
+  myAxes[2].Release (theCtx);
+  myLabelValues.Release (theCtx);
 }
 
-static void drawText(const Handle(OpenGl_Workspace) &AWorkspace, const wchar_t* text, const char* font, Font_FontAspect style, int size, float x, float y, float z)
+// =======================================================================
+// function : initResources
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::initGlResources (const Handle(OpenGl_Context)& theCtx) const
 {
-  AWorkspace->FindFont(font, style, size);
-  AWorkspace->RenderText(text, 0, x, y, z);
+  myAxes[0].Release     (theCtx.operator->());
+  myAxes[1].Release     (theCtx.operator->());
+  myAxes[2].Release     (theCtx.operator->());
+  myLabelValues.Release (theCtx.operator->());
+
+  // Initialize text label parameters for x, y, and z axes
+  myAxes[0] = Axis (myData.XAxisAspect(), OpenGl_Vec3 (1.0f, 0.0f, 0.0f));
+  myAxes[1] = Axis (myData.YAxisAspect(), OpenGl_Vec3 (0.0f, 1.0f, 0.0f));
+  myAxes[2] = Axis (myData.ZAxisAspect(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
+
+  // Initialize constant primitives: text, arrows.
+  myAxes[0].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
+  myAxes[1].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
+  myAxes[2].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (1.0f, 0.0f, 0.0f));
+  for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
+  {
+    myAxes[anIt].Label.SetFontSize (theCtx, myData.NamesSize());
+  }
 
-/* 4 OCC 6.3.1 and older:
-    GLuint fontBase;
+  myLabelValues.SetFontSize (theCtx, myData.ValuesSize());
 
-#ifndef WNT
-     fontBase = tXfmsetfont (1.0F, 1.0F);
-#else
-     fontBase = WNTSetFont (1.0F, 1.0F);
-#endif
+  myAspectLabels.Aspect()->SetTextFontAspect (myData.NamesFontAspect());
+  myAspectLabels.Aspect()->SetTextFont (!myData.NamesFont().IsEmpty()
+                                       ? new TCollection_HAsciiString (myData.NamesFont())
+                                       : Handle(TCollection_HAsciiString )());
 
-#ifndef WNT
-     tXfmprstr(text, fontBase, x, y, z);
-#else
-     WNTPuts(text, fontBase, 0, x, y, z);
-#endif
-*/
-}
+  myAspectValues.Aspect()->SetTextFontAspect (myData.ValuesFontAspect());
+  myAspectValues.Aspect()->SetTextFont (!myData.ValuesFont().IsEmpty()
+                                       ? new TCollection_HAsciiString (myData.ValuesFont())
+                                       : Handle(TCollection_HAsciiString )());
 
-static void drawArrow(float x1, float y1, float z1, 
-                      float x2, float y2, float z2,
-                      float xn, float yn, float zn)
-{
-    float h, r;
-    float xa, ya, za;
-    float x0, y0, z0;
-    float xr, yr, zr;
-    float xa1, ya1, za1, xa2, ya2, za2;
-
-    /* Start of arrow: at 10% from the end */
-    x0 = x1 + 0.9f * (x2 - x1); y0 = y1 + 0.9f * (y2 - y1); z0 = z1 + 0.9f * (z2 - z1);
-
-    /* Base of the arrow */
-    xa = (x2 - x0); ya = (y2 - y0); za = (z2 - z0);
-
-    /* Height of the arrow */
-    h = sqrtf(xa * xa + ya * ya + za * za);
-    if (h <= 0.0f)
-        return;
-    xa = xa / h; ya = ya / h; za = za / h;
-
-    /* Radial direction to the arrow */
-    xr = ya * zn - za * yn;
-    yr = za * xn - xa * zn;
-    zr = xa * yn - ya * xn;
-
-    /* Normalize the radial vector */
-    r = sqrtf(xr * xr + yr * yr + zr * zr);
-    if (r <= 0.0f)
-        return;
-    xr = xr / r; yr = yr / r; zr = zr / r;
-
-    /* First point of the base of the arrow */
-    r = 0.2f * h;
-    xr = r * xr; yr = r * yr; zr = r * zr;
-    xa1 = x0 + xr; ya1 = y0 + yr; za1 = z0 + zr;
-
-    /* Second point of the base of the arrow */
-    xa2 = x0 - xr; ya2 = y0 - yr; za2 = z0 - zr;
-
-    /* Draw a line to the arrow */
-    glBegin(GL_LINES);
-        glVertex3f(x1, y1, z1);
-        glVertex3f(x0, y0, z0);
-    glEnd();
-
-    /* Draw a triangle of the arrow */
-    glBegin(GL_LINE_LOOP);
-        glVertex3f(xa1, ya1, za1);
-        glVertex3f(xa2, ya2, za2);
-        glVertex3f(x2,  y2,  z2);
-    glEnd();
+  // Grid aspect
+  myGridLineAspect.Aspect()->SetColor (myData.GridColor());
 }
 
-OpenGl_GraduatedTrihedron::OpenGl_GraduatedTrihedron (const Graphic3d_CGraduatedTrihedron &AData)
-: myXName(NULL), myYName(NULL), myZName(NULL),
-  myDrawXName(AData.xdrawname), myDrawYName(AData.ydrawname), myDrawZName(AData.zdrawname),
-  myDrawXValues(AData.xdrawvalues), myDrawYValues(AData.ydrawvalues), myDrawZValues(AData.zdrawvalues),
-  myDrawGrid(AData.drawgrid), myDrawAxes(AData.drawaxes),
-  myNbX(AData.nbx), myNbY(AData.nby), myNbZ(AData.nbz),
-  myXOffset(AData.xoffset), myYOffset(AData.yoffset), myZOffset(AData.zoffset),
-  myXAxisOffset(AData.xaxisoffset), myYAxisOffset(AData.yaxisoffset), myZAxisOffset(AData.zaxisoffset),
-  myDrawXTickmarks(AData.xdrawtickmarks), myDrawYTickmarks(AData.ydrawtickmarks), myDrawZTickmarks(AData.zdrawtickmarks),
-  myXTickmarkLength(AData.xtickmarklength), myYTickmarkLength(AData.ytickmarklength), myZTickmarkLength(AData.ztickmarklength),
-  myFontOfNames(NULL),
-  myStyleOfNames(AData.styleOfNames),
-  mySizeOfNames(AData.sizeOfNames),
-  myFontOfValues(NULL),
-  myStyleOfValues(AData.styleOfValues),
-  mySizeOfValues(AData.sizeOfValues),
-  myCbCubicAxes(AData.cbCubicAxes),
-  myPtrVisual3dView(AData.ptrVisual3dView)
+// =======================================================================
+// method  : getNormal
+// purpose : Normal of the view (not normalized!)
+// =======================================================================
+Standard_ShortReal OpenGl_GraduatedTrihedron::getNormal (const Handle(OpenGl_Context)& theContext,
+                                                         OpenGl_Vec3& theNormal) const
 {
-  /* Names of axes */
-  /* X-name */
-  int len = AData.xname.Length();
-  if (len)
-  {
-    Standard_ExtString iname = AData.xname.ToExtString();
-    wchar_t *xname = new wchar_t[len+1];
-    len = 0; while (xname[len] = (wchar_t)(iname[len])) len++;
-    myXName = xname;
-  }
-  /* Y-name */
-  len = AData.yname.Length();
-  if (len)
-  {
-    Standard_ExtString iname = AData.yname.ToExtString();
-    wchar_t *yname = new wchar_t[len+1];
-    len = 0; while (yname[len] = (wchar_t)(iname[len])) len++;
-    myYName = yname;
-  }
-  /* Z-name */
-  len = AData.zname.Length();
-  if (len)
-  {
-    Standard_ExtString iname = AData.zname.ToExtString();
-    wchar_t *zname = new wchar_t[len+1];
-    len = 0; while (zname[len] = (wchar_t)(iname[len])) len++;
-    myZName = zname;
-  }
-  /* Grid color */
-  myGridColor[0] = (float) AData.gridcolor.Red();
-  myGridColor[1] = (float) AData.gridcolor.Green();
-  myGridColor[2] = (float) AData.gridcolor.Blue();
-  /* X name color */
-  myXNameColor[0] = (float) AData.xnamecolor.Red();
-  myXNameColor[1] = (float) AData.xnamecolor.Green();
-  myXNameColor[2] = (float) AData.xnamecolor.Blue();
-  /* Y name color */
-  myYNameColor[0] = (float) AData.ynamecolor.Red();
-  myYNameColor[1] = (float) AData.ynamecolor.Green();
-  myYNameColor[2] = (float) AData.ynamecolor.Blue();
-  /* Z name color */
-  myZNameColor[0] = (float) AData.znamecolor.Red();
-  myZNameColor[1] = (float) AData.znamecolor.Green();
-  myZNameColor[2] = (float) AData.znamecolor.Blue();
-  /* X color of axis and values */
-  myXColor[0] = (float) AData.xcolor.Red();
-  myXColor[1] = (float) AData.xcolor.Green();
-  myXColor[2] = (float) AData.xcolor.Blue();
-  /* Y color of axis and values */
-  myYColor[0] = (float) AData.ycolor.Red();
-  myYColor[1] = (float) AData.ycolor.Green();
-  myYColor[2] = (float) AData.ycolor.Blue();
-  /* Z color of axis and values */
-  myZColor[0] = (float) AData.zcolor.Red();
-  myZColor[1] = (float) AData.zcolor.Green();
-  myZColor[2] = (float) AData.zcolor.Blue();
-  /* Font name of names of axes: Courier, Arial, ... */
-  len = AData.fontOfNames.Length();
-  char *fontOfNames = new char[len+1];
-  if (len)
-    strcpy(fontOfNames, AData.fontOfNames.ToCString());
-  else
-    fontOfNames[0] = '\0';
-  myFontOfNames = fontOfNames;
-  /* Font name of values: Courier, Arial, ... */
-  len = AData.fontOfValues.Length();
-  char *fontOfValues = new char[len+1];
-  if (len)
-    strcpy(fontOfValues, AData.fontOfValues.ToCString());
-  else
-    fontOfValues[0] = '\0';
-  myFontOfValues = fontOfValues;
+  const Standard_Integer* aViewport = theContext->Viewport();
+
+  OpenGl_Mat4 aModelMatrix;
+  OpenGl_Mat4 aProjMatrix;
+  aModelMatrix.Convert (theContext->ModelWorldState.Current() * theContext->WorldViewState.Current());
+  aProjMatrix .Convert (theContext->ProjectionState.Current());
+
+  OpenGl_Vec3 aPoint1, aPoint2, aPoint3;
+  Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
+                                                           (Standard_ShortReal) aViewport[1],
+                                                           0.0f,
+                                                           aModelMatrix, aProjMatrix, aViewport,
+                                                           aPoint1.x(), aPoint1.y(), aPoint1.z());
+
+  Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) (aViewport[0] + aViewport[2]),
+                                                           (Standard_ShortReal) aViewport[1],
+                                                           0.0f,
+                                                           aModelMatrix, aProjMatrix, aViewport,
+                                                           aPoint2.x(), aPoint2.y(), aPoint2.z());
+
+  Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
+                                                           (Standard_ShortReal) (aViewport[1] + aViewport[3]),
+                                                           0.0f,
+                                                           aModelMatrix, aProjMatrix, aViewport,
+                                                           aPoint3.x(), aPoint3.y(), aPoint3.z());
+
+  const OpenGl_Vec3 aD1 = aPoint3 - aPoint1;
+  const OpenGl_Vec3 aD2 = aPoint2 - aPoint1;
+  theNormal =  OpenGl_Vec3::Cross (aD1, aD2);
+
+  // Distance corresponding to 1 pixel
+  return aD2.Modulus() / (float) aViewport[2];
 }
 
-OpenGl_GraduatedTrihedron::~OpenGl_GraduatedTrihedron ()
+// =======================================================================
+// method  : getDistancetoCorner
+// purpose : 
+// =======================================================================
+Standard_ShortReal OpenGl_GraduatedTrihedron::getDistanceToCorner (const OpenGl_Vec3& theNormal,
+                                                                   const OpenGl_Vec3& theCenter,
+                                                                   const Standard_ShortReal theX,
+                                                                   const Standard_ShortReal theY,
+                                                                   const Standard_ShortReal theZ) const
 {
-  // Names of axes
-  if (myXName)
-    delete[] myXName;
-  if (myYName)
-    delete[] myYName;
-  if (myZName)
-    delete[] myZName;
-
-  // Fonts
-  if (myFontOfNames)
-    delete[] myFontOfNames;
-  if (myFontOfValues)
-    delete[] myFontOfValues;
+  return theNormal.x() * (theX - theCenter.x())
+       + theNormal.y() * (theY - theCenter.y())
+       + theNormal.z() * (theZ - theCenter.z());
 }
 
-//call_graduatedtrihedron_redraw
-void OpenGl_GraduatedTrihedron::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+// =======================================================================
+// method  : getGridAxes
+// purpose : 
+// =======================================================================
+Standard_ExtCharacter OpenGl_GraduatedTrihedron::getGridAxes (const Standard_ShortReal theCorners[8],
+                                                              GridAxes& theGridAxes) const
 {
-  const OpenGl_AspectLine *oldAspectLine = AWorkspace->SetAspectLine(&myDefaultAspectLine);
-  AWorkspace->AspectLine(Standard_True);
-
-  /* Update boundary box */
-  if (myCbCubicAxes)
-    myCbCubicAxes(myPtrVisual3dView);
-
-  /* Disable lighting for lines */
-  GLboolean light = glIsEnabled(GL_LIGHTING);
-  if (light)
-    glDisable(GL_LIGHTING);
-
-  /* Find the farest point of bounding box */
-
-  /* Get normal of the view out of user. */
-  /* Also, the method return distance corresponding to 1 pixel */
-  float normal[3];
-  float dpix = getNormal(normal);
-
-  /* Normalize normal */
-  float d = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
-  normal[0] /= d;
-  normal[1] /= d;
-  normal[2] /= d;
-
-  /* Get central point of bounding box */
-  float center[3];
-  center[0] = 0.5f * (xmin + xmax);
-  center[1] = 0.5f * (ymin + ymax);
-  center[2] = 0.5f * (zmin + zmax);
-
-  /* Check distance to corners of bounding box along the normal */
-  float d000 = getDistance2Corner(normal, center, xmin, ymin, zmin);
-  float d100 = getDistance2Corner(normal, center, xmax, ymin, zmin);
-  float d010 = getDistance2Corner(normal, center, xmin, ymax, zmin);
-  float d001 = getDistance2Corner(normal, center, xmin, ymin, zmax);
-  float d110 = getDistance2Corner(normal, center, xmax, ymax, zmin);
-  float d101 = getDistance2Corner(normal, center, xmax, ymin, zmax);
-  float d011 = getDistance2Corner(normal, center, xmin, ymax, zmax);
-  float d111 = getDistance2Corner(normal, center, xmax, ymax, zmax);
-  unsigned char farestCorner = getFarestCorner(d000, d100, d010, d001, d110, d101, d011, d111);
-
-  /* Choose axes for the grid. */
-  float LX1[6], LX2[6], LX3[6]; /* Lines along X direction */
-  float LY1[6], LY2[6], LY3[6]; /* Lines along Y direction */
-  float LZ1[6], LZ2[6], LZ3[6]; /* Lines along Z direction */
-  unsigned char LX1draw, LX2draw, LX3draw; /* Allows drawing of X-line (000 - 100 is forbidden) */
-  unsigned char LY1draw, LY2draw, LY3draw; /* Allows drawing of Y-line (000 - 010 is forbidden) */
-  unsigned char LZ1draw, LZ2draw, LZ3draw; /* Allows drawing of Z-line (000 - 001 is forbidden) */
-
-  /* The first axis will be used for drawing the text and the values. */
-  switch (farestCorner)
+  // Find the farest corner
+  Standard_Byte aMaxIndex = 0;
+  Standard_ShortReal aMax = theCorners[aMaxIndex] > 0.0f ? theCorners[aMaxIndex] : 0.0f;
+
+  for (Standard_Byte anIt = 0; anIt < 8; ++anIt)
   {
-    case 1: /* d000 */
-    {
-      /* 001 - 101 */
-      LX1draw = 1;
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
-      /* 000 - 100 */
-      LX2draw = 0; /* forbidden! */
-      LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmin;
-      /* 010 - 110 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
-
-      /* 100 - 110 */
-      LY1draw = 1;
-      LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
-      /* 000 - 010 */
-      LY2draw = 0; /* forbidden! */
-      LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmin;
-      /* 001 - 011 */
-      LY3draw = 1;
-      LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 100 - 101 */
-      LZ1draw = 1;
-      LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 000 - 001 */
-      LZ2draw = 0; /* forbidden! */
-      LZ2[0] = xmin; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymin; LZ2[5] = zmax;
-      /* 010 - 011 */
-      LZ3draw = 1;
-      LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 2: /* d100 */
-    {
-      /* 001 - 101 */
-      LX1draw = 1;
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
-      /* 000 - 100 */
-      LX2draw = 0; /* forbidden! */
-      LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmin;
-      /* 010 - 110 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
-
-      /* 000 - 010 */
-      LY1draw = 0; /* forbidden! */
-      LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
-      /* 100 - 110 */
-      LY2draw = 1;
-      LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmin;
-      /* 101 - 111 */
-      LY3draw = 1;
-      LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 000 - 001 */
-      LZ1draw = 0; /* forbidden! */
-      LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 100 - 101 */
-      LZ2draw = 1;
-      LZ2[0] = xmax; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymin; LZ2[5] = zmax;
-      /* 110 - 111 */
-      LZ3draw = 1;
-      LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 3: /* d010 */
-    {
-      /* 000 - 100 */
-      LX1draw = 0; /* forbidden */
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
-      /* 010 - 110 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmin;
-      /* 011 - 111 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
-
-      /* 100 - 110 */
-      LY1draw = 1;
-      LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
-      /* 000 - 010 */
-      LY2draw = 0; /* forbidden */
-      LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmin;
-      /* 001 - 011 */
-      LY3draw = 1;
-      LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 110 - 111 */
-      LZ1draw = 1;
-      LZ1[0] = xmax; LZ1[1] = ymax; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymax; LZ1[5] = zmax;
-      /* 010 - 011 */
-      LZ2draw = 1;
-      LZ2[0] = xmin; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymax; LZ2[5] = zmax;
-      /* 000 - 001 */
-      LZ3draw = 0; /* forbidden */
-      LZ3[0] = xmin; LZ3[1] = ymin; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymin; LZ3[5] = zmax;
-
-      break;
-    }
-    case 4: /* d001 */
-    {
-      /* 000 - 100 */
-      LX1draw = 0; /* forbidden */
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
-      /* 001 - 101 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmax;
-      /* 011 - 111 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
-
-      /* 000 - 010 */
-      LY1draw = 0; /* forbidden */
-      LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
-      /* 001 - 011 */
-      LY2draw = 1;
-      LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmax;
-      /* 101 - 111 */
-      LY3draw = 1;
-      LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 100 - 101 */
-      LZ1draw = 1;
-      LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 000 - 001 */
-      LZ2draw = 0; /* forbidden */
-      LZ2[0] = xmin; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymin; LZ2[5] = zmax;
-      /* 010 - 011 */
-      LZ3draw = 1;
-      LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 5: /* d110 */
-    {
-      /* 000 - 100 */
-      LX1draw = 0; /* forbidden */
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
-      /* 010 - 110 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmin; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmin;
-      /* 011 - 111 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
-
-      /* 000 - 010 */
-      LY1draw = 0; /* forbidden */
-      LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
-      /* 100 - 110 */
-      LY2draw = 1;
-      LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmin; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmin;
-      /* 101 - 111 */
-      LY3draw = 1;
-      LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 100 - 101 */
-      LZ1draw = 1;
-      LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 110 - 111 */
-      LZ2draw = 1;
-      LZ2[0] = xmax; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymax; LZ2[5] = zmax;
-      /* 010 - 011 */
-      LZ3draw = 1;
-      LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 6: /* d101 */
-    {
-      /* 000 - 100 */
-      LX1draw = 0; /* forbidden */
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmin;
-      /* 001 - 101 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymin; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymin; LX2[5] = zmax;
-      /* 011 - 111 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmax;
-
-      /* 100 - 110 */
-      LY1draw = 1;
-      LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
-      /* 101 - 111 */
-      LY2draw = 1;
-      LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmax;
-      /* 001 - 011 */
-      LY3draw = 1;
-      LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 000 - 001 */
-      LZ1draw = 0; /* forbidden */
-      LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 100 - 101 */
-      LZ2draw = 1;
-      LZ2[0] = xmax; LZ2[1] = ymin; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymin; LZ2[5] = zmax;
-      /* 110 - 111 */
-      LZ3draw = 1;
-      LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 7: /* d011 */
-    {
-      /* 001 - 101 */
-      LX1draw = 1;
-      LX1[0] = xmin; LX1[1] = ymin; LX1[2] = zmax; LX1[3] = xmax; LX1[4] = ymin; LX1[5] = zmax;
-      /* 011 - 111 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmax;
-      /* 010 - 110 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymax; LX3[2] = zmin; LX3[3] = xmax; LX3[4] = ymax; LX3[5] = zmin;
-
-      /* 000 - 010 */
-      LY1draw = 0; /* forbidden */
-      LY1[0] = xmin; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmin; LY1[4] = ymax; LY1[5] = zmin;
-      /* 001 - 011 */
-      LY2draw = 1;
-      LY2[0] = xmin; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmin; LY2[4] = ymax; LY2[5] = zmax;
-      /* 101 - 111 */
-      LY3draw = 1;
-      LY3[0] = xmax; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmax; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 000 - 001 */
-      LZ1draw = 0; /* forbidden */
-      LZ1[0] = xmin; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmin; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 010 - 011 */
-      LZ2draw = 1;
-      LZ2[0] = xmin; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmin; LZ2[4] = ymax; LZ2[5] = zmax;
-      /* 110 - 111 */
-      LZ3draw = 1;
-      LZ3[0] = xmax; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmax; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
-    }
-    case 8: /* d111 */
+    if (theCorners[anIt] > aMax)
     {
-      /* 010 - 110 */
-      LX1draw = 1;
-      LX1[0] = xmin; LX1[1] = ymax; LX1[2] = zmin; LX1[3] = xmax; LX1[4] = ymax; LX1[5] = zmin;
-      /* 011 - 111 */
-      LX2draw = 1;
-      LX2[0] = xmin; LX2[1] = ymax; LX2[2] = zmax; LX2[3] = xmax; LX2[4] = ymax; LX2[5] = zmax;
-      /* 001 - 101 */
-      LX3draw = 1;
-      LX3[0] = xmin; LX3[1] = ymin; LX3[2] = zmax; LX3[3] = xmax; LX3[4] = ymin; LX3[5] = zmax;
-
-      /* 100 - 110 */
-      LY1draw = 1;
-      LY1[0] = xmax; LY1[1] = ymin; LY1[2] = zmin; LY1[3] = xmax; LY1[4] = ymax; LY1[5] = zmin;
-      /* 101 - 111 */
-      LY2draw = 1;
-      LY2[0] = xmax; LY2[1] = ymin; LY2[2] = zmax; LY2[3] = xmax; LY2[4] = ymax; LY2[5] = zmax;
-      /* 001 - 011 */
-      LY3draw = 1;
-      LY3[0] = xmin; LY3[1] = ymin; LY3[2] = zmax; LY3[3] = xmin; LY3[4] = ymax; LY3[5] = zmax;
-
-      /* 100 - 101 */
-      LZ1draw = 1;
-      LZ1[0] = xmax; LZ1[1] = ymin; LZ1[2] = zmin; LZ1[3] = xmax; LZ1[4] = ymin; LZ1[5] = zmax;
-      /* 110 - 111 */
-      LZ2draw = 1;
-      LZ2[0] = xmax; LZ2[1] = ymax; LZ2[2] = zmin; LZ2[3] = xmax; LZ2[4] = ymax; LZ2[5] = zmax;
-      /* 010 - 011 */
-      LZ3draw = 1;
-      LZ3[0] = xmin; LZ3[1] = ymax; LZ3[2] = zmin; LZ3[3] = xmin; LZ3[4] = ymax; LZ3[5] = zmax;
-
-      break;
+      aMax = theCorners[anIt];
+      aMaxIndex = anIt;
     }
   }
 
-  /* Draw the graduated trihedron */
-  unsigned int i, j, offset;
-  float m1[3], m2[3];
-  float step, dx, dy, dz;
-
-  /* Grid */
-  if (myDrawGrid)
+  switch (aMaxIndex)
   {
-    glColor3fv(myGridColor);
-    glBegin(GL_LINES);
-    /* Boundary grid-lines */
-    if (LX1draw == 1)
-    {
-      glVertex3fv(&(LX1[0]));
-      glVertex3fv(&(LX1[3]));
-    }
-    if (LX2draw == 1)
+    case 0: // (0,0,0)
     {
-      glVertex3fv(&(LX2[0]));
-      glVertex3fv(&(LX2[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, 1.0f, 0.0f);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, 1.0f);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+
+      return OOZ_XOZ | OYO_XYO |
+             XOO_XYO | OOZ_OYZ |
+             XOO_XOZ | OYO_OYZ;
     }
-    if (LX3draw == 1)
+    case 1: // (0,0,1)
     {
-      glVertex3fv(&(LX3[0]));
-      glVertex3fv(&(LX3[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, 1.0f, 0.0f);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, -1.0f);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
+
+      return OOZ_XOZ | OYZ_XYZ |
+             OOZ_OYZ | XOZ_XYZ |
+             XOO_XOZ | OYO_OYZ;
     }
-    if (LY1draw == 1)
+    case 2: // (0,1,0)
     {
-      glVertex3fv(&(LY1[0]));
-      glVertex3fv(&(LY1[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, -1.0f, 0.0f);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, 1.0f);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
+
+      return OYO_XYO | OYZ_XYZ |
+             XOO_XYO | OOZ_OYZ |
+             XYO_XYZ | OYO_OYZ;
     }
-    if (LY2draw == 1)
+    case 3: // (0,1,1)
     {
-      glVertex3fv(&(LY2[0]));
-      glVertex3fv(&(LY2[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMax.y(), myMax.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, -1.0f, 0.0f);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, -1.0f);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
+
+      return OOZ_XOZ | OYZ_XYZ | OYO_XYO |
+             OOZ_OYZ | XOZ_XYZ |
+             OYO_OYZ | XYO_XYZ;
     }
-    if (LY3draw == 1)
+    case 4: // (1,0,0)
     {
-      glVertex3fv(&(LY3[0]));
-      glVertex3fv(&(LY3[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0, 1, 0);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, 1);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
+
+      return OOZ_XOZ | OYO_XYO |
+             XOO_XYO | XOZ_XYZ |
+             XOO_XOZ | XYO_XYZ;
     }
-    if (LZ1draw == 1)
+    case 5: // (1,0,1)
     {
-      glVertex3fv(&(LZ1[0]));
-      glVertex3fv(&(LZ1[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0, 1, 0);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, -1);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
+
+      return OOZ_XOZ | OYZ_XYZ |
+             XOO_XYO | XOZ_XYZ | OOZ_OYZ |
+             XOO_XOZ | XYO_XYZ;
     }
-    if (LZ2draw == 1)
+    case 6: // (1,1,0)
     {
-      glVertex3fv(&(LZ2[0]));
-      glVertex3fv(&(LZ2[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0, -1, 0);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, 1);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
+
+      return OYO_XYO | OYZ_XYZ |
+             XOO_XYO | XOZ_XYZ |
+             XOO_XOZ | XYO_XYZ | OYO_OYZ;
     }
-    if (LZ3draw == 1)
+    case 7: // (1,1,1)
+    default:
     {
-      glVertex3fv(&(LZ3[0]));
-      glVertex3fv(&(LZ3[3]));
+      theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMax.y(), myMax.z());
+      theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
+      theGridAxes.Axes[1] = OpenGl_Vec3 (0, -1, 0);
+      theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, -1);
+
+      theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
+      theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
+      theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
+
+      return OYO_XYO | OYZ_XYZ | OOZ_XOZ |
+             XOO_XYO | XOZ_XYZ | OOZ_OYZ |
+             XOO_XOZ | XYO_XYZ | OYO_OYZ;
     }
-    glEnd();
+  }
+}
 
-    /* Intermediate grid-lines */
-    /* X-Grid lines */
-    if (myNbX > 0)
+// =======================================================================
+// function : renderLine
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::renderLine (const OpenGl_PrimitiveArray&    theLine,
+                                            const Handle(OpenGl_Workspace)& theWorkspace,
+                                            const OpenGl_Mat4& theMat,
+                                            const Standard_ShortReal theXt,
+                                            const Standard_ShortReal theYt,
+                                            const Standard_ShortReal theZt) const
+{
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+  OpenGl_Mat4 aMat (theMat);
+  Graphic3d_TransformUtils::Translate (aMat, theXt, theYt, theZt);
+  aContext->WorldViewState.SetCurrent (aMat);
+  aContext->ApplyWorldViewMatrix();
+  theLine.Render (theWorkspace);
+}
+
+// =======================================================================
+// function : renderGridPlane
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::renderGridPlane (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                 const Standard_Integer& theIndex,
+                                                 const GridAxes& theGridAxes,
+                                                 OpenGl_Mat4& theMat) const
+{
+  const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
+  if (aCurAspect.TickmarksNumber() <= 0)
+  {
+    return;
+  }
+
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+
+  Standard_ShortReal aStep = theGridAxes.Axes[theIndex].GetData()[theIndex]
+                            * (myMax.GetData()[theIndex] - myMin.GetData()[theIndex]) / aCurAspect.TickmarksNumber();
+
+  // NOTE:
+  // Get two other axes directions and draw lines Axis.TickmarksNumber times.
+  // Combining together from three axes, these lines will make a grid.
+  for (Standard_Integer anIter = 1; anIter <= 2; ++anIter)
+  {
+    OpenGl_Mat4 aMat (theMat);
+    const Standard_Integer anIndex = (theIndex + anIter) % 3;
+    const Axis& anAxis = myAxes[anIndex];
+    OpenGl_Vec3 aStart (theGridAxes.Origin);
+    if (theGridAxes.Axes[anIndex].GetData()[anIndex] < 0.0)
     {
-      i = myDrawAxes ? 1 : 0;
-      step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
-      while (i < myNbX)
-      {
-        glBegin(GL_LINE_STRIP);
-        glVertex3f(LX1[0] + i * step, LX1[1], LX1[2]);
-        glVertex3f(LX2[0] + i * step, LX2[1], LX2[2]);
-        glVertex3f(LX3[0] + i * step, LX3[1], LX3[2]);
-        glEnd();
-        i++;
-      }
+      aStart.ChangeData()[anIndex] = myMin.GetData()[anIndex];
     }
-    /* Y-Grid lines */
-    if (myNbY > 0)
+
+    Graphic3d_TransformUtils::Translate (aMat, aStart.x(), aStart.y(), aStart.z());
+    aContext->WorldViewState.SetCurrent (aMat);
+    aContext->ApplyWorldViewMatrix();
+
+    const OpenGl_Vec3 aStepVec (myAxes[theIndex].Direction * aStep);
+    for (Standard_Integer anIt = myData.ToDrawAxes() ? 1 : 0; anIt < aCurAspect.TickmarksNumber(); ++anIt)
     {
-      i = myDrawAxes ? 1 : 0;
-      step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
-      while (i < myNbY)
-      {
-        glBegin(GL_LINE_STRIP);
-        glVertex3f(LY1[0], LY1[1] + i * step, LY1[2]);
-        glVertex3f(LY2[0], LY2[1] + i * step, LY2[2]);
-        glVertex3f(LY3[0], LY3[1] + i * step, LY3[2]);
-        glEnd();
-        i++;
-      }
+      Graphic3d_TransformUtils::Translate (aMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
+      aContext->WorldViewState.SetCurrent (aMat);
+      aContext->ApplyWorldViewMatrix();
+      anAxis.Line.Render (theWorkspace);
     }
-    /* Z-Grid lines */
-    if (myNbZ > 0)
+  }
+}
+
+// =======================================================================
+// function : renderAxis
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theWorkspace,
+                                            const Standard_Integer& theIndex,
+                                            const OpenGl_Mat4& theMat) const
+{
+  const Axis& anAxis = myAxes[theIndex];
+
+  theWorkspace->SetAspects (&anAxis.LineAspect);
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+
+  // Reset transformations
+  aContext->WorldViewState.SetCurrent (theMat);
+  aContext->ApplyWorldViewMatrix();
+
+  // Render arrow
+  OpenGl_Vec3 anArrowVec = myMin + anAxis.Direction * (myMax - myMin);
+
+  Graphic3d_TransformPers aTransMode (Graphic3d_TMF_ZoomPers, gp_Pnt (Standard_Real(anArrowVec.x()),
+                                                                      Standard_Real(anArrowVec.y()),
+                                                                      Standard_Real(anArrowVec.z())));
+  const OpenGl_Mat4& aProjection = aContext->ProjectionState.Current();
+  const OpenGl_Mat4& aWorldView  = aContext->WorldViewState.Current();
+  const Standard_Integer aWidth  = theWorkspace->Width();
+  const Standard_Integer aHeight = theWorkspace->Height();
+
+  // Take into account Transform Persistence
+  aContext->ModelWorldState.SetCurrent (aTransMode.Compute (theWorkspace->View()->Camera(), aProjection, aWorldView, aWidth, aHeight));
+  aContext->ApplyModelViewMatrix();
+
+  anAxis.Arrow.Render (theWorkspace);
+
+  // Get current Model-View and Projection states
+  OpenGl_Mat4 aModelMat;
+  OpenGl_Mat4 aProjMat;
+  aModelMat.Convert (aContext->WorldViewState.Current() * aContext->ModelWorldState.Current());
+  aProjMat .Convert (aContext->ProjectionState.Current());
+
+  // Get the window's (fixed) coordinates for before matrices modifications
+  OpenGl_Vec3 aEndPoint = -anAxis.Direction * myData.ArrowsLength();
+  OpenGl_Vec3 aWinPoint;
+  Graphic3d_TransformUtils::Project<Standard_ShortReal> (aEndPoint.x(), aEndPoint.y(), aEndPoint.z(),
+                                                         aModelMat, aProjMat, aContext->Viewport(),
+                                                         aWinPoint.x(), aWinPoint.y(), aWinPoint.z());
+
+  aContext->ModelWorldState.SetIdentity();
+  aModelMat.Convert (aContext->WorldViewState.Current());
+  aProjMat .Convert (aContext->ProjectionState.Current());
+
+  // Get start point of zoom persistent arrow
+  OpenGl_Vec3 anArrowStart;
+  Graphic3d_TransformUtils::UnProject<Standard_ShortReal> (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(),
+                                                           aModelMat, aProjMat, aContext->Viewport(),
+                                                           anArrowStart.x(), anArrowStart.y(), anArrowStart.z());
+  // Render axis line
+  aModelMat = theMat;
+  Graphic3d_TransformUtils::Translate (aModelMat, myMin.x(), myMin.y(), myMin.z());
+
+  Standard_ShortReal aScaleFactor = ( (anArrowStart - myMin)*anAxis.Direction ).Modulus()
+                                     / (anAxis.Direction * (myMax - myMin) ).Modulus();
+  OpenGl_Vec3 aScaleAxes = anAxis.Direction * aScaleFactor;
+  Graphic3d_TransformUtils::Scale (aModelMat, aScaleAxes.x(), aScaleAxes.y(), aScaleAxes.z());
+
+  aContext->WorldViewState.SetCurrent (aModelMat);
+  aContext->ApplyWorldViewMatrix();
+  anAxis.Line.Render (theWorkspace);
+}
+
+// =======================================================================
+// function : renderTickmarkTextLabels
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::renderTickmarkLabels (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                      const OpenGl_Mat4& theMat,
+                                                      const Standard_Integer theIndex,
+                                                      const GridAxes& theGridAxes,
+                                                      const Standard_ShortReal theDpix) const
+{
+  const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
+  if (!aCurAspect.ToDrawName() && !aCurAspect.ToDrawValues())
+  {
+    return;
+  }
+
+  Standard_Character aTextValue[128];
+  const Axis& anAxis = myAxes[theIndex];
+  const OpenGl_Vec3 aSizeVec (myMax - myMin);
+  Standard_ShortReal aStep = theGridAxes.Axes[theIndex].GetData()[theIndex]
+                       * (myMax.GetData()[theIndex] - myMin.GetData()[theIndex]) / aCurAspect.TickmarksNumber();
+
+  OpenGl_Vec3 aDir = (theGridAxes.Ticks[theIndex] - theGridAxes.Origin).Normalized();
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+
+  if (aCurAspect.ToDrawTickmarks() && aCurAspect.TickmarksNumber() > 0)
+  {
+    theWorkspace->SetAspects (&myGridLineAspect);
+
+    OpenGl_Mat4 aModelMat (theMat);
+
+    anAxis.InitTickmark (aContext, aDir * (Standard_ShortReal) aCurAspect.TickmarksLength() * theDpix);
+    Graphic3d_TransformUtils::Translate (aModelMat, theGridAxes.Ticks[theIndex].x(),
+                                                    theGridAxes.Ticks[theIndex].y(),
+                                                    theGridAxes.Ticks[theIndex].z());
+    aContext->WorldViewState.SetCurrent (aModelMat);
+    aContext->ApplyWorldViewMatrix();
+    OpenGl_Vec3 aStepVec = anAxis.Direction * aStep;
+    for (Standard_Integer anIter = 0; anIter <= aCurAspect.TickmarksNumber(); ++anIter)
     {
-      i = myDrawAxes ? 1 : 0;
-      step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
-      while (i < myNbZ)
-      {
-        glBegin(GL_LINE_STRIP);
-        glVertex3f(LZ1[0], LZ1[1], LZ1[2] + i * step);
-        glVertex3f(LZ2[0], LZ2[1], LZ2[2] + i * step);
-        glVertex3f(LZ3[0], LZ3[1], LZ3[2] + i * step);
-        glEnd();
-        i++;
-      }
+      anAxis.Tickmark.Render (theWorkspace);
+      Graphic3d_TransformUtils::Translate (aModelMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
+      aContext->WorldViewState.SetCurrent (aModelMat);
+      aContext->ApplyWorldViewMatrix();
     }
   }
 
-  /* Axes (arrows) */
-  if (myDrawAxes)
+  // Restore matrix
+  aContext->WorldViewState.SetCurrent (theMat);
+  aContext->ApplyWorldViewMatrix();
+
+  if (aCurAspect.ToDrawName())
   {
-    /* X-axis */
-    glColor3fv(myXColor);
-    drawArrow(xmin, ymin, zmin, xmax, ymin, zmin, normal[0], normal[1], normal[2]);
+    Standard_Real anOffset = aCurAspect.NameOffset() + aCurAspect.TickmarksLength();
 
-    /* Y-axis */
-    glColor3fv(myYColor);
-    drawArrow(xmin, ymin, zmin, xmin, ymax, zmin, normal[0], normal[1], normal[2]);
+    OpenGl_Vec3 aMiddle (theGridAxes.Ticks[theIndex] + aSizeVec * theGridAxes.Axes[theIndex] * 0.5f + aDir * (Standard_ShortReal)(theDpix * anOffset));
 
-    /* Z-axis */
-    glColor3fv(myZColor);
-    drawArrow(xmin, ymin, zmin, xmin, ymin, zmax, normal[0], normal[1], normal[2]);
+    myAspectLabels.Aspect()->SetColor (anAxis.NameColor);
+    theWorkspace->SetAspects (&myAspectLabels);
+    anAxis.Label.SetPosition (aMiddle);
+    anAxis.Label.Render (theWorkspace);
   }
 
-  /* Names of axes & values */
-  char textValue[128];
-  wchar_t wtextValue[128];
-
-  if (myDrawXName || myDrawXValues)
+  if (aCurAspect.ToDrawValues() && aCurAspect.TickmarksNumber() > 0)
   {
-    /* Middle point of the first X-axis */
-    m1[0] = 0.5f * (LX1[0] + LX1[3]);
-    m1[1] = 0.5f * (LX1[1] + LX1[4]);
-    m1[2] = 0.5f * (LX1[2] + LX1[5]);
-
-    /* Middle point of the second X-axis */
-    m2[0] = 0.5f * (LX2[0] + LX2[3]);
-    m2[1] = 0.5f * (LX2[1] + LX2[4]);
-    m2[2] = 0.5f * (LX2[2] + LX2[5]);
-
-    /* Apply offset to m1 */
-    dy = m1[1] - m2[1];
-    if (fabsf(dy) > 1.e-7f)
-    {
-      dy = (dy > 0.0f)? 1.0f : -1.0f;
-    }
-    dz = m1[2] - m2[2];
-    if (fabsf(dz) > 1.e-7f)
-    {
-      dz = (dz > 0.0f)? 1.0f : -1.0f;
-    }
-    m2[1] = dpix * dy;
-    m2[2] = dpix * dz;
+    myAspectValues.Aspect()->SetColor (anAxis.LineAspect.Aspect()->Color());
+    theWorkspace->SetAspects (&myAspectValues);
+    Standard_Real anOffset = aCurAspect.ValuesOffset() + aCurAspect.TickmarksLength();
 
-    /* Name of X-axis */
-    if (myDrawXName)
+    for (Standard_Integer anIt = 0; anIt <= aCurAspect.TickmarksNumber(); ++anIt)
     {
-      glColor3fv(myXNameColor);
-      offset = myXAxisOffset + myXTickmarkLength;
-      drawText(AWorkspace, myXName, myFontOfNames, myStyleOfNames, mySizeOfNames, 
-               m1[0], m1[1] + offset * m2[1], m1[2] + offset * m2[2]);
+      sprintf (aTextValue, "%g", theGridAxes.Ticks[theIndex].GetData()[theIndex] + anIt * aStep);
+      OpenGl_Vec3 aPos (theGridAxes.Ticks[theIndex] + anAxis.Direction* (Standard_ShortReal) (anIt * aStep) + aDir * (Standard_ShortReal) (theDpix * anOffset));
+      myLabelValues.Init (theWorkspace->GetGlContext(), aTextValue, aPos);
+      myLabelValues.Render (theWorkspace);
     }
+  }
+}
 
-    /* X-values */
-    if (myDrawXValues && myNbX > 0)
-    {
-      glColor3fv(myXColor);
-
-      i = 0;
-      step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
-      offset = myXOffset + myXTickmarkLength;
-      while (i <= myNbX)
-      {
-        sprintf(textValue, "%g", LX1[0] + i * step);
-        j = 0; while (wtextValue[j] = textValue[j]) j++;
-        drawText(AWorkspace, wtextValue, myFontOfValues, myStyleOfValues, mySizeOfValues, 
-                 LX1[0] + i * step, m1[1] + offset * m2[1], m1[2] + offset * m2[2]);
-        i++;
-      }
-    }
+// =======================================================================
+// function : Render
+// purpose  : call_graduatedtrihedron_redraw
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+  if (!myIsInitialized)
+  {
+    initGlResources (theWorkspace->GetGlContext());
+    myIsInitialized = Standard_True;
+  }
+
+  // Update boundary box
+  OpenGl_Vec3 anOldMin = myMin;
+  OpenGl_Vec3 anOldMax = myMax;
 
-    /* X-tickmark */
-    if (myDrawXTickmarks && myNbX > 0)
+  if (myData.CubicAxesCallback)
+  {
+    myData.CubicAxesCallback (myData.PtrView);
+    if (!myAxes[0].Line.IsInitialized()
+     || !myAxes[1].Line.IsInitialized()
+     || !myAxes[2].Line.IsInitialized()
+     ||  OpenGl_Vec3 (anOldMin - myMin).Modulus() > Precision::Confusion()
+     ||  OpenGl_Vec3 (anOldMax - myMax).Modulus() > Precision::Confusion())
     {
-      glColor3fv(myGridColor);
-
-      i = 0;
-      step = fabsf(LX1[3] - LX1[0]) / (float) myNbX;
-      while (i <= myNbX)
-      {
-        glBegin(GL_LINES);
-        glVertex3f(LX1[0] + i * step, m1[1],                             m1[2]);
-        glVertex3f(LX1[0] + i * step, m1[1] + myXTickmarkLength * m2[1], m1[2] + myXTickmarkLength * m2[2]);
-        glEnd();
-        i++;
-      }
+      myAxes[0].InitLine (aContext, OpenGl_Vec3 (myMax.x() - myMin.x(), 0.0f, 0.0f));
+      myAxes[1].InitLine (aContext, OpenGl_Vec3 (0.0f, myMax.y() - myMin.y(), 0.0f));
+      myAxes[2].InitLine (aContext, OpenGl_Vec3 (0.0f, 0.0f, myMax.z() - myMin.z()));
     }
   }
 
-  if (myDrawYName || myDrawYValues)
+  // Find the farest point of bounding box
+
+  // Get normal of the view out of user and distance corresponding to 1 pixel
+  OpenGl_Vec3 aNormal;
+  Standard_ShortReal aDpix = getNormal (aContext, aNormal);
+  aNormal.Normalize();
+
+  // Get central point of bounding box
+  OpenGl_Vec3 aCenter;
+  aCenter = (myMin + myMax) * 0.5f;
+
+  // Check distance to corners of bounding box along the normal
+  Standard_ShortReal aCorners[8];
+  aCorners[0] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMin.y(), myMin.z());
+  aCorners[1] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMin.y(), myMax.z());
+  aCorners[2] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMax.y(), myMin.z());
+  aCorners[3] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMax.y(), myMax.z());
+  aCorners[4] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMin.y(), myMin.z());
+  aCorners[5] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMin.y(), myMax.z());
+  aCorners[6] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMax.y(), myMin.z());
+  aCorners[7] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMax.y(), myMax.z());
+
+  // NOTE:
+  // (0, 0, 1), (0, 1, 0) and (0, 0, 1) directions from (myMin.x(), Ymin, Zmin) point
+  // are reserved for trihedron axes.
+  // So for the grid here are 9 edges of cube,
+  // and, depending on the farest point, 2 or 3 of them may not be drawn
+  // if they overlap displayed model.
+  
+  // Write an axes state what axes of bounding box are to be drawn
+  GridAxes aGridAxes;
+  Standard_ExtCharacter anAxesState = getGridAxes (aCorners, aGridAxes);
+
+  // Remember current aspects
+  const OpenGl_Aspects* anOldAspectLine = theWorkspace->Aspects();
+
+  OpenGl_Mat4 aModelMatrix;
+  aModelMatrix.Convert (aContext->WorldViewState.Current());
+
+  // Remember model-view matrix
+  aContext->WorldViewState.Push();
+  aContext->WorldViewState.SetCurrent (aModelMatrix);
+  aContext->ApplyWorldViewMatrix();
+
+  if (myData.ToDrawGrid())
   {
-    /* Middle point of the first Y-axis */
-    m1[0] = 0.5f * (LY1[0] + LY1[3]);
-    m1[1] = 0.5f * (LY1[1] + LY1[4]);
-    m1[2] = 0.5f * (LY1[2] + LY1[5]);
-
-    /* Middle point of the second Y-axis */
-    m2[0] = 0.5f * (LY2[0] + LY2[3]);
-    m2[1] = 0.5f * (LY2[1] + LY2[4]);
-    m2[2] = 0.5f * (LY2[2] + LY2[5]);
-
-    /* Apply offset to m1 */
-    dx = m1[0] - m2[0];
-    if (fabsf(dx) > 1.e-7f)
+    theWorkspace->SetAspects (&myGridLineAspect);
+
+    // render grid edges
+    if (anAxesState & XOO_XYO)
     {
-      dx = (dx > 0.0f)? 1.0f : -1.0f;
+      renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
     }
-    dz = m1[2] - m2[2];
-    if (fabsf(dz) > 1.e-7f)
+
+    if (anAxesState & XOO_XOZ)
     {
-      dz = (dz > 0.0f)? 1.0f : -1.0f;
+      renderLine (myAxes[2].Line,theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
     }
 
-    m2[0] = dpix * dx;
-    m2[2] = dpix * dz;
-
-    /* Name of Y-axis */
-    if (myDrawYName)
+    if (anAxesState & OYO_OYZ)
     {
-      glColor3fv(myYNameColor);
-      offset = myYAxisOffset + myYTickmarkLength;
-      drawText(AWorkspace, myYName, myFontOfNames, myStyleOfNames, mySizeOfNames, 
-               m1[0] + offset * m2[0], m1[1], m1[2] + offset * m2[2]);
+      renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
     }
 
-    /* Y-values */
-    if (myDrawYValues && myNbY > 0)
+    if (anAxesState & OYO_XYO)
     {
-      glColor3fv(myYColor);
-
-      i = 0;
-      step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
-      offset = myYOffset + myYTickmarkLength;
-      while (i <= myNbY)
-      {
-        sprintf(textValue, "%g", LY1[1] + i * step);
-        j = 0; while (wtextValue[j] = textValue[j]) j++;
-        drawText(AWorkspace, wtextValue, myFontOfValues, myStyleOfValues, mySizeOfValues, 
-                 m1[0] + offset * m2[0], LY1[1] + i * step, m1[2] + offset * m2[2]);
-        i++;
-      }
+      renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
     }
 
-    /* Y-tickmark */
-    if (myDrawYTickmarks && myNbY > 0)
+    if (anAxesState & OOZ_XOZ)
     {
-      glColor3fv(myGridColor);
-
-      i = 0;
-      step = fabsf(LY1[4] - LY1[1]) / (float) myNbY;
-      while (i <= myNbY)
-      {
-        glBegin(GL_LINES);
-        glVertex3f(m1[0],                             LY1[1] + i * step, m1[2]);
-        glVertex3f(m1[0] + myYTickmarkLength * m2[0], LY1[1] + i * step, m1[2] + myYTickmarkLength * m2[2]);
-        glEnd();
-        i++;
-      }
+      renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.z(), myMin.y(), myMax.z());
     }
-  }
 
-  if (myDrawZName || myDrawZValues)
-  {
-    /* Middle point of the first Z-axis */
-    m1[0] = 0.5f * (LZ1[0] + LZ1[3]);
-    m1[1] = 0.5f * (LZ1[1] + LZ1[4]);
-    m1[2] = 0.5f * (LZ1[2] + LZ1[5]);
-
-    /* Middle point of the second Z-axis */
-    m2[0] = 0.5f * (LZ2[0] + LZ2[3]);
-    m2[1] = 0.5f * (LZ2[1] + LZ2[4]);
-    m2[2] = 0.5f * (LZ2[2] + LZ2[5]);
-
-    /* Apply offset to m1 */
-    dx = m1[0] - m2[0];
-    if (fabsf(dx) > 1.e-7f)
+    if (anAxesState & OOZ_OYZ)
     {
-      dx = (dx > 0.0f)? 1.0f : -1.0f;
+      renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMin.x(), myMin.y(), myMax.z());
     }
-    dy = m1[1] - m2[1];
-    if (fabsf(dy) > 1.e-7f)
+
+    if (anAxesState & OYZ_XYZ)
     {
-      dy = (dy > 0.0f)? 1.0f : -1.0f;
+      renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMax.z());
     }
 
-    m2[0] = dpix * dx;
-    m2[1] = dpix * dy;
+    if (anAxesState & XOZ_XYZ)
+    {
+      renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMax.z());
+    }
 
-    /* Name of Z-axis */
-    if (myDrawZName)
+    if (anAxesState & XYO_XYZ)
     {
-      glColor3fv(myZNameColor);
-      offset = myZAxisOffset + myZTickmarkLength;
-      drawText(AWorkspace, myZName, myFontOfNames, myStyleOfNames, mySizeOfNames, 
-               m1[0] + offset * m2[0], m1[1] + offset * m2[1], m1[2]);
+      renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMax.x(), myMax.y(), myMin.z());
     }
 
-    /* Z-values */
-    if (myDrawZValues && myNbZ > 0)
+    for (Standard_Integer anIter = 0 ; anIter < 3; ++anIter)
     {
-      glColor3fv(myZColor);
-
-      i = 0;
-      step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
-      offset = myZOffset + myZTickmarkLength;
-      while (i <= myNbZ)
-      {
-        sprintf(textValue, "%g", LZ1[2] + i * step);
-        j = 0; while (wtextValue[j] = textValue[j]) j++;
-        drawText(AWorkspace, wtextValue, myFontOfValues, myStyleOfValues, mySizeOfValues, 
-                 m1[0] + offset * m2[0], m1[1] + offset * m2[1], LZ1[2] + i * step);
-        i++;
-      }
+      renderGridPlane (theWorkspace, anIter, aGridAxes, aModelMatrix);
     }
+  }
 
-    /* Z-tickmark */
-    if (myDrawZTickmarks && myNbZ > 0)
+  // Axes (arrows)
+  if (myData.ToDrawAxes())
+  {
+    for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
     {
-      glColor3fv(myGridColor);
-
-      i = 0;
-      step = fabsf(LZ1[5] - LZ1[2]) / (float) myNbZ;
-      while (i <= myNbZ)
-      {
-        glBegin(GL_LINES);
-        glVertex3f(m1[0],                             m1[1],                             LZ1[2] + i * step);
-        glVertex3f(m1[0] + myZTickmarkLength * m2[0], m1[1] + myZTickmarkLength * m2[1], LZ1[2] + i * step);
-        glEnd();
-        i++;
-      }
+      renderAxis (theWorkspace, anIter, aModelMatrix);
     }
   }
 
-  /* Activate the lighting if it was turned off by this method call */
-  if (light)
-    glEnable(GL_LIGHTING);
+  // Names of axes & values
+  for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
+  {
+    // Restore current matrix
+    aContext->WorldViewState.SetCurrent (aModelMatrix);
+    aContext->ApplyWorldViewMatrix();
+    renderTickmarkLabels (theWorkspace, aModelMatrix, anIter, aGridAxes, aDpix);
+  }
+
+  theWorkspace->SetAspects (anOldAspectLine);
+
+  aContext->WorldViewState.Pop();
+  aContext->ApplyWorldViewMatrix();
+}
+
+// =======================================================================
+// method  : SetMinMax
+// purpose :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::SetMinMax (const OpenGl_Vec3& theMin, const OpenGl_Vec3& theMax)
+{
+  myMin = theMin;
+  myMax = theMax;
+}
+
+// =======================================================================
+// method  : OpenGl_GraduatedTrihedron::Axis constructor
+// purpose :
+// =======================================================================
+OpenGl_GraduatedTrihedron::Axis::Axis (const Graphic3d_AxisAspect& theAspect,
+                                       const OpenGl_Vec3&          theDirection)
+: Direction (theDirection),
+  Label     (NCollection_String ((Standard_Utf16Char* )theAspect.Name().ToExtString()).ToCString(), theDirection, THE_LABEL_PARAMS),
+  Tickmark  (NULL),
+  Line      (NULL),
+  Arrow     (NULL)
+{
+  NameColor = theAspect.NameColor();
+  LineAspect.Aspect()->SetColor (theAspect.Color());
+}
+
+// =======================================================================
+// method  : OpenGl_GraduatedTrihedron::Axis::~Axis
+// purpose :
+// =======================================================================
+OpenGl_GraduatedTrihedron::Axis::~Axis()
+{
+  //
+}
+
+// =======================================================================
+// method  : OpenGl_GraduatedTrihedron::Axis operator=
+// purpose :
+// =======================================================================
+OpenGl_GraduatedTrihedron::Axis& OpenGl_GraduatedTrihedron::Axis::operator= (const Axis& theOther)
+{
+  Direction  = theOther.Direction;
+  NameColor  = theOther.NameColor;
+  LineAspect = theOther.LineAspect;
+  Label      = theOther.Label;
+
+  Line    .InitBuffers (NULL, Graphic3d_TOPA_SEGMENTS,  theOther.Line.Indices(),     theOther.Line.Attributes(),     theOther.Line.Bounds());
+  Tickmark.InitBuffers (NULL, Graphic3d_TOPA_SEGMENTS,  theOther.Tickmark.Indices(), theOther.Tickmark.Attributes(), theOther.Tickmark.Bounds());
+  Arrow   .InitBuffers (NULL, Graphic3d_TOPA_POLYLINES, theOther.Arrow.Indices(),    theOther.Arrow.Attributes(),    theOther.Arrow.Bounds());
+  return *this;
+}
+
+// =======================================================================
+// method  : InitArrow
+// purpose :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Axis::InitArrow (const Handle(OpenGl_Context)& theContext,
+                                                 const Standard_ShortReal theLength,
+                                                 const OpenGl_Vec3& theNormal) const
+{
+  // Draw from the end point of the aris
+  OpenGl_Vec3 aLengthVec = -Direction * theLength;
+
+  // Radial direction to the arrow
+  OpenGl_Vec3 aRadial = OpenGl_Vec3::Cross (this->Direction, theNormal);
+  if (aRadial.Modulus() < (Standard_ShortReal) Precision::Confusion())
+  {
+    return;
+  }
+  aRadial = aRadial.Normalized() * theLength * 0.2f;
+
+  // Initialize arrow primitive array
+  // Make loop from polyline
+  const OpenGl_Vec3 aPoint1 = aRadial + aLengthVec;
+  const OpenGl_Vec3 aPoint2 (0.0f, 0.0f, 0.0f);
+  const OpenGl_Vec3 aPoint3 = -aRadial + aLengthVec;
+
+  Handle(Graphic3d_ArrayOfPolylines) anArray = new Graphic3d_ArrayOfPolylines (4);
+  anArray->AddVertex (aPoint1);
+  anArray->AddVertex (aPoint2);
+  anArray->AddVertex (aPoint3);
+  anArray->AddVertex (aPoint1);
+
+  Arrow.InitBuffers (theContext, Graphic3d_TOPA_POLYLINES,
+                     anArray->Indices(), anArray->Attributes(), anArray->Bounds());
+}
+
+// =======================================================================
+// function : InitTickmark
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Axis::InitTickmark (const Handle(OpenGl_Context)& theContext,
+                                                    const OpenGl_Vec3& theDir) const
+{
+
+  Handle(Graphic3d_ArrayOfSegments) anArray = new Graphic3d_ArrayOfSegments (2);
+  anArray->AddVertex (0.0f, 0.0f, 0.0f);
+  anArray->AddVertex (theDir);
+  Tickmark.InitBuffers (theContext, Graphic3d_TOPA_SEGMENTS,
+                        anArray->Indices(), anArray->Attributes(), anArray->Bounds());
+
+}
+
+// =======================================================================
+// function : InitLine
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Axis::InitLine (const Handle(OpenGl_Context)& theContext,
+                                                const OpenGl_Vec3& theDir) const
+{
+
+  Handle(Graphic3d_ArrayOfSegments) anArray = new Graphic3d_ArrayOfSegments (2);
+  anArray->AddVertex (0.0f, 0.0f, 0.0f);
+  anArray->AddVertex (theDir);
 
-  AWorkspace->SetAspectLine(oldAspectLine);
+  Line.InitBuffers (theContext, Graphic3d_TOPA_SEGMENTS,
+                    anArray->Indices(), anArray->Attributes(), anArray->Bounds());
 }
 
-//call_graduatedtrihedron_minmaxvalues
-void OpenGl_GraduatedTrihedron::SetMinMax (const Standard_ShortReal xMin, const Standard_ShortReal yMin, const Standard_ShortReal zMin,
-                                          const Standard_ShortReal xMax, const Standard_ShortReal yMax, const Standard_ShortReal zMax)
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_GraduatedTrihedron::Axis::Release (OpenGl_Context* theCtx)
 {
-  xmin = xMin;
-  ymin = yMin;
-  zmin = zMin;
-  xmax = xMax;
-  ymax = yMax;
-  zmax = zMax;
+  Label   .Release (theCtx);
+  Tickmark.Release (theCtx);
+  Line    .Release (theCtx);
+  Arrow   .Release (theCtx);
 }