octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: plot templates and options lists for set, plot etc.


From: Thorsten Meyer
Subject: Re: plot templates and options lists for set, plot etc.
Date: Sun, 05 Jul 2009 22:24:17 +0200
User-agent: Mozilla-Thunderbird 2.0.0.19 (X11/20090103)

Thorsten Meyer wrote:
> Hi,
> 
> thanks a lot for the quick response.
> 
> Ben Abbott wrote:
>> On Jul 5, 2009, at 7:23 AM, Thorsten Meyer wrote:
>>
>>> Hi,
>>>> I'm running Matlab 2009a
>>>>
>>>> x = 0:0.01:5;
>>>> h(1) = line (x, sin(x));
>>>> h(2) = line (x, cos(x));
>>>> s(1,1).Color = 'red';
>>>> s(1,2).Color = 'green';
>>>> set (h, s);
>>>> color = get (h, 'color');
>>>> color{:}
>>>> ans =
>>>>     0     1     0
>>>> ans =
>>>>     0     1     0
>>>>
>>>> I'd expected the lines to have different colors.
>>> Could you also try
>>>    h(1) = line (x, sin(x));
>>>    h(2) = line (x, cos(x));
>>>    s(1,1).Color = 'red';
>>>    s(2,1).Color = 'green';
>>>    set (h, s);
>>>    color = get (h, 'color');
>>>    color{:}
>>> ?
>> My usual computer is in for repair. My second machine is PPC based and
>> is only able to run Matlab R2007b. I had to add the 3rd line below to
>> run your script, but the results are not correct.
>>
>>>> h(1) = line (x, sin(x));
>>>> h(2) = line (x, cos(x));
>>>> s = struct ();
>>>> s(1,1).Color = 'red';
>>>> s(2,1).Color = 'green';
>>>> set (h, s);
>>>> color = get (h, 'color');
>>>> color{:}
>>>> ans =
>>      0     1     0
>>>> ans =
>>      0     1     0
>>
> So, matlab sets all elements of the properties structure for each of the
> handles in h independent of the dimensions of the structure (unless they
> have changed it in the 2009 version). Or, nicer to implement: it sets
> the values found in the last elements of the struct array fields.
>>>> I also tried the following ...
>>>>
>>>> property_names = {'color', 'color'};
>>>> property_values = {[1,0,0], [0,1,0]};
>>>> set (h, property_names, property_values)
>>>> color = get (h, 'color');
>>>> color{:}
>>>> ans =
>>>>     0     1     0
>>>> ans =
>>>>     0     1     0
>>>>
>>>> It appears that the property names and values are each applied to all
>>>> handles. The green sticks because it was set last.
>>> Could you try again with
>>>    property_names = {'color'};
>>>    property_values = {[1,0,0]; [0,1,0]};
>>>    set (h, property_names, property_values)
>>>    color = get (h, 'color');
>>>    color{:}
>>> ?
>>>> property_names = {'color'};
>>>> property_values = {[1,0,0]; [0,1,0]};
>>>> set (h, property_names, property_values)
>> ??? Error using ==> set
>> Value cell array handle dimension must match handle vector length.
>>
>> But this does work
>>
>>>> x = 0:0.01:5;
>>>> h(1,1) = line (x, sin(x));
>>>> h(2,1) = line (x, cos(x));
>>>> pn = {'Color'};
>>>> pv = {'red'; 'green'};
>>>> set (h, pn, pv);
>>>> color = get (h, 'color');
>>>> color{:}
>>>> ans =
>>      1     0     0
>>>> ans =
>>      0     1     0
> Ok, so matlab really wants to have values meant for different elements
> of the handle vector in the rows of the values cell array.
> 
> I'll put this behaviour in my patch for the set function.
> 
Here is a patch implementing struct and cell array arguments for the set 
function.

I have impplemented the matlab behaviour (as I understand it ...). See the tests
 added to the patch for the details.

Could somebody please review the patch (what I do in the sources is still a lot
of trial and error):
 - Have I got the types of the various variables right?
 - Is it ok to add doxygen style comments to the new methods? (the doxygen docs
have helped me a lot to find my way in the sources)
 - What about the coding style?
 - Are the added methods for the graphics_object ok (also where I placed the
definitions)?

Thanks

Thorsten
# HG changeset patch
# User Thorsten Meyer <address@hidden>
# Date 1246822969 -7200
# Node ID 17d8e1a009024fe7e3ab0bbb8822e92743d53c9a
# Parent  0dd3c7a2ba19af3eaec6053b49dbe0d048fc31aa
Fix set function to allow cell and struct arguments.

