changeset 25966:d85049849e88

improve plot position updates (bug #48273) * graphics.cc (axes::properties::update_outerposition, axes::properties::update_position, axes::properties::update_looseinset): Move here from graphics.in.h. Use intermediate variables in an attempt to improve clarity. Impose limits on position to avoid generating bounding boxes with negative widths.
author John W. Eaton <jwe@octave.org>
date Thu, 25 Oct 2018 16:08:49 -0400
parents e80a87f65997
children e02f500a0980
files libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h
diffstat 2 files changed, 202 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/graphics.cc	Wed Oct 24 15:20:43 2018 -0700
+++ b/libinterp/corefcn/graphics.cc	Thu Oct 25 16:08:49 2018 -0400
@@ -7185,6 +7185,205 @@
     }
 }
 
+void
+axes::properties::update_outerposition (void)
+{
+  set_activepositionproperty ("outerposition");
+  caseless_str old_units = get_units ();
+  set_units ("normalized");
+
+  Matrix outerbox = outerposition.get ().matrix_value ();
+
+  double outer_left = outerbox(0);
+  double outer_bottom = outerbox(1);
+  double outer_width = outerbox(2);
+  double outer_height = outerbox(3);
+
+  double outer_right = outer_width + outer_left;
+  double outer_top = outer_height + outer_bottom;
+
+  Matrix linset = looseinset.get ().matrix_value ();
+  Matrix tinset = tightinset.get ().matrix_value ();
+
+  double left_margin = std::max (linset(0), tinset(0));
+  double bottom_margin = std::max (linset(1), tinset(1));
+  double right_margin = std::max (linset(2), tinset(2));
+  double top_margin = std::max (linset(3), tinset(3));
+
+  double inner_left = outer_left;
+  double inner_right = outer_right;
+
+  if ((left_margin + right_margin) < outer_width)
+    {
+      inner_left += left_margin;
+      inner_right -= right_margin;
+    }
+
+  double inner_bottom = outer_bottom;
+  double inner_top = outer_top;
+
+  if ((bottom_margin + top_margin) < outer_height)
+    {
+      inner_bottom += bottom_margin;
+      inner_top -= top_margin;
+    }
+
+  double inner_width = inner_right - inner_left;
+  double inner_height = inner_top - inner_bottom;
+
+  Matrix innerbox (1, 4);
+
+  innerbox(0) = inner_left;
+  innerbox(1) = inner_bottom;
+  innerbox(2) = inner_width;
+  innerbox(3) = inner_height;
+
+  position = innerbox;
+
+  set_units (old_units);
+  update_transform ();
+}
+
+void
+axes::properties::update_position (void)
+{
+  set_activepositionproperty ("position");
+  caseless_str old_units = get_units ();
+  set_units ("normalized");
+
+  Matrix innerbox = position.get ().matrix_value ();
+
+  double inner_left = innerbox(0);
+  double inner_bottom = innerbox(1);
+  double inner_width = innerbox(2);
+  double inner_height = innerbox(3);
+
+  double inner_right = inner_width + inner_left;
+  double inner_top = inner_height + inner_bottom;
+
+  Matrix linset = looseinset.get ().matrix_value ();
+  Matrix tinset = tightinset.get ().matrix_value ();
+
+  double left_margin = std::max (linset(0), tinset(0));
+  double bottom_margin = std::max (linset(1), tinset(1));
+  double right_margin = std::max (linset(2), tinset(2));
+  double top_margin = std::max (linset(3), tinset(3));
+
+  // FIXME: do we need to place limits on any of these?
+
+  double outer_left = inner_left - left_margin;
+  double outer_bottom = inner_bottom - bottom_margin;
+  double outer_right = inner_right + right_margin;
+  double outer_top = inner_top + top_margin;
+
+  double outer_width = outer_right - outer_left;
+  double outer_height = outer_top = outer_bottom;
+
+  Matrix outerbox (1, 4);
+
+  outerbox(0) = outer_left;
+  outerbox(1) = outer_bottom;
+  outerbox(2) = outer_width;
+  outerbox(3) = outer_height;
+
+  outerposition = outerbox;
+
+  set_units (old_units);
+  update_transform ();
+}
+
+void
+axes::properties::update_looseinset (void)
+{
+  caseless_str old_units = get_units ();
+  set_units ("normalized");
+
+  Matrix linset = looseinset.get ().matrix_value ();
+  Matrix tinset = tightinset.get ().matrix_value ();
+
+  double left_margin = std::max (linset(0), tinset(0));
+  double bottom_margin = std::max (linset(1), tinset(1));
+  double right_margin = std::max (linset(2), tinset(2));
+  double top_margin = std::max (linset(3), tinset(3));
+
+  if (activepositionproperty.is ("position"))
+    {
+      Matrix innerbox = position.get ().matrix_value ();
+
+      double inner_left = innerbox(0);
+      double inner_bottom = innerbox(1);
+      double inner_width = innerbox(2);
+      double inner_height = innerbox(3);
+
+      double inner_right = inner_width + inner_left;
+      double inner_top = inner_height + inner_bottom;
+
+      // FIXME: do we need to place limits on any of these?
+
+      double outer_left = inner_left - left_margin;
+      double outer_bottom = inner_bottom - bottom_margin;
+      double outer_right = inner_right + right_margin;
+      double outer_top = inner_top + top_margin;
+
+      double outer_width = outer_right - outer_left;
+      double outer_height = outer_top = outer_bottom;
+
+      Matrix outerbox (1, 4);
+
+      outerbox(0) = outer_left;
+      outerbox(1) = outer_bottom;
+      outerbox(2) = outer_width;
+      outerbox(3) = outer_height;
+
+      outerposition = outerbox;
+    }
+  else
+    {
+      Matrix outerbox = outerposition.get ().matrix_value ();
+
+      double outer_left = outerbox(0);
+      double outer_bottom = outerbox(1);
+      double outer_width = outerbox(2);
+      double outer_height = outerbox(3);
+
+      double outer_right = outer_width + outer_left;
+      double outer_top = outer_height + outer_bottom;
+
+      double inner_left = outer_left;
+      double inner_right = outer_right;
+
+      if ((left_margin + right_margin) < outer_width)
+        {
+          inner_left += left_margin;
+          inner_right -= right_margin;
+        }
+
+      double inner_bottom = outer_bottom;
+      double inner_top = outer_top;
+
+      if ((bottom_margin + top_margin) < outer_height)
+        {
+          inner_bottom += bottom_margin;
+          inner_top -= top_margin;
+        }
+
+      double inner_width = inner_right - inner_left;
+      double inner_height = inner_top - inner_bottom;
+
+      Matrix innerbox (1, 4);
+
+      innerbox(0) = inner_left;
+      innerbox(1) = inner_bottom;
+      innerbox(2) = inner_width;
+      innerbox(3) = inner_height;
+
+      position = innerbox;
+    }
+
+  set_units (old_units);
+  update_transform ();
+}
+
 // A translation from Tom Holoryd's python code at
 // http://kurage.nimh.nih.gov/tomh/tics.py
 // FIXME: add log ticks
