# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1477655983 -7200
#      Fri Oct 28 13:59:43 2016 +0200
# Node ID a6dbf5aa2f1790697e6cf2e2a5263d224adeea51
# Parent  340e37fd3c2046d2e45b64105826383a58f120ca
Correct locations of minor grid lines for manual ticks (bug #45850)

* graphics.cc (axes::properties::calc_ticks_and_lims): Use manually set
ticks for calculation of minor grid.

* graphics.in.h (axes::properties): Trigger minor grid calculation on
update_(xyz)tick and update_(xyz)lim.

* grid.m: Add demo.

diff -r 340e37fd3c20 -r a6dbf5aa2f17 libinterp/corefcn/graphics.cc
--- a/libinterp/corefcn/graphics.cc	Thu Oct 27 17:18:27 2016 -0700
+++ b/libinterp/corefcn/graphics.cc	Fri Oct 28 13:59:43 2016 +0200
@@ -6867,7 +6867,9 @@
 axes::properties::calc_ticks_and_lims (array_property& lims,
                                        array_property& ticks,
                                        array_property& mticks,
-                                       bool limmode_is_auto, bool is_logscale)
+                                       bool limmode_is_auto,
+                                       bool tickmode_is_auto,
+                                       bool is_logscale)
 {
   // FIXME: add log ticks and lims
 
@@ -6897,73 +6899,83 @@
         }
     }
 
-  double tick_sep;
-
-  if (is_logscale)
-    {
-      if (! (octave::math::isinf (hi) || octave::math::isinf (lo)))
-        tick_sep = 1;  // Tick is every order of magnitude (bug #39449)
-      else
-        tick_sep = 0;
-    }
-  else
-    tick_sep = calc_tick_sep (lo, hi);
-
-  double i1 = std::floor (lo / tick_sep);
-  double i2 = std::ceil (hi / tick_sep);
-
-  if (limmode_is_auto)
-    {
-      // Adjust limits to include min and max ticks
-      Matrix tmp_lims (1,2);
-      tmp_lims(0) = std::min (tick_sep * i1, lo);
-      tmp_lims(1) = std::max (tick_sep * i2, hi);
+  Matrix tmp_ticks;
+  if (tickmode_is_auto)
+    {
+      double tick_sep;
 
       if (is_logscale)
         {
-          tmp_lims(0) = std::pow (10., tmp_lims(0));
-          tmp_lims(1) = std::pow (10., tmp_lims(1));
-          if (tmp_lims(0) <= 0)
-            tmp_lims(0) = std::pow (10., lo);
-          if (is_negative)
+          if (! (octave::math::isinf (hi) || octave::math::isinf (lo)))
+            tick_sep = 1;  // Tick is every order of magnitude (bug #39449)
+          else
+            tick_sep = 0;
+        }
+      else
+        tick_sep = calc_tick_sep (lo, hi);
+
+      double i1 = std::floor (lo / tick_sep);
+      double i2 = std::ceil (hi / tick_sep);
+
+      if (limmode_is_auto)
+        {
+          // Adjust limits to include min and max ticks
+          Matrix tmp_lims (1,2);
+          tmp_lims(0) = std::min (tick_sep * i1, lo);
+          tmp_lims(1) = std::max (tick_sep * i2, hi);
+
+          if (is_logscale)
             {
+              tmp_lims(0) = std::pow (10., tmp_lims(0));
+              tmp_lims(1) = std::pow (10., tmp_lims(1));
+              if (tmp_lims(0) <= 0)
+                tmp_lims(0) = std::pow (10., lo);
+              if (is_negative)
+                {
               double tmp = tmp_lims(0);
-              tmp_lims(0) = -tmp_lims(1);
-              tmp_lims(1) = -tmp;
+                  tmp_lims(0) = -tmp_lims(1);
+                  tmp_lims(1) = -tmp;
+                }
             }
-        }
-      lims = tmp_lims;
+          lims = tmp_lims;
+        }
+      else
+        {
+          // adjust min and max ticks to be within limits
+          if (i1*tick_sep < lo)
+            i1++;
+          if (i2*tick_sep > hi && i2 > i1)
+            i2--;
+        }
+
+      tmp_ticks = Matrix (1, i2-i1+1);
+      for (int i = 0; i <= static_cast<int> (i2-i1); i++)
+        {
+          tmp_ticks(i) = tick_sep * (i+i1);
+          if (is_logscale)
+            tmp_ticks(i) = std::pow (10., tmp_ticks(i));
+        }
+      if (is_logscale && is_negative)
+        {
+          Matrix rev_ticks (1, i2-i1+1);
+          rev_ticks = -tmp_ticks;
+      for (int i = 0; i <= static_cast<int> (i2-i1); i++)
+            tmp_ticks(i) = rev_ticks(i2-i1-i);
+        }
+
+      ticks = tmp_ticks;
     }
   else
