comparison scripts/plot/private/__clabel__.m @ 17481:576cf0589c6d

Overhaul contour labeling functions. * scripts/plot/clabel.m: Use 'h', rather than 'retval', to match variables to documentation. Improve performance of input processing by using try/catch block and eliminating for loops. * scripts/plot/private/__clabel__.m: Get X and Y spacing in points from axis rather than assuming 4"x3" plot figure. Fix incorrect determination of axis limits if no contour handle provided. Rename loop vars i1, j1 to i,j. Performance improvement by using bsxfun over repmat. Use find to replace while loop (slow). Keep label rotation in the range [-90, 90] for readability.
author Rik <rik@octave.org>
date Tue, 24 Sep 2013 13:16:50 -0700
parents 1c89599167a6
children
comparison
equal deleted inserted replaced
17480:710b3d5fe966 17481:576cf0589c6d
21 ## Undocumented internal function. 21 ## Undocumented internal function.
22 ## @end deftypefn 22 ## @end deftypefn
23 23
24 function h = __clabel__ (c, v, hparent, label_spacing, z, varargin) 24 function h = __clabel__ (c, v, hparent, label_spacing, z, varargin)
25 25
26 ## FIXME: Why assume? Can get position in points directly from axis. 26 hax = ancestor (hparent, "axes");
27 ## Assume that the plot size is 4 by 3 inches. 27 units = get (hax, "units");
28 set (hax, "units", "points");
29 axpos = get (hax, "position");
30 set (hax, "units", units);
28 lims = axis (); 31 lims = axis ();
29 xspacing = 72 * 4 / abs (lims(1) - lims(2)); 32 xspacing = axpos(3) / (lims(2) - lims (1));
30 yspacing = 72 * 3 / abs (lims(3) - lims(4)); 33 yspacing = axpos(4) / (lims(4) - lims (3));
31 34
32 if (isscalar (hparent) && ishandle (hparent) 35 if (isscalar (hparent) && ishandle (hparent)
33 && strcmp (get (hparent, "type"), "hggroup")) 36 && strcmp (get (hparent, "type"), "hggroup"))
34 x = get (hparent, "xdata"); 37 x = get (hparent, "xdata");
35 xmin = min (x(:)); 38 xmin = min (x(:));
36 xmax = max (x(:)); 39 xmax = max (x(:));
37 y = get (hparent, "ydata"); 40 y = get (hparent, "ydata");
38 ymin = min (y(:)); 41 ymin = min (y(:));
39 ymax = max (y(:)); 42 ymax = max (y(:));
40 else 43 else
41 i1 = 1; 44 xmin = xmax = ymin = ymax = NaN;
42 while (i1 < length (c)) 45 i = 1;
43 clev = c(1,i1); 46 while (i < length (c))
44 clen = c(2,i1); 47 clen = c(2,i);
45 p = c(:, i1+1:i1+clen); 48 data = c(:, i+(1:clen));
46 49
47 xmin = min (c(1,:)); 50 xmin = min ([xmin, data(1,:)]);
48 xmax = max (c(1,:)); 51 xmax = max ([xmax, data(1,:)]);
49 ymin = min (c(2,:)); 52 ymin = min ([ymin, data(2,:)]);
50 ymax = max (c(2,:)); 53 ymax = max ([ymax, data(2,:)]);
51 54
52 i1 += clen+1; 55 i += clen+1;
53 endwhile 56 endwhile
54 endif 57 endif
55 58
56 ## Decode contourc output format and place labels. 59 ## Decode contourc output format and place labels.
57 i1 = 1;
58 h = []; 60 h = [];
59 while (i1 < length (c)) 61 i = 1;
60 clev = c(1,i1); 62 while (i < length (c))
61 clen = c(2,i1); 63 clev = c(1,i);
64 clen = c(2,i);
62 65
63 if (!isempty (v) && ! any (find (clev == v))) 66 if (! isempty (v) && ! any (v == clev))
64 i1 += clen+1; 67 i += clen+1;
65 continue; 68 continue;
66 endif 69 endif
67 70
68 p = c(:, i1+1:i1+clen) .* repmat ([xspacing; yspacing], 1, clen); 71 p = bsxfun (@times, c(:, i+(1:clen)), [xspacing; yspacing]);
69 d = sqrt (sumsq (diff (p, 1, 2))); 72 d = sqrt (sumsq (diff (p, 1, 2)));
70 cumd = cumsum (d); 73 cumd = cumsum (d);
71 td = sum (d); 74 td = cumd(end);
72 ntag = ceil (td / label_spacing); 75 ntag = ceil (td / label_spacing);
73 76
74 if (all (c(:,i1+1) == c(:,i1+clen))) 77 if (all (c(:,i+1) == c(:,i+clen)))
75 Spacing = td / ntag; 78 ## Closed contour
76 pos = Spacing / 2 + [0:ntag-1] * Spacing; 79 ## FIXME: This spreads the tags uniformly around the contour which
80 ## looks nice, but it does not respect the label_spacing attribute.
81 ## Should we follow user input, which can result in two labels being
82 ## quite close to each other?
83 spacing = td / ntag;
84 pos = spacing/2 + spacing*[0:ntag-1];
77 else 85 else
86 ## Open contour
78 pos = zeros (1, ntag); 87 pos = zeros (1, ntag);
79 pos(1) = (td - label_spacing * (ntag - 1)) ./ 2; 88 pos(1) = (td - label_spacing*(ntag - 1)) / 2;
80 pos(2:ntag) = pos(1) + [1:ntag-1] * label_spacing; 89 pos(2:ntag) = pos(1) + label_spacing*[1:ntag-1];
81 endif 90 endif
82 91
83 j1 = 2; 92 tlabel = sprintf ("%.5g", clev);
84 tlabel = sprintf ("%g", clev);
85 for i = 1 : ntag
86 tagpos = pos(i);
87 93
88 while (j1 < clen && cumd(j1) < tagpos) 94 for tagpos = pos
89 j1++; 95
90 endwhile 96 j = find (cumd > tagpos, 1);
91 tpos = sum (c(:,i1+j1-1:i1+j1), 2) ./ 2; 97 if (isempty (j))
98 j = clen;
99 endif
100 tpos = sum (c(:,i+j-1:i+j), 2) / 2;
92 101
93 if ( tpos(1) != xmin && tpos(1) != xmax 102 if ( tpos(1) != xmin && tpos(1) != xmax
94 && tpos(2) != ymin && tpos(2) != ymax) 103 && tpos(2) != ymin && tpos(2) != ymax)
95 trot = 180 / pi * atan2 (diff (c(2,i1+j1-1:i1+j1)), 104 trot = 180 / pi * atan2 (diff (c(2,i+j-1:i+j)),
96 diff (c(1,i1+j1-1:i1+j1))); 105 diff (c(1,i+j-1:i+j)));
97 106 if (abs (trot) > 90)
107 trot += 180;
108 endif
98 if (ischar (z)) 109 if (ischar (z))
99 ht = text (tpos(1), tpos(2), clev, tlabel, "rotation", trot, 110 ht = text (tpos(1), tpos(2), clev, tlabel, "rotation", trot,
100 "parent", hparent, "horizontalalignment", "center", 111 "horizontalalignment", "center", "userdata", clev,
101 "userdata", clev, varargin{:}); 112 "parent", hparent, varargin{:});
102 elseif (!isempty (z)) 113 elseif (! isempty (z))
103 ht = text (tpos(1), tpos(2), z, tlabel, "rotation", trot, 114 ht = text (tpos(1), tpos(2), z, tlabel, "rotation", trot,
104 "parent", hparent, "horizontalalignment", "center", 115 "horizontalalignment", "center", "userdata", clev,
105 "userdata", clev, varargin{:}); 116 "parent", hparent, varargin{:});
106 else 117 else
107 ht = text (tpos(1), tpos(2), tlabel, "rotation", trot, 118 ht = text (tpos(1), tpos(2), tlabel, "rotation", trot,
108 "parent", hparent, "horizontalalignment", "center", 119 "horizontalalignment", "center", "userdata", clev,
109 "userdata", clev, varargin{:}); 120 "parent", hparent, varargin{:});
110 endif 121 endif
111 h = [h; ht]; 122 h = [h; ht];
112 endif 123 endif
113 endfor 124 endfor
114 i1 += clen+1; 125 i += clen+1;
115 endwhile 126 endwhile
127
116 endfunction 128 endfunction
117 129