Skip to content

Commit 450f7c7

Browse files
committed
Initial commit of clabel_along an improved clabel for MATLAB
clabel_along( C, X, Y ) labels all contours in C, placing labels at the intersections between the contours and the curve in X, Y. Labels are rotated to align with the contour.
1 parent bf1e0dd commit 450f7c7

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# MATLAB contour labels along a curve
2+
3+
The placement of contour labels by MATLAB's `clabel` can be very
4+
frustrating. Some control can be gained with `'LabelSpacing'`, but
5+
`clabel` still has a mind of its own. The user can take full control
6+
with `'manual'` mode, but that doesn't work well in terms of
7+
automation and consistency.
8+
9+
This tool, `clabel_along`, allows the user to specify a curve along
10+
which to place the contour labels.
11+
12+
![Example clabel_along result](example.png)
13+
14+
## Example Use
15+
16+
[c, h] = contour( peaks );
17+
clabel_along( c, [1 37], [40 1] );
18+
clabel_along( c, [25 25], [37.5 30] );
19+
clabel_along( c, [27.5 27.5], [27 25] );
20+
21+
## Documentation
22+
23+
H = clabel_along( C, X, Y ) labels all contours in C, placing labels
24+
at the intersections between the contours and the curve in X, Y.
25+
Labels are rotated to align with the contour.
26+
27+
H = clabel_along( C, X, Y, V ) as above, but only labels the contours
28+
with levels contained in vector V. If V is empty (default), then all
29+
contours are labeled.
30+
31+
H = clabel_along( C, X, Y, V, ROTATE ) as above, but ROTATE is a
32+
boolean flag to enable label rotation. If ROTATE is TRUE (default),
33+
then the labels are rotated. The rotation angle is based on the slope
34+
of the contour at the intersection point and is corrected for the
35+
aspect ratio of the data and the plot.
36+
37+
If the data or plot aspect ratios change significantly after the call
38+
to clabel_along, the labels may not look properly aligned.
39+
40+
The graphics handles for all of the labels are returned in H.
41+
42+
## Dependencies
43+
44+
`clabel_along` requires Douglas Schwarz's
45+
[intersections](https://www.mathworks.com/matlabcentral/fileexchange/11837)
46+
routine to calculate the intersectinos between the curve and the contours.
47+
48+
## License
49+
50+
This software is Copyright (c) Rob McDonald 2021 and is released under the terms specified in the [license](license.txt).
51+

clabel_along.m

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
function h = clabel_along( c, x, y, varargin )
2+
%CLABEL_ALONG Label contours along a curve
3+
% H = CLABEL_ALONG( C, X, Y ) labels all contours in C, placing labels
4+
% at the intersections between the contours and the curve in X, Y.
5+
% Labels are rotated to align with the contour.
6+
%
7+
% H = CLABEL_ALONG( C, X, Y, V ) as above, but only labels the contours
8+
% with levels contained in vector V. If V is empty (default), then all
9+
% contours are labeled.
10+
%
11+
% H = CLABEL_ALONG( C, X, Y, V, ROTATE ) as above, but ROTATE is a
12+
% boolean flag to enable label rotation. If ROTATE is TRUE (default),
13+
% then the labels are rotated. The rotation angle is based on the slope
14+
% of the contour at the intersection point and is corrected for the
15+
% aspect ratio of the data and the plot.
16+
%
17+
% If the data or plot aspect ratios change significantly after the call
18+
% to CLABEL_ALONG, the labels may not look properly aligned.
19+
%
20+
% The graphics handles for all of the labels are returned in H.
21+
%
22+
% CLABEL_ALONG requires Douglas Schwarz's INTERSECTIONS routine to
23+
% calculate the intersectinos between the curve and the contours. It is
24+
% available from the Matlab File Exchange
25+
% https://www.mathworks.com/matlabcentral/fileexchange/11837
26+
%
27+
% Example:
28+
% [c, h] = contour( peaks );
29+
% CLABEL_ALONG( c, [1 37], [40 1] );
30+
% CLABEL_ALONG( c, [25 25], [37.5 30] );
31+
% CLABEL_ALONG( c, [27.5 27.5], [27 25] );
32+
%
33+
% See also CONTOUR, CONTOURF, CONTOURC, CLABEL, INTERSECTIONS, DASPECT, PBASPECT.
34+
35+
% Rob McDonald
36+
37+
% 25 March 2021 v. 1.0 -- Original version.
38+
39+
if ( ~exist( 'intersections', 'file' ) )
40+
error( 'clabel_along:intersections_not_found',...
41+
'clabel_along could not find intersections.\nIt is available from the MATLAB file exchange:\nhttps://www.mathworks.com/matlabcentral/fileexchange/11837' );
42+
end
43+
44+
% Handle values of contours to label. Empty for all (default).
45+
if ( nargin < 4 )
46+
v = [];
47+
else
48+
v = varargin{1};
49+
end
50+
51+
% Handle rotation disabling flag. True to rotate (default).
52+
if ( nargin < 5 )
53+
rotate = true;
54+
else
55+
rotate = varargin{2};
56+
end
57+
58+
% Grab aspect ratios to correct rotation
59+
% Data aspect ratio
60+
da = daspect();
61+
ard = da(2) / da(1);
62+
% Plot aspect ratio
63+
pa = pbaspect();
64+
arp = pa(2) / pa(1);
65+
66+
% Initialize handle array
67+
h = [];
68+
69+
% Loop over contours in c array
70+
nlimit = size( c , 2 );
71+
icont = 1;
72+
while( icont < nlimit )
73+
74+
% Pull out contour level and number of points in this contour line
75+
level = c( 1, icont );
76+
n = c( 2, icont );
77+
78+
% Only proceed for empty v (all) or contour in v
79+
if ( isempty( v ) || any( level == v ) )
80+
81+
% Pick off contour points
82+
xc = c( 1, icont+1:icont+n );
83+
yc = c( 2, icont+1:icont+n );
84+
85+
% Calculate the intersection points between the contours and the
86+
% guide curve using Douglas Schwarz's routine
87+
% https://www.mathworks.com/matlabcentral/fileexchange/11837
88+
[ xint, yint, iout ] = intersections( xc, yc, x, y );
89+
90+
% Loop over all intersections
91+
nint = length( xint );
92+
for iint = 1:nint
93+
th = 0;
94+
if ( rotate )
95+
% Calculate text rotation angle based on curve slope and
96+
% plot and data aspect ratios.
97+
iprev = floor( iout( iint ) );
98+
if ( iprev == length(xc) )
99+
iprev = iprev - 1;
100+
end
101+
inext = iprev + 1;
102+
103+
% Calculate aspect ratio adjusted slope
104+
dx = ( xc( inext ) - xc( iprev ) );
105+
dy = ( yc( inext ) - yc( iprev ) ) * ard * arp;
106+
107+
% Calculate angle
108+
th = atan( dy / dx ) * 180.0 / pi;
109+
end
110+
111+
hh = text( xint(iint), yint(iint), num2str( level ), 'rotation', th, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle' );
112+
113+
% Append text handle
114+
h = [h hh];
115+
end
116+
end
117+
118+
% Increment to next contour line
119+
icont = icont + n + 1;
120+
end

example.png

130 KB
Loading

0 commit comments

Comments
 (0)