changeset 14324:5a2b012b10c7

allow zooming for logscale plots * graphics.cc (axes::properties::zoom_about_point): Allow zooming for logscale axes. * graphics.h.in (class neg_log_scaler): New class. (log_scalar::do_neg_scale): Delete (log_scalar::scale): Don't attempt to handle negative data. (axes::properties::get_scale): New function. (axes::properties::update_xscale, axes::properties::update_yscale, axes::properties::update_zscale): Use it. (axes::properties::update_xlim): Call update_xscale. (axes::properties::update_ylim): Call update_yscale. (axes::properties::update_zlim): Call update_zscale.
author John W. Eaton <jwe@octave.org>
date Fri, 03 Feb 2012 19:54:26 -0500
parents ec99c8c185be
children 63f1bdf08339
files src/graphics.cc src/graphics.h.in
diffstat 2 files changed, 77 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/graphics.cc
+++ b/src/graphics.cc
@@ -6632,11 +6632,8 @@
   double max_neg_y = -octave_Inf;
   get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');
 
-  if (! xscale_is ("log"))
-    xlims = do_zoom (x, factor, xlims, xscale_is ("log"));
-
-  if (! yscale_is ("log"))
-    ylims = do_zoom (y, factor, ylims, yscale_is ("log"));
+  xlims = do_zoom (x, factor, xlims, xscale_is ("log"));
+  ylims = do_zoom (y, factor, ylims, yscale_is ("log"));
 
   zoom (xlims, ylims, push_to_zoom_stack);
 }
--- a/src/graphics.h.in
+++ b/src/graphics.h.in
@@ -222,10 +222,7 @@
     {
       Matrix retval (m.rows (), m.cols ());
 
-      if (m.any_element_is_positive ())
-        do_scale (m.data (), retval.fortran_vec (), m.numel ());
-      else
-        do_neg_scale (m.data (), retval.fortran_vec (), m.numel ());
+      do_scale (m.data (), retval.fortran_vec (), m.numel ());
 
       return retval;
     }
@@ -234,10 +231,7 @@
     {
       NDArray retval (m.dims ());
 
-      if (m.any_element_is_positive ())
-        do_scale (m.data (), retval.fortran_vec (), m.numel ());
-      else
-        do_neg_scale (m.data (), retval.fortran_vec (), m.numel ());
+      do_scale (m.data (), retval.fortran_vec (), m.numel ());
 
       return retval;
     }
@@ -255,13 +249,47 @@
   void do_scale (const double *src, double *dest, int n) const
     {
       for (int i = 0; i < n; i++)
-        dest[i] = log10(src[i]);
+        dest[i] = log10 (src[i]);
+    }
+};
+
+class neg_log_scaler : public base_scaler
+{
+public:
+  neg_log_scaler (void) { }
+
+  Matrix scale (const Matrix& m) const
+    {
+      Matrix retval (m.rows (), m.cols ());
+
+      do_scale (m.data (), retval.fortran_vec (), m.numel ());
+
+      return retval;
     }
 
-  void do_neg_scale (const double *src, double *dest, int n) const
+  NDArray scale (const NDArray& m) const
+    {
+      NDArray retval (m.dims ());
+
+      do_scale (m.data (), retval.fortran_vec (), m.numel ());
+
+      return retval;
+    }
+
+  double scale (double d) const
+    { return -log10 (-d); }
+
+  double unscale (double d) const
+    { return -pow (10.0, -d); }
+
+  base_scaler* clone (void) const
+    { return new neg_log_scaler (); }
+
+private:
+  void do_scale (const double *src, double *dest, int n) const
     {
       for (int i = 0; i < n; i++)
-        dest[i] = -log10(-src[i]);
+        dest[i] = -log10 (-src[i]);
     }
 };
 
@@ -275,7 +303,8 @@
   scaler (const std::string& s)
     : rep (s == "log"
            ? new log_scaler ()
-           : (s == "linear" ? new lin_scaler () : new base_scaler ()))
+           : (s == "neglog" ? new neg_log_scaler ()
+              : (s == "linear" ? new lin_scaler () : new base_scaler ())))
     { }
 
   ~scaler (void) { delete rep; }
@@ -318,6 +347,8 @@
 
       if (s == "log")
         rep = new log_scaler ();
+      else if (s == "neglog")
+        rep = new neg_log_scaler ();
       else if (s == "linear")
         rep = new lin_scaler ();
       else
@@ -3814,9 +3845,32 @@
     void init (void);
 
   private:
-    void update_xscale (void) { sx = get_xscale (); }
-    void update_yscale (void) { sy = get_yscale (); }
-    void update_zscale (void) { sz = get_zscale (); }
+
+    std::string
+    get_scale (const std::string& scale, const Matrix& lims)
+    {
+      std::string retval = scale;
+
+      if (scale == "log" && lims.numel () > 1 && lims(0) < 0 && lims(1) < 0)
+        retval = "neglog";
+
+      return retval;
+    }
+
+    void update_xscale (void)
+    {
+      sx = get_scale (get_xscale (), xlim.get ().matrix_value ());
+    }
+
+    void update_yscale (void)
+    {
+      sy = get_scale (get_yscale (), ylim.get ().matrix_value ());
+    }
+
+    void update_zscale (void)
+    {
+      sz = get_scale (get_zscale (), zlim.get ().matrix_value ());
+    }
 
     void update_view (void) { sync_positions (); }
     void update_dataaspectratio (void) { sync_positions (); }
@@ -3968,6 +4022,8 @@
 
       fix_limits (xlim);
 
+      update_xscale ();
+
       if (do_clr_zoom)
         zoom_stack.clear ();
 
@@ -3983,6 +4039,8 @@
 
       fix_limits (ylim);
 
+      update_yscale ();
+
       if (do_clr_zoom)
         zoom_stack.clear ();
 
@@ -3998,6 +4056,8 @@
 
       fix_limits (zlim);
 
+      update_zscale ();
+
       zoom_stack.clear ();
 
       update_axes_layout ();