Mercurial > hg > octave-lyh
comparison scripts/plot/private/__scatter__.m @ 17412: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
17411:db8b90a56298 | 17412: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 |