From 5f88a6c5f8cbabd9b89dd1b59c17c719300e5a89 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 3 Aug 2012 08:29:16 +0000
Subject: [PATCH] automatically adjust number of axis tics

---
 Common/Context.h         |  4 +-
 Common/Options.cpp       | 12 ++---
 Graphics/drawAxes.cpp    | 94 ++++++++++++++++++----------------------
 Graphics/drawContext.h   |  4 +-
 Graphics/drawGraph2d.cpp |  4 +-
 Post/PViewOptions.h      |  3 +-
 6 files changed, 56 insertions(+), 65 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index b7b176c0cf..a27373bf6a 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -149,8 +149,8 @@ class CTX {
   // small axes options
   int smallAxes, smallAxesSize, smallAxesPos[2];
   // large axes options
-  int axes, axesAutoPosition, axesTics[3], axesMikado, axesForceValue;
-  double axesPosition[6], axesValue[6];
+  int axes, axesAutoPosition, axesMikado, axesForceValue;
+  double axesPosition[6], axesValue[6], axesTics[3];
   std::string axesLabel[3], axesFormat[3];
   // simple dynamic lock (should be a mutex)
   int lock;
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 48f617ed24..09991224f1 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -2575,7 +2575,7 @@ double opt_general_axes_auto_position(OPT_ARGS_NUM)
 double opt_general_axes_tics0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX::instance()->axesTics[0] = (int)val;
+    CTX::instance()->axesTics[0] = val;
 #if defined(HAVE_FLTK)
   if(FlGui::available() && (action & GMSH_GUI))
     FlGui::instance()->options->general.value[17]->value
@@ -2587,7 +2587,7 @@ double opt_general_axes_tics0(OPT_ARGS_NUM)
 double opt_general_axes_tics1(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX::instance()->axesTics[1] = (int)val;
+    CTX::instance()->axesTics[1] = val;
 #if defined(HAVE_FLTK)
   if(FlGui::available() && (action & GMSH_GUI))
     FlGui::instance()->options->general.value[18]->value
@@ -2599,7 +2599,7 @@ double opt_general_axes_tics1(OPT_ARGS_NUM)
 double opt_general_axes_tics2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX::instance()->axesTics[2] = (int)val;
+    CTX::instance()->axesTics[2] = val;
 #if defined(HAVE_FLTK)
   if(FlGui::available() && (action & GMSH_GUI))
     FlGui::instance()->options->general.value[19]->value
@@ -6853,7 +6853,7 @@ double opt_view_axes_tics0(OPT_ARGS_NUM)
 #if defined(HAVE_POST)
   GET_VIEW(0.);
   if(action & GMSH_SET) {
-    opt->axesTics[0] = (int)val;
+    opt->axesTics[0] = val;
   }
 #if defined(HAVE_FLTK)
   if(_gui_action_valid(action, num)) {
@@ -6871,7 +6871,7 @@ double opt_view_axes_tics1(OPT_ARGS_NUM)
 #if defined(HAVE_POST)
   GET_VIEW(0.);
   if(action & GMSH_SET) {
-    opt->axesTics[1] = (int)val;
+    opt->axesTics[1] = val;
   }
 #if defined(HAVE_FLTK)
   if(_gui_action_valid(action, num)) {
@@ -6889,7 +6889,7 @@ double opt_view_axes_tics2(OPT_ARGS_NUM)
 #if defined(HAVE_POST)
   GET_VIEW(0.);
   if(action & GMSH_SET) {
-    opt->axesTics[2] = (int)val;
+    opt->axesTics[2] = val;
   }
 #if defined(HAVE_FLTK)
   if(_gui_action_valid(action, num)) {
diff --git a/Graphics/drawAxes.cpp b/Graphics/drawAxes.cpp
index 59a7b63ea6..897b8d2b82 100644
--- a/Graphics/drawAxes.cpp
+++ b/Graphics/drawAxes.cpp
@@ -14,7 +14,9 @@
 #include "Numeric.h"
 #include "gl2ps.h"
 
-static int drawTics(drawContext *ctx, int comp, int n, std::string &format,
+#define SQU(a)      ((a)*(a))
+
+static int drawTics(drawContext *ctx, int comp, double n, std::string &format,
                     std::string &label, double p1[3], double p2[3],
                     double perp[3], int mikado, double pixelfact,
                     double value_p1[3], double value_p2[3])
@@ -26,18 +28,18 @@ static int drawTics(drawContext *ctx, int comp, int n, std::string &format,
   double value_t[3] = {value_p2[0] - value_p1[0], value_p2[1] - value_p1[1],
                        value_p2[2] - value_p1[2]};
   double value_l = norme(value_t);
-  double w = 10 * pixelfact; // big tics 10 pixels
-  double w2 = 5 * pixelfact; // small tics 5 pixels
+  double w = 10 * pixelfact; // tic marks are 10 pixels long
+  double w2 = w * 1.3; // distance to labels
 
-  glRasterPos3d(p2[0] + t[0] * w * 1.4,
-                p2[1] + t[1] * w * 1.4,
-                p2[2] + t[2] * w * 1.4);
+  // draw label at the end of the axis
+  glRasterPos3d(p2[0] + t[0] * w2, p2[1] + t[1] * w2, p2[2] + t[2] * w2);
   ctx->drawString(label);
 
+  // return number of tics in special cases
   if(n < 2) return 0;
-
   if(format.empty()) return n;
 
+  // select perp direction automatically if it is not provided
   double lp = norme(perp);
   if(!lp){
     switch(comp){
@@ -48,22 +50,28 @@ static int drawTics(drawContext *ctx, int comp, int n, std::string &format,
     }
   }
 
-  double tmp = 2. * CTX::instance()->glFontSize * pixelfact;
-  if(n * tmp > l) n = 3;
-  if(n * tmp > l) n = 2;
-
+  // reduce number of tics depending on font size and length of axis on screen
+  drawContext::global()->setFont(CTX::instance()->glFontEnum,
+                                 CTX::instance()->glFontSize);
+  char tmp[256];
+  sprintf(tmp, format.c_str(), -M_PI * 1.e4);
+  double win1[3], win2[3];
+  ctx->world2Viewport(p1, win1);
+  ctx->world2Viewport(p2, win2);
+  double winl = sqrt(SQU(win2[0] - win1[0]) + SQU(win2[1] - win1[1]));
+  double strl = drawContext::global()->getStringWidth(tmp);
+  if((n - 1) * strl > winl) n = (int)(winl / strl) + 1;
+  if(n <= 1) n = 2;
+
+  // draw n tics
   double step = l / (double)(n - 1);
   double value_step = value_l / (double)(n - 1);
 
   for(int i = 0; i < n; i++){
     double d = i * step;
     double p[3] = {p1[0] + t[0] * d, p1[1] + t[1] * d, p1[2] + t[2] * d};
-    double q[3] = {p[0] + perp[0] * w,
-                   p[1] + perp[1] * w,
-                   p[2] + perp[2] * w};
-    double r[3] = {p[0] + perp[0] * w * 1.4,
-                   p[1] + perp[1] * w * 1.4,
-                   p[2] + perp[2] * w * 1.4 };
+    double q[3] = {p[0] + perp[0] * w, p[1] + perp[1] * w, p[2] + perp[2] * w};
+    double r[3] = {p[0] + perp[0] * w2, p[1] + perp[1] * w2, p[2] + perp[2] * w2};
 
     double value_d = i * value_step;
     double value_p[3] = {value_p1[0] + value_t[0] * value_d,
@@ -75,43 +83,25 @@ static int drawTics(drawContext *ctx, int comp, int n, std::string &format,
     glVertex3d(q[0], q[1], q[2]);
     glEnd();
 
-    if(i < n-1 && !mikado){
-      for(int j = 1; j < 10; j++){
-        double dd = d + j * step/10.;
-        double pp[3] = {p1[0] + t[0] * dd,
-                        p1[1] + t[1] * dd,
-                        p1[2] + t[2] * dd};
-        double qq[3] = {pp[0] + perp[0] * w2,
-                        pp[1] + perp[1] * w2,
-                        pp[2] + perp[2] * w2};
-        glBegin(GL_LINES);
-        glVertex3d(pp[0], pp[1], pp[2]);
-        glVertex3d(qq[0], qq[1], qq[2]);
-        glEnd();
-      }
-    }
-
-    char str[256];
-    if(comp < 0) // display the length (ruler)
-      sprintf(str, format.c_str(), value_d);
-    else // display the coordinate
-      sprintf(str, format.c_str(), value_p[comp]);
+    // draw tic labels
+    if(comp < 0) // display the length value (ruler-mode, starting at 0)
+      sprintf(tmp, format.c_str(), value_d);
+    else // display the coordinate value
+      sprintf(tmp, format.c_str(), value_p[comp]);
     double winp[3], winr[3];
     ctx->world2Viewport(p, winp);
     ctx->world2Viewport(r, winr);
-    drawContext::global()->setFont(CTX::instance()->glFontEnum,
-                                   CTX::instance()->glFontSize);
     if(fabs(winr[0] - winp[0]) < 2.) // center align
-      winr[0] -= drawContext::global()->getStringWidth(str) / 2.;
+      winr[0] -= drawContext::global()->getStringWidth(tmp) / 2.;
     else if(winr[0] < winp[0]) // right align
-      winr[0] -= drawContext::global()->getStringWidth(str);
+      winr[0] -= drawContext::global()->getStringWidth(tmp);
     if(fabs(winr[1] - winp[1]) < 2.) // center align
       winr[1] -= drawContext::global()->getStringHeight() / 3.;
     else if(winr[1] < winp[1]) // top align
       winr[1] -= drawContext::global()->getStringHeight();
     ctx->viewport2World(winr, r);
     glRasterPos3d(r[0], r[1], r[2]);
-    ctx->drawString(str);
+    ctx->drawString(tmp);
   }
 
   return n;
@@ -155,17 +145,17 @@ static void drawGridStipple(int n1, int n2, double p1[3], double p2[3], double p
 
 void drawContext::drawAxis(double xmin, double ymin, double zmin,
                            double xmax, double ymax, double zmax,
-                           int nticks, int mikado)
+                           int ntics, int mikado)
 {
   if(mikado){
-    nticks = (nticks - 1) * mikado;
-    if(nticks < 1) nticks = 1;
-    double dd[3] = {(xmax - xmin) / nticks,
-                    (ymax - ymin) / nticks,
-                    (zmax - zmin) / nticks};
+    ntics = (ntics - 1) * mikado;
+    if(ntics < 1) ntics = 1;
+    double dd[3] = {(xmax - xmin) / ntics,
+                    (ymax - ymin) / ntics,
+                    (zmax - zmin) / ntics};
     double axe_color[4];
     glGetDoublev(GL_CURRENT_COLOR, axe_color);
-    for(int i = 1; i <= nticks; i++){
+    for(int i = 1; i <= ntics; i++){
       if(i % 2) glColor4dv(axe_color);
       else glColor3f(1, 1, 1);
       double cx[2] = {xmin + (i - 1) * dd[0], xmin + i * dd[0]};
@@ -183,7 +173,7 @@ void drawContext::drawAxis(double xmin, double ymin, double zmin,
   }
 }
 
-void drawContext::drawAxes(int mode, int tics[3], std::string format[3],
+void drawContext::drawAxes(int mode, double tics[3], std::string format[3],
                            std::string label[3], double bb[6], int mikado,
                            double value_bb[6])
 {
@@ -281,7 +271,7 @@ void drawContext::drawAxes(int mode, int tics[3], std::string format[3],
   }
 }
 
-void drawContext::drawAxes(int mode, int tics[3], std::string format[3],
+void drawContext::drawAxes(int mode, double tics[3], std::string format[3],
                            std::string label[3], SBoundingBox3d &bb, int mikado,
                            SBoundingBox3d &value_bb)
 {
diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h
index 0c2c03b717..42ff998e1f 100644
--- a/Graphics/drawContext.h
+++ b/Graphics/drawContext.h
@@ -189,9 +189,9 @@ class drawContext {
   void drawAxis(double xmin, double ymin, double zmin,
                 double xmax, double ymax, double zmax,
                 int nticks, int mikado);
-  void drawAxes(int mode, int tics[3], std::string format[3],
+  void drawAxes(int mode, double tics[3], std::string format[3],
                 std::string label[3], double bb[6], int mikado, double value_bb[6]);
-  void drawAxes(int mode, int tics[3], std::string format[3],
+  void drawAxes(int mode, double tics[3], std::string format[3],
                 std::string label[3], SBoundingBox3d &bb, int mikado, SBoundingBox3d &value_bb);
   void drawAxes();
   void drawSmallAxes();
diff --git a/Graphics/drawGraph2d.cpp b/Graphics/drawGraph2d.cpp
index dcfd0f0e4f..a146aa3098 100644
--- a/Graphics/drawGraph2d.cpp
+++ b/Graphics/drawGraph2d.cpp
@@ -299,7 +299,7 @@ static void drawGraphAxes(drawContext *ctx, PView *p, double xleft, double ytop,
     int nb = opt->axesTics[0];
     if(opt->axes){
       char tmp[256];
-      sprintf(tmp, opt->axesFormat[0].c_str(), - M_PI * 1.e-4);
+      sprintf(tmp, opt->axesFormat[0].c_str(), -M_PI * 1.e4);
       if((nb - 1) * drawContext::global()->getStringWidth(tmp) > width)
         nb = (int)(width / drawContext::global()->getStringWidth(tmp)) + 1;
     }
@@ -487,7 +487,7 @@ void drawContext::drawGraph2d()
   char label[1024];
   for(unsigned int i = 0; i < graphs.size(); i++){
     PViewOptions *opt = graphs[i]->getOptions();
-    sprintf(label, opt->format.c_str(), -M_PI * 1.e-4);
+    sprintf(label, opt->format.c_str(), -M_PI * 1.e4);
     xsep = std::max(xsep, drawContext::global()->getStringWidth(label));
   }
 
diff --git a/Post/PViewOptions.h b/Post/PViewOptions.h
index 24f09a4cfe..56bfbc5dcd 100644
--- a/Post/PViewOptions.h
+++ b/Post/PViewOptions.h
@@ -60,7 +60,8 @@ class PViewOptions {
   int type;
   int position[2], size[2], autoPosition;
   std::string format;
-  int axes, axesAutoPosition, axesMikado, axesTics[3];
+  int axes, axesAutoPosition, axesMikado;
+  double axesTics[3];
   std::string axesFormat[3], axesLabel[3];
   double axesPosition[6];
   double customMin, customMax, tmpMin, tmpMax, externalMin, externalMax;
-- 
GitLab