changeset 10917:888c75785221

Improvements to FLTK backend rotation * Don't rotate past the top and bottom * Implement __calc_dimensions__ in C++ so that it's available to graphics object ctors * Make rotation the default mode in 3d plots * Replace an instance of m-script __calc_dimensions__ with C++ version
author Jordi Guti?rrez Hermoso <jordigh@gmail.com>
date Fri, 27 Aug 2010 15:11:35 -0400
parents 5074494f01a9
children 811f8611995d
files scripts/ChangeLog scripts/plot/__go_draw_axes__.m scripts/plot/private/__actual_axis_position__.m src/ChangeLog src/DLD-FUNCTIONS/fltk_backend.cc src/graphics.cc src/graphics.h.in
diffstat 7 files changed, 129 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,8 @@
+2010-08-27  Jordi GutiƩrrez Hermoso  <jordigh@gmail.com>
+
+	* plot/__go_draw_axes__.m (__calc_dimensions__): Delete.
+	* plot/__actual_axis_position__.m (__calc_dimensions__): Delete.
+
 2010-08-27  Pascal A. Dupuis  <Pascal.Dupuis@worldonline.be>
 
 	* plot/hold.m: If arg is axis handle, get corresponding figure
--- a/scripts/plot/__go_draw_axes__.m
+++ b/scripts/plot/__go_draw_axes__.m
@@ -45,7 +45,8 @@
       ymirror = true;
     endif
 
-    nd = __calc_dimensions__ (axis_obj);
+    nd = __calc_dimensions__ (h);
+
     if (strcmpi (axis_obj.plotboxaspectratiomode, "manual"))
       pos = __actual_axis_position__ (axis_obj);
     else
@@ -1786,29 +1787,6 @@
 
 endfunction
 
-function nd = __calc_dimensions__ (obj)
-  kids = obj.children;
-  nd = 2;
-  for i = 1:length (kids)
-    obj = get (kids(i));
-    switch (obj.type)
-      case {"image", "text"}
-        ## ignore as they 
-      case {"line", "patch"}
-        if (! isempty (obj.zdata))
-          nd = 3;
-        endif
-      case "surface"
-        nd = 3;
-      case "hggroup"
-        obj_nd = __calc_dimensions__ (obj);
-        if (obj_nd == 3)
-          nd = 3;
-        endif
-    endswitch
-  endfor
-endfunction
-
 function __gnuplot_write_data__ (plot_stream, data, nd, parametric, cdata)
   
   ## DATA is already transposed.
--- a/scripts/plot/private/__actual_axis_position__.m
+++ b/scripts/plot/private/__actual_axis_position__.m
@@ -31,7 +31,8 @@
 
   ## When using {rltb}margin, Gnuplot does not handle the specified
   ## aspect ratio properly, so handle it here.
-  if (__calc_dimensions__ (axis_obj) == 2 || all (mod (axis_obj.view, 90) == 0))
+  if (__calc_dimensions__ (axis_obj.parent) == 2
+      || all (mod (axis_obj.view, 90) == 0))
     aspect_ratio_2d = axis_obj.plotboxaspectratio(1:2);
   else
     ## FIXME -- this works for "axis square", but has not been
@@ -63,26 +64,3 @@
 
 endfunction
 
-function nd = __calc_dimensions__ (obj)
-  kids = obj.children;
-  nd = 2;
-  for i = 1:length (kids)
-    obj = get (kids(i));
-    switch (obj.type)
-      case {"image", "text"}
-        ## ignore as they 
-      case {"line", "patch"}
-        if (! isempty (obj.zdata))
-          nd = 3;
-        endif
-      case "surface"
-        nd = 3;
-      case "hggroup"
-        obj_nd = __calc_dimensions__ (obj);
-        if (obj_nd == 3)
-          nd = 3;
-        endif
-    endswitch
-  endfor
-endfunction
-
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2010-08-27  Jordi GutiƩrrez Hermoso  <jordigh@gmail.com>
+
+	* graphics.cc (axes::properties::rotate_view): Don't rotate past
+	the top and bottom.
+	(axes::properties::update_camera): Fix the view when rotating to
+	the bottom.
+	(calc_dimensions): New static function.
+	(F__calc_dimensions__) New defun to replace m-script function.
+	* graphics.h.in (calc_dimension): Provide decl.
+	* DLD-FUNCTIONS/fltk_backend.cc (plot_window::plot_window):
+	Use calc_dimensions to decide whether the current figure should
+	be rotated.
+	(plot_window::mark_modified) Recompute the number of dimensions.
+	Deactivate rotation if necessary.
+	(plot_window::ndim) New data member.
+	(plot_window::button_press, plot_window::handle): Only turn on
+	rotation if ndim == 3.
+
 2010-08-24  David Bateman  <dbateman@free.fr>
 
 	* ls-mat5.cc (static void read_mat5_binary_data (std::istream&,
--- a/src/DLD-FUNCTIONS/fltk_backend.cc
+++ b/src/DLD-FUNCTIONS/fltk_backend.cc
@@ -224,7 +224,8 @@
 public:
   plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp)
     : Fl_Window (xx, yy, ww, hh, "octave"), window_label (), shift (0),
-      fp (xfp), canvas (0), autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0), status (0)
+      ndim (2), fp (xfp), canvas (0), autoscale (0), togglegrid (0),
+      panzoom (0), rotate (0), help (0), status (0)
   {
     callback (window_close, static_cast<void*> (this));
 
@@ -239,7 +240,9 @@
                 ww, 
                 status_h);
       bottom->box(FL_FLAT_BOX);