diff -r 0dd3c7a2ba19 -r 17d8e1a00902 src/ChangeLog
--- a/src/ChangeLog     Sat Jul 04 13:19:20 2009 +0200
+++ b/src/ChangeLog     Sun Jul 05 21:42:49 2009 +0200
@@ -0,0 +1,8 @@
+2009-07-05  Thorsten Meyer  <address@hidden>
+
+       * graphics.cc (Fset), graphics.cc (graphics_object::set): Add
+       support for struct and cell arguments.
+
+       * graphics.h.in (graphics_objects::set): Add prototypes for
+       calling with struct respectively cell arguments.
+
diff -r 0dd3c7a2ba19 -r 17d8e1a00902 src/graphics.cc
--- a/src/graphics.cc   Sat Jul 04 13:19:20 2009 +0200
+++ b/src/graphics.cc   Sun Jul 05 21:42:49 2009 +0200
@@ -1322,6 +1322,94 @@
     }
 }
 
+//! Set properties given in two cell arrays containing names and values.
+void
+graphics_object::set (const Array<std::string> names,
+                      const Cell values, octave_idx_type row)
+{
+  if (! (names.numel () == values.columns ())) 
+    {
+      error("set: number of names must match number of value columns (%d != 
%d)",
+            names.numel (), values.columns ());
+    }
+
+  octave_idx_type k = names.columns ();
+
+  for (octave_idx_type column = 0; column < k; column++)
+    {
+      caseless_str name = names(column);
+      octave_value val  = values(row, column);
+
+      set_value_or_default (name, val);
+
+      if (error_state)
+        break;
+    }
+}
+
+/*
+%!# test set with cell array arguments
+%!test
+%!  set (gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1);
+%!  set (h, {"linewidth", "marker"}, {10, "x"});
+%!  assert (get(h, "linewidth"), 10);
+%!  assert (get(h, "marker"), "x");
+
+%!# test set with multiple handles and cell array arguments
+%!test
+%!  set (gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1, 1:10, 1:10);
+%!  set (h, {"linewidth", "marker"}, {10, "x"; 5, "o"});
+%!  assert (get (h, "linewidth"), {10; 5});
+%!  assert (get (h, "marker"), {"x"; "o"});
+%!  set (h, {"linewidth", "marker"}, {10, "x"});
+%!  assert (get (h, "linewidth"), {10; 10});
+%!  assert (get (h, "marker"), {"x"; "x"});
+
+%!error <set: number of graphics handles must match number of value rows>
+%!  set (gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1, 1:10, 1:10);
+%!  set (h, {"linewidth", "marker"}, {10, "x"; 5, "o"; 7, "."});
+
+%!error <set: number of names must match number of value columns>
+%!  set (gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1, 1:10, 1:10);
+%!  set (h, {"linewidth"}, {10, "x"; 5, "o"});
+*/
+
+//! Set properties given in a struct array
+void
+graphics_object::set (const Octave_map m)
+{
+  for (Octave_map::const_iterator p = m.begin ();
+       p != m.end (); p++)
+    {
+      caseless_str name  = m.key (p);
+
+      octave_value val = octave_value (m.contents (p).elem (m.numel () - 1));
+
+      set_value_or_default (name, val);
+
+      if (error_state)
+        break;
+    }
+}
+
+/*
+%!# test set with struct arguments
+%!test
+%!  set (gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1);
+%!  set (h, struct ("linewidth", 10, "marker", "x"));
+%!  assert (get (h, "linewidth"), 10);
+%!  assert (get (h, "marker"), "x");
+%!  h = plot (1:10, 10:-1:1, 1:10, 1:10);
+%!  set (h, struct ("linewidth", {5, 10}));
+%!  assert (get(h, "linewidth"), {10; 10});
+*/
+
+//! Set properties given in a cs-list of (name, value) pairs
 void
 graphics_object::set (const octave_value_list& args)
 {
@@ -1339,20 +1427,10 @@
            {
              octave_value val = args(i+1);
 
-             if (val.is_string ())
-               {
-                 caseless_str tval = val.string_value ();
-
-                 if (tval.compare ("default"))
-                   val = get_default (name);
-                 else if (tval.compare ("factory"))
-                   val = get_factory_default (name);
-               }
+              set_value_or_default (name, val);
 
              if (error_state)
                break;
-
-             rep->set (name, val);
            }
          else
            error ("set: expecting argument %d to be a property name", i);
@@ -1362,6 +1440,36 @@
     error ("set: invalid number of arguments");
 }
 