--- a/libinterp/corefcn/graphics.in.h	Wed Oct 24 15:20:43 2018 -0700
+++ b/libinterp/corefcn/graphics.in.h	Thu Oct 25 16:08:49 2018 -0400
@@ -3999,85 +3999,9 @@
       sync_positions ();
     }
 
-    void update_outerposition (void)
-    {
-      set_activepositionproperty ("outerposition");
-      caseless_str old_units = get_units ();
-      set_units ("normalized");
-      Matrix outerbox = outerposition.get ().matrix_value ();
-      Matrix innerbox = position.get ().matrix_value ();
-      Matrix linset = looseinset.get ().matrix_value ();
-      Matrix tinset = tightinset.get ().matrix_value ();
-      outerbox(2) = outerbox(2) + outerbox(0);
-      outerbox(3) = outerbox(3) + outerbox(1);
-      innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
-      innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
-      innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
-      innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
-      innerbox(2) = innerbox(2) - innerbox(0);
-      innerbox(3) = innerbox(3) - innerbox(1);
-      position = innerbox;
-      set_units (old_units);
-      update_transform ();
-    }
-
-    void update_position (void)
-    {
-      set_activepositionproperty ("position");
-      caseless_str old_units = get_units ();
-      set_units ("normalized");
-      Matrix outerbox = outerposition.get ().matrix_value ();
-      Matrix innerbox = position.get ().matrix_value ();
-      Matrix linset = looseinset.get ().matrix_value ();
-      Matrix tinset = tightinset.get ().matrix_value ();
-      innerbox(2) = innerbox(2) + innerbox(0);
-      innerbox(3) = innerbox(3) + innerbox(1);
-      outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
-      outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
-      outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
-      outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
-      outerbox(2) = outerbox(2) - outerbox(0);
-      outerbox(3) = outerbox(3) - outerbox(1);
-      outerposition = outerbox;
-      set_units (old_units);
-      update_transform ();
-    }
-
-    void update_looseinset (void)
-    {
-      caseless_str old_units = get_units ();
-      set_units ("normalized");
-      Matrix innerbox = position.get ().matrix_value ();
-      innerbox(2) = innerbox(2) + innerbox(0);
-      innerbox(3) = innerbox(3) + innerbox(1);
-      Matrix outerbox = outerposition.get ().matrix_value ();
-      outerbox(2) = outerbox(2) + outerbox(0);
-      outerbox(3) = outerbox(3) + outerbox(1);
-      Matrix linset = looseinset.get ().matrix_value ();
-      Matrix tinset = tightinset.get ().matrix_value ();
-      if (activepositionproperty.is ("position"))
-        {
-          outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
-          outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
-          outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
-          outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
-          outerbox(2) = outerbox(2) - outerbox(0);
-          outerbox(3) = outerbox(3) - outerbox(1);
-          outerposition = outerbox;
-        }
-      else
-        {
-          innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
-          innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
-          innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
-          innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
-          innerbox(2) = innerbox(2) - innerbox(0);
-          innerbox(3) = innerbox(3) - innerbox(1);
-          position = innerbox;
-        }
-      set_units (old_units);
-      update_transform ();
-    }
+    void update_outerposition (void);
+    void update_position (void);
+    void update_looseinset (void);
 
     double calc_tick_sep (double minval, double maxval);
     void calc_ticks_and_lims (array_property& lims, array_property& ticks,