-    {
-      // adjust min and max ticks to be within limits
-      if (i1*tick_sep < lo)
-        i1++;
-      if (i2*tick_sep > hi && i2 > i1)
-        i2--;
-    }
-
-  Matrix tmp_ticks (1, i2-i1+1);
-  for (int i = 0; i <= static_cast<int> (i2-i1); i++)
-    {
-      tmp_ticks(i) = tick_sep * (i+i1);
-      if (is_logscale)
-        tmp_ticks(i) = std::pow (10., tmp_ticks(i));
-    }
-  if (is_logscale && is_negative)
-    {
-      Matrix rev_ticks (1, i2-i1+1);
-      rev_ticks = -tmp_ticks;
-      for (int i = 0; i <= static_cast<int> (i2-i1); i++)
-        tmp_ticks(i) = rev_ticks(i2-i1-i);
-    }
-
-  ticks = tmp_ticks;
+    tmp_ticks = ticks.get ().matrix_value ();
+
+  octave_idx_type n_ticks = tmp_ticks.numel ();
+  if (n_ticks < 2)
+    return;
 
   int n = is_logscale ? 8 : 4;
-  Matrix tmp_mticks (1, n * (tmp_ticks.numel () - 1));
-
-  for (int i = 0; i < tmp_ticks.numel ()-1; i++)
+  Matrix tmp_mticks (1, n * (n_ticks - 1));
+
+  for (int i = 0; i < n_ticks-1; i++)
     {
       double d = (tmp_ticks(i+1) - tmp_ticks(i)) / (n + 1);
       for (int j = 0; j < n; j++)
diff -r 340e37fd3c20 -r a6dbf5aa2f17 libinterp/corefcn/graphics.in.h
--- a/libinterp/corefcn/graphics.in.h	Thu Oct 27 17:18:27 2016 -0700
+++ b/libinterp/corefcn/graphics.in.h	Fri Oct 28 13:59:43 2016 +0200
@@ -4015,18 +4015,24 @@
 
     void update_xtick (void)
     {
+      calc_ticks_and_lims (xlim, xtick, xminortickvalues, xlimmode.is ("auto"),
+                           xtickmode.is ("auto"), xscale.is ("log"));
       if (xticklabelmode.is ("auto"))
         calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
       sync_positions ();
     }
     void update_ytick (void)
     {
+      calc_ticks_and_lims (ylim, ytick, yminortickvalues, ylimmode.is ("auto"),
+                           ytickmode.is ("auto"), yscale.is ("log"));
       if (yticklabelmode.is ("auto"))
         calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
       sync_positions ();
     }
     void update_ztick (void)
     {
+      calc_ticks_and_lims (zlim, ztick, zminortickvalues, zlimmode.is ("auto"),
+                           ztickmode.is ("auto"), zscale.is ("log"));
       if (zticklabelmode.is ("auto"))
         calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
       sync_positions ();
@@ -4035,29 +4041,17 @@
     void update_xtickmode (void)
     {
       if (xtickmode.is ("auto"))
-        {
-          calc_ticks_and_lims (xlim, xtick, xminortickvalues,
-                               xlimmode.is ("auto"), xscale.is ("log"));
-          update_xtick ();
-        }
+        update_xtick ();
     }
     void update_ytickmode (void)
     {
       if (ytickmode.is ("auto"))
-        {
-          calc_ticks_and_lims (ylim, ytick, yminortickvalues,
-                               ylimmode.is ("auto"), yscale.is ("log"));
-          update_ytick ();
-        }
+        update_ytick ();
     }
     void update_ztickmode (void)
     {
       if (ztickmode.is ("auto"))
-        {
-          calc_ticks_and_lims (zlim, ztick, zminortickvalues,
-                               zlimmode.is ("auto"), zscale.is ("log"));
-          update_ztick ();
-        }
+        update_ztick ();
     }
 
     void update_xticklabelmode (void)
@@ -4180,8 +4174,8 @@
 
     double calc_tick_sep (double minval, double maxval);
     void calc_ticks_and_lims (array_property& lims, array_property& ticks,
-                              array_property& mticks,
-                              bool limmode_is_auto, bool is_logscale);
+                              array_property& mticks, bool limmode_is_auto,
+                              bool tickmode_is_auto, bool is_logscale);
     void calc_ticklabels (const array_property& ticks, any_property& labels,
                           bool is_logscale);
     Matrix get_ticklabel_extents (const Matrix& ticks,
@@ -4217,9 +4211,8 @@
 
     void update_xlim ()
     {
-      if (xtickmode.is ("auto"))
-        calc_ticks_and_lims (xlim, xtick, xminortickvalues,
-                             xlimmode.is ("auto"), xscale.is ("log"));
+      calc_ticks_and_lims (xlim, xtick, xminortickvalues, xlimmode.is ("auto"),
+                           xtickmode.is ("auto"), xscale.is ("log"));
       if (xticklabelmode.is ("auto"))
         calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
 
@@ -4232,9 +4225,8 @@
 
     void update_ylim (void)
     {
-      if (ytickmode.is ("auto"))
-        calc_ticks_and_lims (ylim, ytick, yminortickvalues,
-                             ylimmode.is ("auto"), yscale.is ("log"));
+      calc_ticks_and_lims (ylim, ytick, yminortickvalues, ylimmode.is ("auto"),
+                           ytickmode.is ("auto"), yscale.is ("log"));
       if (yticklabelmode.is ("auto"))
         calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
 
@@ -4247,9 +4239,8 @@
 
     void update_zlim (void)
     {
-      if (ztickmode.is ("auto"))
-        calc_ticks_and_lims (zlim, ztick, zminortickvalues,
-                             zlimmode.is ("auto"), zscale.is ("log"));
+      calc_ticks_and_lims (zlim, ztick, zminortickvalues, zlimmode.is ("auto"),
+                           ztickmode.is ("auto"), zscale.is ("log"));
       if (zticklabelmode.is ("auto"))
         calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
 
diff -r 340e37fd3c20 -r a6dbf5aa2f17 scripts/plot/appearance/grid.m
--- a/scripts/plot/appearance/grid.m	Thu Oct 27 17:18:27 2016 -0700
+++ b/scripts/plot/appearance/grid.m	Fri Oct 28 13:59:43 2016 +0200
@@ -82,7 +82,6 @@
       minor_auto = false;
     elseif (strcmpi (arg1, "on"))
       grid_on = true;
-      minor_on = false;
       minor_auto = true;
     elseif (strcmpi (arg1, "minor"))
       minor_auto = false;
@@ -180,6 +179,18 @@
 %!  set (gca, "xminorgrid", "on");
 %!  set (gca, "yminorgrid", "on");
 
+%!demo
+%! clf;
+%! plot3 (1:10, 1:10, 1:10);
+%! set (gca, "xtick", [0, pi/2, 4.7, 8, 10]);
+%! set (gca, "ytick", [0, 1, pi, 7.3, 10]);
+%! set (gca, "ztick", [0, exp(1), 5, 9.1, 10]);
+%! set (gca, "xminorgrid", "on");
+%! set (gca, "yminorgrid", "on");
+%! set (gca, "zminorgrid", "on");
+%! view (3);
+%! title ("Minor grid adapts to xticks (bug #45850)")
+
 ## linear scaling
 %!test <48533>
 %! hf = figure ("visible", "off");