+/*
+%!# test set with name, value pairs
+%!test
+%!  set(gcf, "visible", "off");
+%!  h = plot (1:10, 10:-1:1);
+%!  set (h, "linewidth", 10, "marker", "x");
+%!  assert (get (h, "linewidth"), 10);
+%!  assert (get (h, "marker"), "x");
+*/
+
+//! Set a property to a value or to its (factory) default value.
+void graphics_object::set_value_or_default (caseless_str& name,
+                                            octave_value& val)
+{
+  if (val.is_string ())
+    {
+      caseless_str tval = val.string_value ();
+
+      if (tval.compare ("default"))
+        val = get_default (name);
+      else if (tval.compare ("factory"))
+        val = get_factory_default (name);
+    }
+
+  if (error_state)
+    return;
+
+  rep->set (name, val);
+}
+
 static double
 make_handle_fraction (void)
 {
@@ -4412,9 +4520,35 @@
 
 DEFUN (set, args, ,
   "-*- texinfo -*-\n\
address@hidden {Built-in Function} {} set (@var{h}, @var{p}, @var{v}, 
@dots{})\n\
-Set the named property value or vector @var{p} to the value @var{v}\n\
-for the graphics handle @var{h}.\n\
address@hidden {Built-in Function} {} set (@var{h}, @var{property}, 
@var{value}, @dots{})\n\
address@hidden {Built-in Function} {} set (@var{h}, @var{properties}, 
@var{values})\n\
address@hidden {Built-in Function} {} set (@var{h}, @var{pv})\n\
+Set named property values for the graphics handle (or vector of graphics\n\
+handles) @var{h}.\n\
+There are three options how to give the property names and values:\n\
+\n\
address@hidden
address@hidden as a comma separated list of @var{property}, @var{value} pairs\n\
+\n\
+Here, each @var{property} is a string containing the property name, each\n\
address@hidden is a value of the appropriate type for the property.\n\
address@hidden as a cell array of strings @var{properties} containing property 
names\n\
+and a cell array @var{values} containing property values.\n\
+\n\
+In this case, the number of columns of @var{values} must match the number of\n\
+elements in @var{properties}.  The first column of @var{values} contains 
values\n\
+for the first entry in @var{properties} etc..  The number of rows of 
@var{values}\n\
+must be 1 or match the number of elements of @var{h}. In the first case, 
each\n\
+handle in @var{h} will be assigned the same values. In the latter case, the\n\
+first handle in @var{h} will be assigned the values from the first row of\n\
address@hidden and so on.\n\
address@hidden as a structure array @var{pv}\n\
+\n\
+Here, the field names of @var{pv} represent the property names, and the 
field\n\
+values give the property values.  In contrast to the previous case, all\n\
+elements of @var{pv} will be set in all handles in @var{h} independent of\n\
+the dimensions of @var{pv}.\n\
address@hidden itemize\n\
 @end deftypefn")
 {
   gh_manager::autolock guard;
@@ -4425,28 +4559,59 @@
 
   if (nargin > 0)
     {
+      // get vector of graphics handles
       ColumnVector hcv (args(0).vector_value ());
 
       if (! error_state)
         {
          bool request_drawnow = false;
 
+          // loop over graphics objects
           for (octave_idx_type n = 0; n < hcv.length (); n++) 
             {
               graphics_object obj = gh_manager::get_object (hcv(n));
 
               if (obj)
                 {
-                  obj.set (args.splice (0, 1));
-
-                  request_drawnow = true;
+                  if (nargin == 3 && args(1).is_cellstr () 
+                      && args(2).is_cell ())
+                    {
+                      if (args(2).cell_value ().rows () == 1)
+                        {
+                          obj.set (args(1).cellstr_value (),
+                                   args(2).cell_value (), 0);
+                        }
+                      else if (hcv.length () == args(2).cell_value ().rows ())
+                        {
+                          obj.set (args(1).cellstr_value (),
+                                   args(2).cell_value (), n);
+                        }
+                      else
+                        {
+                          error("set: number of graphics handles must match 
number of value rows (%d != %d)",
+                                hcv.length (), args(2).cell_value ().rows ());
+                          break;
+
+                        }
+                    }
+                  else if (nargin == 2 && args(1).is_map ())
+                    {
+                      obj.set (args(1).map_value ());
+                    }
+                  else
+                    {
+                      obj.set (args.splice (0, 1));
+                      request_drawnow = true;
+                    }
                 }
               else
                {
                  error ("set: invalid handle (= %g)", hcv(n));
                  break;
                }
-            }
+
+              request_drawnow = true;
+           }
 
          if (! error_state && request_drawnow)
            Vdrawnow_requested = true;
diff -r 0dd3c7a2ba19 -r 17d8e1a00902 src/graphics.h.in
--- a/src/graphics.h.in Sat Jul 04 13:19:20 2009 +0200
+++ b/src/graphics.h.in Sun Jul 05 21:42:49 2009 +0200
@@ -2049,6 +2049,14 @@
     rep->set (name, val);
   }
 
+  void set_value_or_default (caseless_str& name,
+                             octave_value& val);
+
+  void set (const Array<std::string> names, const Cell values,
+            octave_idx_type row);
+
+  void set (const Octave_map m);
+
   void set (const octave_value_list& args);
 
   void set_defaults (const std::string& mode) { rep->set_defaults (mode); }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]