-      
+
+      ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ()));
+
       autoscale = new
         Fl_Button (0,
                    hh - status_h,
@@ -266,7 +269,7 @@
                    "P");
       panzoom->callback (button_callback, static_cast<void*> (this));
       panzoom->tooltip ("Mouse Pan/Zoom");
-      
+
       rotate = new
         Fl_Button (3 * status_h,
                    hh - status_h,
@@ -276,6 +279,9 @@
       rotate->callback (button_callback, static_cast<void*> (this));
       rotate->tooltip ("Mouse Rotate");
 
+      if (ndim == 2)
+        rotate->deactivate ();
+
       help = new
         Fl_Button (4 * status_h,
                    hh - status_h,
@@ -317,7 +323,7 @@
     set_name ();
     resizable (canvas);
     size_range (4*status_h, 2*status_h);
-    gui_mode = pan_zoom;
+    gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom);
   }
 
   ~plot_window (void)
@@ -346,6 +352,15 @@
   {
     damage (FL_DAMAGE_ALL);
     canvas->damage (FL_DAMAGE_ALL);
+    ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ()));
+
+    if (ndim == 3)
+      rotate->activate ();
+    else
+      {
+        rotate->deactivate ();
+        gui_mode = pan_zoom;
+      }
   }
 
   void set_name (void)
@@ -362,6 +377,9 @@
   // Mod keys status
   int shift;
 
+  // Number of dimensions, 2 or 3.
+  int ndim;
+
   // Interactive Mode
   enum { pan_zoom, rotate_zoom } gui_mode;
   
@@ -396,7 +414,7 @@
     if (widg == panzoom)
       gui_mode = pan_zoom;
     
-    if (widg == rotate)
+    if (widg == rotate && ndim == 3)
       gui_mode = rotate_zoom;
 
     if (widg == help)
@@ -656,7 +674,10 @@
 
             case 'r':
             case 'R':
-              gui_mode = rotate_zoom;
+              if (ndim == 3)
+                gui_mode = rotate_zoom;
+              else
+                gui_mode = pan_zoom;
             break;
             }
         }
--- a/src/graphics.cc
+++ b/src/graphics.cc
@@ -3434,8 +3434,10 @@
 
       if (el == 90 || el == -90)
         {
-          c_upv(0) = -sin(az*M_PI/180.0)*(xlimits(1)-xlimits(0))/pb(0);
-          c_upv(1) = cos(az*M_PI/180.0)*(ylimits(1)-ylimits(0))/pb(1);
+          c_upv(0) =
+            -signum(el)*sin(az*M_PI/180.0)*(xlimits(1)-xlimits(0))/pb(0);
+          c_upv(1) =
+            signum(el)*cos(az*M_PI/180.0)*(ylimits(1)-ylimits(0))/pb(1);
         }
       else
         c_upv(2) = 1;
@@ -4278,7 +4280,7 @@
   xlims (1) += delta_x;
   ylims (0) += delta_y;
   ylims (1) += delta_y;
-                
+ 
   zoom (xlims, ylims, false);
 }
 
@@ -4288,7 +4290,13 @@
   Matrix v = get_view ().matrix_value ();
 
   v (1) += delta_el;
-  v (0) -= delta_az;
+
+  if(v(1) > 90)
+    v(1) = 90;
+  if(v(1) < -90)
+    v(1) = -90;
+
+  v (0) = fmod(v(0) - delta_az + 720,360);
 
   set_view(v);
   update_transform();
@@ -5498,6 +5506,67 @@
  \
   return retval
 
+int
+calc_dimensions (const graphics_object& go)
+{
+
+  int nd = 2;
+
+  if (go.isa ("surface"))
+    nd = 3;
+
+  if ((go.isa ("line") || go.isa ("patch")) && ! go.get("zdata").is_empty ())
+    nd = 3;
+
+  Matrix kids = go.get_properties().get_children ();
+
+  for (octave_idx_type i = 0; i < kids.length (); i++)
+    {
+      graphics_handle hnd = gh_manager::lookup (kids(i));
+
+      if (hnd.ok ())
+        {
+          const graphics_object& kid = gh_manager::get_object(hnd);
+
+          if (kid.valid_object())
+            nd = calc_dimensions (kid);
+
+          if (nd == 3)
+            break;
+        }
+    }
+
+  return nd;
+}
+
+DEFUN (__calc_dimensions__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __calc_dimensions__ (@var{axes})\n\
+Internal function. Determine the number of dimensions in a graphics\n\
+object, whether 2 or 3.\n\
+@end deftypefn")
+{
+  gh_manager::autolock guard;
+
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+      double h = args(0).double_value ();
+
+      if (! error_state)
+        retval = calc_dimensions (gh_manager::get_object (h));
+      else
+        error ("__calc_dimensions__: expecting graphics handle as only argument");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
 DEFUN (__go_axes__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} __go_axes__ (@var{parent})\n\
--- a/src/graphics.h.in
+++ b/src/graphics.h.in
@@ -4250,6 +4250,8 @@
 void get_children_limits (double& min_val, double& max_val, double& min_pos,
                           const Matrix& kids, char limit_type);
 
+OCTINTERP_API int calc_dimensions (const graphics_object& gh);
+
 // This function is NOT equivalent to the scripting language function gcf.
 OCTINTERP_API graphics_handle gcf (void);