changeset 11167:51ac3a08e53c

Fix {d,pb}aspectratios for OpenGL backends.
author Konstantinos Poulios <logari81@googlemail.com>
date Thu, 28 Oct 2010 14:12:46 +0200
parents 9cdf43d1fa16
children 36442102c340
files src/ChangeLog src/graphics.cc src/graphics.h.in
diffstat 3 files changed, 164 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Oct 29 10:20:30 2010 +0800
+++ b/src/ChangeLog	Thu Oct 28 14:12:46 2010 +0200
@@ -3,6 +3,29 @@
 	* gl-render.cc: Crop ticks, ticklabels, and gridlines for OpenGL
 	backend.
 
+2010-10-28  Konstantinos Poulios  <logari81@googlemail.com>
+
+        * graphics.cc (normalized_aspectratios, max_axes_scale):
+        New file-scope static function
+        (updating_aspectratios): New file-scope variable.
+        (axes::properties::update_aspectratios, axes::update_axis_limits):
+        Return immediately if updating_aspecratios is true.
+        (axes::properties::update_aspectratios):
+        If dataaspectratiomode is set to manual this function will try to
+        respect it even after changes in xlim, ylim, zlim.
+        If both dataaspectratiomode and plotboxaspectratiomode is set to
+        manual this function will try to recalulate xlim, ylim, zlim
+        depending on the status of xlimmode, ylimmode, zlimmode. If
+        altering xlim, ylim, zlim is not possible, plotboxaspectratio will
+        be overriden.
+        * graphics.h.in (class axes::properties): Tag dataaspectratio,
+        dataaspectratiomode, plotboxaspectratio, and
+        plotboxaspectratiomode with "u" qualifier.
+        (axes::update_dataaspectratio,
+        axes::update_dataaspectratiomode,
+        axes::update_plotboxaspectratio,
+        axes::update_plotboxaspectratiomode): New functions.
+
 2010-10-25  John W. Eaton  <jwe@octave.org>
 
 	* octave.cc (octave_main): Use F77_CHAR_ARC_LEN macro to pass
--- a/src/graphics.cc	Fri Oct 29 10:20:30 2010 +0800
+++ b/src/graphics.cc	Thu Oct 28 14:12:46 2010 +0200
@@ -3911,9 +3911,51 @@
   x_gl_mat2 = x_viewport * x_projection;
 }
 
