comparison scripts/plot/private/__scatter__.m @ 17404:5e552cd9315a

Overhaul scatter family of functions * scripts/plot/module.mk: Remove unused function __color_str_rgb__.m from build. * scripts/plot/private/__color_str_rgb__.m: Remove unnecessary function. * scripts/plot/scatter.m: Put input validation first. Adjust indentation. * scripts/plot/scatter3.m: Put input validation first. Adjust indentation. Use htmp instead of tmp for temporary graphics handle. * scripts/plot/private/__scatter__.m: Update "markeredgecolor" in child patch objects when same property is updated in hggroup. Accept "fill" for "filled" for Matlab compatibility. Remove call to __color_str_rgb__. Don't bother saving graphics handle from __go_patch__ since it is never used. Use cellfun instead of for loop for input processing.
author Rik <rik@octave.org>
date Tue, 10 Sep 2013 16:31:34 -0700
parents 1c89599167a6
children a5de727e3795
comparison
equal deleted inserted replaced
17403:db8b90a56298 17404:5e552cd9315a
21 ## Undocumented internal function. 21 ## Undocumented internal function.
22 ## @end deftypefn 22 ## @end deftypefn
23 23
24 function hg = __scatter__ (varargin) 24 function hg = __scatter__ (varargin)
25 25
26 h = varargin{1}; 26 hax = varargin{1}; # We don't do anything with this. Could remove it.
27 nd = varargin{2}; 27 nd = varargin{2};
28 fcn = varargin{3}; 28 fcn = varargin{3};
29 x = varargin{4}(:); 29 x = varargin{4}(:);
30 y = varargin{5}(:); 30 y = varargin{5}(:);
31 istart = 6; 31
32 32 if (nd == 2)
33 if (nd == 3) 33 idx = isnan (x) | isnan (y);
34 x(idx) = [];
35 y(idx) = [];
36 z = zeros (length (x), 0);
37 istart = 6;
38 else
34 z = varargin{6}(:); 39 z = varargin{6}(:);
35 idx = isnan (x) | isnan (y) | isnan (z); 40 idx = isnan (x) | isnan (y) | isnan (z);
36 x (idx) = []; 41 x(idx) = [];
37 y (idx) = []; 42 y(idx) = [];
38 z (idx) = []; 43 z(idx) = [];
39 istart = 7; 44 istart = 7;
40 else 45 endif
41 idx = isnan (x) | isnan (y); 46
42 x (idx) = []; 47 firstnonnumeric = find (! cellfun ("isnumeric", varargin(istart:nargin)), 1);
43 y (idx) = []; 48 if (isempty (firstnonnumeric))
44 z = zeros (length (x), 0); 49 firstnonnumeric = Inf;
45 endif 50 else
46 51 firstnonnumeric += istart - 1;
47 firstnonnumeric = Inf; 52 endif
48 for i = istart:nargin
49 if (! isnumeric (varargin{i}))
50 firstnonnumeric = i;
51 break;
52 endif
53 endfor
54 53
55 if (istart <= nargin) 54 if (istart <= nargin)
56 s = varargin{istart}; 55 s = varargin{istart};
57 if (isempty (s) || ischar (s)) 56 if (isempty (s) || ischar (s))
58 s = 6; 57 s = 6;
64 s = 6; 63 s = 6;
65 endif 64 endif
66 65
67 if (istart <= nargin && firstnonnumeric > istart) 66 if (istart <= nargin && firstnonnumeric > istart)
68 c = varargin{istart}; 67 c = varargin{istart};
69 if (isvector (c)) 68 if (isvector (c) && columns (c) != 3)
70 if (columns (c) != 3) 69 c = c(:);
71 c = c(:); 70 endif
72 endif 71 ## Compare only first 4 letters of "fill" as that is what Matlab uses.
73 endif
74 elseif (firstnonnumeric == istart && ischar (varargin{istart}) 72 elseif (firstnonnumeric == istart && ischar (varargin{istart})
75 && ! strcmpi (varargin{istart}, "filled")) 73 && ! strncmpi (varargin{istart}, "filled", 4))
76 c = varargin{istart}; 74 c = varargin{istart};
77 firstnonnumeric++; 75 firstnonnumeric++;
78 else 76 else
79 c = []; 77 c = [];
80 endif 78 endif
84 have_marker = false; 82 have_marker = false;
85 marker = "o"; 83 marker = "o";
86 iarg = firstnonnumeric; 84 iarg = firstnonnumeric;
87 while (iarg <= nargin) 85 while (iarg <= nargin)
88 arg = varargin{iarg++}; 86 arg = varargin{iarg++};
89 if (ischar (arg) && strncmpi (arg, "filled", 6)) 87 if (ischar (arg) && strncmpi (arg, "filled", 4))
90 filled = true; 88 filled = true;
91 elseif ((ischar (arg) || iscell (arg)) && ! have_marker) 89 elseif ((ischar (arg) || iscell (arg)) && ! have_marker)
92 [linespec, valid] = __pltopt__ (fcn, arg, false); 90 [linespec, valid] = __pltopt__ (fcn, arg, false);
93 if (valid) 91 if (valid)
94 have_marker = true; 92 have_marker = true;
95 marker = linespec.marker; 93 marker = linespec.marker;
96 if (strncmp (marker, "none", 4)) 94 if (strcmp (marker, "none"))
97 marker = "o"; 95 marker = "o";
98 elseif (isempty (marker)) 96 elseif (isempty (marker))
99 have_marker = false; 97 have_marker = false;
100 [dummy, marker] = __next_line_style__ (); 98 [~, marker] = __next_line_style__ ();
101 endif 99 endif
102 else 100 else
103 error ("%s: invalid linespec", fcn); 101 error ("%s: invalid linespec", fcn);
104 endif 102 endif
105 else 103 else
114 c = __next_line_color__ (); 112 c = __next_line_color__ ();
115 endif 113 endif
116 114
117 hg = hggroup (); 115 hg = hggroup ();
118 newargs = __add_datasource__ (fcn, hg, {"x", "y", "z", "c", "size"}, 116 newargs = __add_datasource__ (fcn, hg, {"x", "y", "z", "c", "size"},
119 newargs{:}); 117 newargs{:});
120 118
121 addproperty ("xdata", hg, "data", x); 119 addproperty ("xdata", hg, "data", x);
122 addproperty ("ydata", hg, "data", y); 120 addproperty ("ydata", hg, "data", y);
123 addproperty ("zdata", hg, "data", z); 121 addproperty ("zdata", hg, "data", z);
124 if (ischar (c)) 122 if (ischar (c))
125 addproperty ("cdata", hg, "data", __color_str_rgb__ (c)); 123 ## For single explicit color, cdata is unused
124 addproperty ("cdata", hg, "data", []);
126 else 125 else
127 addproperty ("cdata", hg, "data", c); 126 addproperty ("cdata", hg, "data", c);
128 endif 127 endif
129 addproperty ("sizedata", hg, "data", s); 128 addproperty ("sizedata", hg, "data", s);
130 addlistener (hg, "xdata", @update_data); 129 addlistener (hg, "xdata", @update_data);
144 endif 143 endif
145 144
146 if (one_explicit_color) 145 if (one_explicit_color)
147 for i = 1 : numel (x) 146 for i = 1 : numel (x)
148 if (filled) 147 if (filled)
149 h = __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:), 148 __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
150 "faces", 1, "vertices", [x(i), y(i), z(i,:)], 149 "faces", 1, "vertices", [x(i), y(i), z(i,:)],
151 "facecolor", "none", "edgecolor", "none", 150 "facecolor", "none", "edgecolor", "none",
152 "marker", marker, "markersize", s(i), 151 "marker", marker, "markersize", s(i),
153 "markeredgecolor", c, "markerfacecolor", c, 152 "markeredgecolor", c, "markerfacecolor", c,
154 "linestyle", "none"); 153 "linestyle", "none");
155 else 154 else
156 h = __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:), 155 __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
157 "faces", 1, "vertices", [x(i), y(i), z(i,:)], 156 "faces", 1, "vertices", [x(i), y(i), z(i,:)],
158 "facecolor", "none", "edgecolor", "none", 157 "facecolor", "none", "edgecolor", "none",
159 "marker", marker, "markersize", s(i), 158 "marker", marker, "markersize", s(i),
160 "markeredgecolor", c, "markerfacecolor", "none", 159 "markeredgecolor", c, "markerfacecolor", "none",
161 "linestyle", "none"); 160 "linestyle", "none");
162 endif 161 endif
163 endfor 162 endfor
164 else 163 else
165 if (rows (c) == 1) 164 if (rows (c) == 1)
166 c = ones (rows (x), 1) * c; 165 c = repmat (c, rows (x), 1);
167 endif 166 endif
168 for i = 1 : numel (x) 167 for i = 1 : numel (x)
169 if (filled) 168 if (filled)
170 h = __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:), 169 __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
171 "faces", 1, "vertices", [x(i), y(i), z(i,:)], 170 "faces", 1, "vertices", [x(i), y(i), z(i,:)],
172 "facecolor", "none", "edgecolor", "none", 171 "facecolor", "none", "edgecolor", "none",
173 "marker", marker, "markersize", s(i), 172 "marker", marker, "markersize", s(i),
174 "markeredgecolor", "none", 173 "markeredgecolor", "none",
175 "markerfacecolor", "flat", 174 "markerfacecolor", "flat",
176 "cdata", c(i,:), "facevertexcdata", c(i,:), 175 "cdata", c(i,:), "facevertexcdata", c(i,:),
177 "linestyle", "none"); 176 "linestyle", "none");
178 else 177 else
179 h = __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:), 178 __go_patch__ (hg, "xdata", x(i), "ydata", y(i), "zdata", z(i,:),
180 "faces", 1, "vertices", [x(i), y(i), z(i,:)], 179 "faces", 1, "vertices", [x(i), y(i), z(i,:)],
181 "facecolor", "none", "edgecolor", "none", 180 "facecolor", "none", "edgecolor", "none",
182 "marker", marker, "markersize", s(i), 181 "marker", marker, "markersize", s(i),
183 "markeredgecolor", "flat", 182 "markeredgecolor", "flat",
184 "markerfacecolor", "none", 183 "markerfacecolor", "none",
185 "cdata", c(i,:), "facevertexcdata", c(i,:), 184 "cdata", c(i,:), "facevertexcdata", c(i,:),
186 "linestyle", "none"); 185 "linestyle", "none");
187
188 endif 186 endif
189 endfor 187 endfor
190 endif 188 endif
191 189
192 else 190 else
193 191
194 ## For larger numbers of points, we split the points by common color. 192 ## For larger numbers of points, we split the points by common color.
195 193
196 vert = [x, y, z]; 194 vert = [x, y, z];
197 if (one_explicit_color) 195 if (one_explicit_color)
198 h = render_size_color (hg, vert, s, c, marker, filled, true); 196 render_size_color (hg, vert, s, c, marker, filled, true);
199 else 197 else
200 if (rows (c) == 1) 198 if (rows (c) == 1)
201 c = ones (rows (x), 1) * c; 199 c = repmat (c, rows (x), 1);
202 endif 200 endif
203 ## We want to group points by colour. So first get all the unique colours 201 ## We want to group points by color. So first get all the unique colors
204 [cc, ~, c_to_cc] = unique (c, "rows"); 202 [cc, ~, c_to_cc] = unique (c, "rows");
205 203
206 for i = 1:rows (cc) 204 for i = 1 : rows (cc)
207 ## Now for each possible unique colour, get the logical index of 205 ## Now for each possible unique color, get the logical index of
208 ## points that correspond to that colour 206 ## points that correspond to that color
209 idx = (i == c_to_cc); 207 idx = (i == c_to_cc);
210 if (isscalar (s)) 208 if (isscalar (s))
211 h = render_size_color (hg, vert(idx, :), s, c(idx,:), 209 render_size_color (hg, vert(idx, :), s, c(idx,:),
212 marker, filled, true); 210 marker, filled, true);
213 else 211 else
214 h = render_size_color (hg, vert(idx, :), s(idx), c(idx,:), 212 render_size_color (hg, vert(idx, :), s(idx), c(idx,:),
215 marker, filled, true); 213 marker, filled, true);
216 endif 214 endif
217 endfor 215 endfor
218 216
219 endif 217 endif
257 set (hg, newargs{:}); 255 set (hg, newargs{:});
258 endif 256 endif
259 257
260 endfunction 258 endfunction
261 259
262 function h = render_size_color (hg, vert, s, c, marker, filled, isflat) 260 function render_size_color (hg, vert, s, c, marker, filled, isflat)
263 if (isscalar (s)) 261 if (isscalar (s))
264 x = vert(:,1); 262 x = vert(:,1);
265 y = vert(:,2); 263 y = vert(:,2);
266 z = vert(:,3:end); 264 z = vert(:,3:end);
267 toolkit = get (ancestor (hg, "figure"), "__graphics_toolkit__"); 265 toolkit = get (ancestor (hg, "figure"), "__graphics_toolkit__");
268 ## Does gnuplot only support triangles with different vertex colors ? 266 ## Does gnuplot only support triangles with different vertex colors ?
269 ## TODO - Verify gnuplot can only support one color. If RGB triplets 267 ## TODO: Verify gnuplot can only support one color. If RGB triplets
270 ## can be assigned to each vertex, then fix __go_draw_axe__.m 268 ## can be assigned to each vertex, then fix __go_draw_axes__.m
271 gnuplot_hack = (numel (x) > 1 && columns (c) == 3 269 gnuplot_hack = (numel (x) > 1 && columns (c) == 3
272 && strcmp (toolkit, "gnuplot")); 270 && strcmp (toolkit, "gnuplot"));
273 if (ischar (c) || ! isflat || gnuplot_hack) 271 if (ischar (c) || ! isflat || gnuplot_hack)
274 if (filled) 272 if (filled)
275 h = __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z, 273 __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z,
276 "faces", 1:numel (x), "vertices", vert, 274 "faces", 1:numel (x), "vertices", vert,
277 "facecolor", "none", "edgecolor", "none", 275 "facecolor", "none", "edgecolor", "none",
278 "marker", marker, 276 "marker", marker,
279 "markeredgecolor", "none", 277 "markeredgecolor", "none",
280 "markerfacecolor", c(1,:), 278 "markerfacecolor", c(1,:),
281 "markersize", s, "linestyle", "none"); 279 "markersize", s, "linestyle", "none");
282 else 280 else
283 h = __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z, 281 __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z,
284 "faces", 1:numel (x), "vertices", vert, 282 "faces", 1:numel (x), "vertices", vert,
285 "facecolor", "none", "edgecolor", "none", 283 "facecolor", "none", "edgecolor", "none",
286 "marker", marker, 284 "marker", marker,
287 "markeredgecolor", c(1,:), 285 "markeredgecolor", c(1,:),
288 "markerfacecolor", "none", 286 "markerfacecolor", "none",
289 "markersize", s, "linestyle", "none"); 287 "markersize", s, "linestyle", "none");
290 endif 288 endif
291 else 289 else
292 if (filled) 290 if (filled)
293 h = __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z, 291 __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z,
294 "faces", 1:numel (x), "vertices", vert, 292 "faces", 1:numel (x), "vertices", vert,
295 "facecolor", "none", "edgecolor", "none", 293 "facecolor", "none", "edgecolor", "none",
296 "marker", marker, "markersize", s, 294 "marker", marker, "markersize", s,
297 "markeredgecolor", "none", 295 "markeredgecolor", "none",
298 "markerfacecolor", "flat", 296 "markerfacecolor", "flat",
299 "cdata", c, "facevertexcdata", c, 297 "cdata", c, "facevertexcdata", c,
300 "linestyle", "none"); 298 "linestyle", "none");
301 else 299 else
302 h = __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z, 300 __go_patch__ (hg, "xdata", x, "ydata", y, "zdata", z,
303 "faces", 1:numel (x), "vertices", vert, 301 "faces", 1:numel (x), "vertices", vert,
304 "facecolor", "none", "edgecolor", "none", 302 "facecolor", "none", "edgecolor", "none",
305 "marker", marker, "markersize", s, 303 "marker", marker, "markersize", s,
306 "markeredgecolor", "flat", 304 "markeredgecolor", "flat",
307 "markerfacecolor", "none", 305 "markerfacecolor", "none",
308 "cdata", c, "facevertexcdata", c, 306 "cdata", c, "facevertexcdata", c,
309 "linestyle", "none"); 307 "linestyle", "none");
310 endif 308 endif
311 endif 309 endif
312 else 310 else
313 ## FIXME: round the size to one decimal place. It's not quite right, though. 311 ## Round size to one decimal place.
314 [ss, ~, s_to_ss] = unique (ceil (s*10) / 10); 312 [ss, ~, s_to_ss] = unique (ceil (s*10) / 10);
315 for i = 1:rows (ss) 313 for i = 1:rows (ss)
316 idx = (i == s_to_ss); 314 idx = (i == s_to_ss);
317 h = render_size_color (hg, vert(idx,:), ss(i), c, 315 render_size_color (hg, vert(idx,:), ss(i), c,
318 marker, filled, isflat); 316 marker, filled, isflat);
319 endfor 317 endfor
320 endif 318 endif
321 endfunction 319 endfunction
322 320
323 function update_props (h, d) 321 function update_props (h, d)
324 lw = get (h, "linewidth"); 322 lw = get (h, "linewidth");
325 m = get (h, "marker"); 323 m = get (h, "marker");
326 fc = get (h, "markerfacecolor"); 324 fc = get (h, "markerfacecolor");
327 ec = get (h, "markeredgecolor"); 325 ec = get (h, "markeredgecolor");
328 kids = get (h, "children"); 326 kids = get (h, "children");
329 327
330 for i = 1 : numel (kids) 328 set (kids, "linewidth", lw, "marker", m,
331 set (kids (i), "linewidth", lw, "marker", m, "markerfacecolor", fc, 329 "markerfacecolor", fc, "markeredgecolor", ec);
332 "edgecolor", ec);
333 endfor
334 endfunction 330 endfunction
335 331
336 function update_data (h, d) 332 function update_data (h, d)
337 x1 = get (h, "xdata"); 333 x = get (h, "xdata");
338 y1 = get (h, "ydata"); 334 y = get (h, "ydata");
339 z1 = get (h, "zdata"); 335 z = get (h, "zdata");
340 c1 = get (h, "cdata"); 336 c = get (h, "cdata");
341 if (!ischar (c1) && rows (c1) == 1) 337 if (rows (c) == 1)
342 c1 = repmat (c1, numel (x1), 1); 338 c = repmat (c, numel (x), 1);
343 endif 339 endif
344 size1 = get (h, "sizedata"); 340 s = get (h, "sizedata");
345 if (numel (size1) == 1) 341 if (numel (s) == 1)
346 size1 = repmat (size1, numel (x1), 1); 342 s = repmat (s, numel (x), 1);
347 endif 343 endif
348 hlist = get (h, "children"); 344 hlist = get (h, "children");
349 if (ischar (c1)) 345
350 if (isempty (z1)) 346 if (isempty (z))
351 for i = 1 : length (hlist) 347 for i = 1 : length (hlist)
352 set (hlist(i), "vertices", [x1(i), y1(i)], "cdata", c1, 348 set (hlist(i), "vertices", [x(i), y(i)],
353 "markersize", size1(i)); 349 "cdata", reshape (c(i,:),[1, size(c)(2:end)]),
354 endfor 350 "facevertexcdata", c(i,:),
355 else 351 "markersize", s(i));
356 for i = 1 : length (hlist) 352 endfor
357 set (hlist(i), "vertices", [x1(i), y1(i), z1(i)], "cdata", c1, 353 else
358 "markersize", size1(i)); 354 for i = 1 : length (hlist)
359 endfor 355 set (hlist(i), "vertices", [x(i), y(i), z(i)],
360 endif 356 "cdata", reshape (cd(i,:),[1, size(cd)(2:end)]),
361 else 357 "facevertexcdata", cd(i,:),
362 if (isempty (z1)) 358 "markersize", s(i));
363 for i = 1 : length (hlist) 359 endfor
364 set (hlist(i), "vertices", [x1(i), y1(i)], "cdata", 360 endif
365 reshape (c1(i,:),[1, size(c1)(2:end)]), 361
366 "facevertexcdata", c1(i,:),
367 "markersize", size1(i));
368 endfor
369 else
370 for i = 1 : length (hlist)
371 set (hlist(i), "vertices", [x1(i), y1(i), z1(i)], "cdata",
372 reshape (c1(i,:),[1, size(c1)(2:end)]),
373 "facevertexcdata", c1(i,:),
374 "markersize", size1(i));
375 endfor
376 endif
377 endif
378 endfunction 362 endfunction
379 363