No BSD License  

Highlights from
linspace_round

from linspace_round by Andy Eichelberger
Creates linearly spaced vector with "rounded" intervals.

linspace_round(min_val,max_val,n)
function [y] = linspace_round(min_val,max_val,n)
%LINSPACE_ROUND Creates linearly spaced vector with "rounded" intervals.
%   LINSPACE_ROUND(x1, x2) generates a row vector of 100 equally spaced
%   points that bound x1 and x2.  The spacing is chosen according to the
%   vector round_sample_ints, defined below.  At present, it is chosen such
%   that tenths and quarters are considered "rounded" fractions.
%
%   LINSPACE_ROUND(x1, x2, N) generates approximately N points that
%   bound x1 and x2.
%
%   Example: If X1 = 3.4, X2 = 7.5, N = 6,
%
%   then LINSPACE_ROUND(X1,X2,N) is [2.8 3.5 4.2 4.9 5.6 6.3 7.0 7.7]
%   (in words, choosing spacing of 0.7 will produce about 6 points that
%   bound X1 and X2)
%
%   This is useful in having automatically chosen data bins, contour
%   intervals, graph tick marks, etc., that are pleasing to the eye.
%
%   See also LINSPACE, COLON.

%   Author: Andy Eichelberger

if nargin == 2
    n = 100;
end

if ~isreal(min_val) || ~isreal(max_val)
    warning('linspace_round:bad_input','LINSPACE_ROUND has been passed an imaginary number')
end

% if min_val == max_val, just return n of that value
if min_val == max_val
    y = ones(1,n)*min_val;
    return
end

approx_sample_int = (max_val - min_val)/n;

% want to have spacing in 1/10s or 1/4s of the appropriate sig fig
round_sample_ints = [.1 .2 .25 .3 .4 .5 .6 .7 .75 .9 1];

sample_int = find_nearest(approx_sample_int,round_sample_ints);

% pick start and end values that are within the bounds
start_val = floor(min_val/sample_int)*sample_int;
end_val = ceil(max_val/sample_int)*sample_int;

y = start_val:sample_int:end_val;



% --------------------------------------------------------------------
function out_val = find_nearest(in_val,possible_vals)
%FIND_NEAREST Find nearest appropriate spacing.
%
%   See also LINSPACE_ROUND.

% check for zero since we'll be using log10
if in_val == 0
    out_val = 0;
    return
end

% find the exponent when put in scientific notation
exponent = floor(log10(abs(in_val)));

% divide it by (10 to that exponent plus one) so decimal preceeds the first sig fig
dec_val = in_val/10^(exponent+1);

% take absolute value so it can be compared against an all-positive vector of possible_vals
dec_val = abs(dec_val);

% prefer .1 to 1 for consistency with the other decimal values
if dec_val == 1
    dec_val = .1;
end

% find the closest match
difference = abs(possible_vals - dec_val);
nearest_ind = find(min(difference) == difference);

% if it's half way between two round_sample_ints, take the first
nearest_ind = nearest_ind(1);

% put the (10 to the exponent plus one) back in, shifting the decimal back to its original location
out_val = possible_vals(nearest_ind)*10^(exponent+1);

% multiply by sign(in_val) to cancel out the abs() above
out_val = out_val*sign(in_val);

Contact us at files@mathworks.com