+static void
+normalized_aspectratios (Matrix& aspectratios, const Matrix& scalefactors,
+                         double xlength, double ylength, double zlength)
+{
+      double xval = xlength/scalefactors(0);
+      double yval = ylength/scalefactors(1);
+      double zval = zlength/scalefactors(2);
+
+      double minval = xmin (xmin (xval, yval), zval);
+
+      aspectratios(0) = xval/minval;
+      aspectratios(1) = yval/minval;
+      aspectratios(2) = zval/minval;
+}
+
+static void
+max_axes_scale (double& s, Matrix& limits, const Matrix& kids,
+                double pbfactor, double dafactor, char limit_type, bool tight)
+{
+  if (tight)
+    {
+      double minval = octave_Inf;
+      double maxval = -octave_Inf;
+      double min_pos = octave_Inf;
+      get_children_limits (minval, maxval, min_pos, kids, limit_type);
+      if (!xisinf (minval) && !xisnan (minval)
+          && !xisinf (maxval) && !xisnan (maxval))
+        {
+          limits(0) = minval;
+          limits(1) = maxval;
+          s = xmax(s, (maxval - minval) / (pbfactor * dafactor));
+        }
+    }
+  else
+    s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor));
+}
+
+static bool updating_aspectratios = false;
+
 void
 axes::properties::update_aspectratios (void)
 {
+  if (updating_aspectratios)
+    return;
+
   Matrix xlimits = get_xlim ().matrix_value ();
   Matrix ylimits = get_ylim ().matrix_value ();
   Matrix zlimits = get_zlim ().matrix_value ();
@@ -3922,35 +3964,102 @@
   double dy = (ylimits(1)-ylimits(0));
   double dz = (zlimits(1)-zlimits(0));
 
+  Matrix da = get_dataaspectratio ().matrix_value ();
+  Matrix pba = get_plotboxaspectratio ().matrix_value ();
+
   if (dataaspectratiomode_is ("auto"))
     {
-      double dmin = xmin (xmin (dx, dy), dz);
-      Matrix da (1, 3, 0.0);
-
-      da(0) = dx/dmin;
-      da(1) = dy/dmin;
-      da(2) = dz/dmin;
-
-      dataaspectratio = da;
-    }
-
-  if (plotboxaspectratiomode_is ("auto"))
-    {
-      if (dataaspectratiomode_is ("auto"))
-        plotboxaspectratio = Matrix (1, 3, 1.0);
+      if (plotboxaspectratiomode_is ("auto"))
+        {
+          pba = Matrix (1, 3, 1.0);
+          plotboxaspectratio.set (pba, false);
+        }
+
+      normalized_aspectratios (da, pba, dx, dy, dz);
+      dataaspectratio.set (da, false);
+    }
+  else if (plotboxaspectratiomode_is ("auto"))
+    {
+      normalized_aspectratios (pba, da, dx, dy, dz);
+      plotboxaspectratio.set (pba, false);
+    }
+  else
+    {
+      double s = -octave_Inf;
+      bool modified_limits = false;
+      Matrix kids;
+
+      if (xlimmode_is ("auto") && ylimmode_is ("auto") && zlimmode_is ("auto"))
+        {
+          modified_limits = true;
+          kids = get_children ();
+          max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', true);
+          max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', true);
+          max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', true);
+        }
+      else if (xlimmode_is ("auto") && ylimmode_is ("auto"))
+        {
+          modified_limits = true;
+          max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', false);
+        }
+      else if (ylimmode_is ("auto") && zlimmode_is ("auto"))
+        {
+          modified_limits = true;
+          max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', false);
+        }
+      else if (zlimmode_is ("auto") && xlimmode_is ("auto"))
+        {
+          modified_limits = true;
+          max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', false);
+        }
+
+      if (modified_limits)
+        {
+
+          unwind_protect frame;
+          frame.protect_var (updating_aspectratios);
+
+          updating_aspectratios = true;
+
+          dx = pba(0) *da(0);
+          dy = pba(1) *da(1);
+          dz = pba(2) *da(2);
+          if (xisinf (s))
+            s = 1 / xmin (xmin (dx, dy), dz);
+
+          if (xlimmode_is ("auto"))
+            {
+              dx = s * dx;
+              xlimits(0) = 0.5 * (xlimits(0) + xlimits(1) - dx);
+              xlimits(1) = xlimits(0) + dx;
+              set_xlim (xlimits);
+              set_xlimmode ("auto");
+            }
+
+          if (ylimmode_is ("auto"))
+            {
+              dy = s * dy;
+              ylimits(0) = 0.5 * (ylimits(0) + ylimits(1) - dy);
+              ylimits(1) = ylimits(0) + dy;
+              set_ylim (ylimits);
+              set_ylimmode ("auto");
+            }
+
+          if (zlimmode_is ("auto"))
+            {
+              dz = s * dz;
+              zlimits(0) = 0.5 * (zlimits(0) + zlimits(1) - dz);
+              zlimits(1) = zlimits(0) + dz;
+              set_zlim (zlimits);
+              set_zlimmode ("auto");
+            }
+        }
       else
         {
-          Matrix da = get_dataaspectratio ().matrix_value ();
-          Matrix pba (1, 3, 0.0);
-
-          pba(0) = dx/da(0);
-          pba(1) = dy/da(1);
-          pba(2) = dz/da(2);
+          normalized_aspectratios (pba, da, dx, dy, dz);
+          plotboxaspectratio.set (pba, false);
         }
     }
-  
-  // FIXME -- if plotboxaspectratiomode is "manual", limits
-  // and/or dataaspectratio might be adapted.
 }
 
 // The INTERNAL flag defines whether position or outerposition is used.
@@ -4448,7 +4557,7 @@
 void
 axes::update_axis_limits (const std::string& axis_type)
 {
-  if (updating_axis_limits)
+  if (updating_axis_limits || updating_aspectratios)
     return;
 
   Matrix kids = xproperties.get_children ();
--- a/src/graphics.h.in	Fri Oct 29 10:20:30 2010 +0800
+++ b/src/graphics.h.in	Thu Oct 28 14:12:46 2010 +0200
@@ -2911,8 +2911,8 @@
       array_property position u , default_axes_position ()
       bool_property box , "on"
       array_property colororder , default_colororder ()
-      array_property dataaspectratio m , Matrix (1, 3, 1.0)
-      radio_property dataaspectratiomode , "{auto}|manual"
+      array_property dataaspectratio mu , Matrix (1, 3, 1.0)
+      radio_property dataaspectratiomode u , "{auto}|manual"
       radio_property layer , "{bottom}|top"
       row_vector_property xlim mu , default_lim ()
       row_vector_property ylim mu , default_lim ()
@@ -2988,8 +2988,8 @@
       string_array_property linestyleorder , "-"
       double_property linewidth , 0.5
       radio_property minorgridlinestyle , "-|--|{:}|-.|none"
-      array_property plotboxaspectratio m , Matrix (1, 3, 1.0)
-      radio_property plotboxaspectratiomode , "{auto}|manual"
+      array_property plotboxaspectratio mu , Matrix (1, 3, 1.0)
+      radio_property plotboxaspectratiomode u , "{auto}|manual"
       radio_property projection , "{orthographic}|perpective"
       radio_property tickdir m , "{in}|out"
       radio_property tickdirmode , "{auto}|manual"
@@ -3014,6 +3014,10 @@
     void update_zscale (void) { sz = get_zscale (); }
 
     void update_view (void) { update_camera (); }
+    void update_dataaspectratio (void) { update_transform (); }
+    void update_dataaspectratiomode (void) { update_transform (); }
+    void update_plotboxaspectratio (void) { update_transform (); }
+    void update_plotboxaspectratiomode (void) { update_transform (); }
 
     void update_xdir (void) { update_camera (); }
     void update_ydir (void) { update_camera (); }