📄 m_vec.m
字号:
function [hp, ht] = mvec(s, x, y, varargin) % and color, etc% M_VEC Draws fancy arrows/quiverplots on a map.% [HP, HT]=M_VEC(S,LONG,LAT,VARARGIN) draws arrows as a patch % object on a map created by the M_Map package.% HP: handle to the patch object% HT: handle to text object if this is a key; see below.% S: scale factor, arrow data units per inch.% It is based on the figure PaperPosition, so be% sure to set this (e.g. via "landscape" or "portrait")% before calling m_vec.% LONG,LAT: longitude, latitude of the arrows% LONG and LAT must have the same dimensions, but can be% scalars or vectors; if scalars, multiple arrows can% be plotted at a single location.% VARARGIN can consist of any of the following:% U,V U,V,C Z,U,V,C% followed by optional arrow parameters,% followed by optional patch parameters.% U,V are vectors containing the east and north components% of the arrows.% C is an optional colorspec for all arrows, or an% array of CData, one value per arrow.% Defaults to black.% Z is a height in axes data units: this is subject% to future modification or omission, and% is probably not useful now as-is.% optional arrow parameters: keyword-value pairs, shown% here with default values:% 'headangle',60 degrees: angle of arrow tip% 'headwidth',NaN points: direct specification of% width, instead of headangle% 'headlength',5 points: length of tip; set to 0% to omit arrowhead entirely% 'shaftwidth',1 points: width of arrow shaft% 'centered', 'no' 'yes' to make x,y the arrow% center instead of its tail% 'key', '' make a labelled horizontal arrow% if the string is not empty;% then the string labels the% arrow, and the second argument% returned, ht, is the handle of% the string.% optional patch parameters: any valid patch properties% may be specified here; they are passed directly% to the patch function.%% M_VEC called without any parameters generates a demonstration plot.%% Mon 98/02/16 Eric Firing, efiring@soest.hawaii.edu%% 6/Nov/00 - eliminate returned stuff if ';' neglected (thx to D Byrne)% 2/May/01 - small bug fix (thx to Pierre Jaccard)% 7/jun/06 - arrows near boundaries were not done correctly - now fixed.global MAP_PROJECTION% Have to have initialized a map firstif nargin==0, % demo % demvec.m % This is a demonstration of m_vec. % Sun 98/02/22 Eric Firing % Set up the figure and axes at the start, so that the vector lengths % will come out right when the figure is printed: orient tall % Main axes, for the map. ha1 = axes; pos = get(ha1,'position'); pos1 = pos; pos1(4) = pos1(4) - 0.1; pos1(2) = pos1(2) + 0.1; set(ha1,'position',pos1) % Colormap axes. Make them smaller than for the default colormap. pos2 = [0.3 0 0.4 0]; pos2(2) = pos(2); pos2(4) = 0.02; % This positioning of the colormap is actually not very good as % printed, but I am not going to fiddle with it any more now. % This is just a typical difficulty with normalized coordinates % combined with fixed DataAspectRatio; if % something looks reasonable on the screen, it is likely to look % wrong when printed. ha2 = axes('position', pos2); axes(ha1); % Back to the main axes. m_proj('ortho','lat',48','long',-123', 'rad', 10, ... 'rec', 'off' ); m_coast('patch',[0.9 0.95 0.9]); m_grid('linest','-','xtick',[-135:5:-110]); title('Demonstration of m\_vec') %% The following form, centered and without heads, is suitable for %% the square roots of the principle axes of variance ellipses, %% for example. Color is given as a single RGB triplet; if it were %% given as an array of triplets, the two lines could be different %% colors; unfortunately, as of Matlab 5.1, if you do this the plot %% will be forced into Zbuffer mode with the warning: %% "RGB color data not yet supported in Painter's mode" %% This example also illustrates specification of a black patch %% boundary, via direct patch property specifications following any %% vector parameter options. hpv1 = m_vec(100, [-133 -133], [49 49], [0 50], [100 0.0],... [0.7 0.8 0.9],'centered','yes', ... 'shaftwidth', 5, 'headlength', 0,... 'EdgeColor','k'); %% Here are three vectors, no color specified, all properties defaulted. hpv2 = m_vec(100, [-128 -128 -128], [46 46 46], ... [0 25*sqrt(2) 50], [50 25*sqrt(2) 0]); incs = (1:20)/20; vlat = 42 + incs*3; vlon = -127 - incs*2; uu = 50*sin(incs*2*pi); vv = 50*cos(incs*2*pi); %% This simulates a set of vectors such as currents measured %% with an ADCP along a cruise track. Color is specified by letter, %% in this case. The arrows and heads are about as skinny as they %% can reasonably be. hpv3 = m_vec(100, vlon, vlat, uu, vv, 'm', ... 'shaftwidth', 0.2, 'headlength', 2.5); %% Now let's make a similar vectors, but with colors based on the %% colormap, simulating SST, for example: vlon = vlon - 3; sst = 12 - incs * 4; hpv4 = m_vec(100, vlon, vlat, uu, vv, sst); colorbar(ha2); axes(ha2); xlabel('SST'); axes(ha1); %% These vectors will not show up well on the screen because they %% have no edges, but they will print adequately. There does not %% seem to be any easy way to get around this; I would have to %% completely change the way the patches are specified. Ordinarily, %% one would probably use fatter than default vectors with this %% method anyway, so that the colors are clear when printed; and in %% this case the screen display will look OK also. %% Key: Note that it can be on or off the map. The vector and %% text are the same color by default. Handles to both the vector %% (patch) and the label (text) are returned so that you can %% change the font, color, etc. [hpv5, htv5] = m_vec(100, -115, 38, 50, 0, 'b', 'key', '50 cm s^{-1}'); set(htv5,'FontSize',8); returnendif isempty(MAP_PROJECTION), error('No Map Projection initialized - call M_PROJ first!');end;% Default arrow parameters:centered = 0;headlength = 5/72;headwidth = NaN;headangle = 40;shaftwidth = 1/72;c = 'k';key = '';clip = 'on'; % except for the keyif nargin < 5, % Minimum: s,x,y,u,v help('mvec'); error('not enough input arguments');endUVperIn = s;x = x(:);y = y(:);%% Begin the slightly complicated parsing of arguments. This%% could probably be done more efficiently and elegantly.% One cause of complexity is that the optional argument c% could be either character or numeric.keyvars = {}; % This will hold keyword/value pairs.nvarargin = length(varargin);% Find the index of the first string argument in varargin.istr0 = 0;for ii = 1:nvarargin if ischar(varargin{ii}), istr0 = ii; break, endendif istr0 > 0, % There are strings. if rem(nvarargin - istr0, 2) == 0, % an odd number c = varargin{istr0}; % should be a colorspec string istr0 = istr0 + 1; end % istr0: start of keyword/value pairs. n_numeric = istr0 - 1; %Actually, numeric or colorspec. keyvars = varargin(istr0:nvarargin); finished = 0; while ~isempty(keyvars) & ~finished, kv = lower(keyvars{1}); value = keyvars{2}; if strcmp(kv, 'headlength') headlength = value/72; elseif strcmp(kv, 'headwidth') headwidth = value/72; elseif strcmp(kv, 'headangle') headangle = value; elseif strcmp(kv, 'shaftwidth') shaftwidth = value/72; elseif strcmp(kv, 'centered') & lower(value(1)) == 'y', centered = 1; elseif strcmp(kv, 'key') key = value; clip = 'off'; % Can put key outside the map. else finished = 1; % no match; break out end if ~finished, keyvars(1:2) = []; end endelse n_numeric = nvarargin;end% Calculate the headwidth if it is not given explicitly:if isnan(headwidth) & headangle < 170 & headangle > 0 headwidth = headlength * tan(headangle*pi/180);endheadwidth = max([headwidth; shaftwidth]);if n_numeric == 2 | n_numeric == 3, u = varargin{1}(:); v = varargin{2}(:); if n_numeric == 3, c = varargin{3}; end z = zeros(size(u));elseif n_numeric == 4, z = varargin{1}(:); u = varargin{2}(:); v = varargin{3}(:); c = varargin{4};else help('mvec') error('not enough numeric arguments')end[nr,nc] = size(c);if nr == 1 & nc == length(u) & (nc ~= 3 | (any(c<=1) | any(c>=0))), c = c(:);end% c could be a 1x3 colorspecif (length(x) == 1 & length(y) == 1 & length(u) > 1) x = x(ones(size(u))); y = y(ones(size(u)));end%% End of input argument parsing.OrigAxUnits = get(gca,'Units');if OrigAxUnits(1:3) == 'nor' OrigPaUnits = get(gcf, 'paperunits'); set(gcf, 'paperunits', 'inches'); figposInches = get(gcf, 'paperposition'); set(gcf, 'paperunits', OrigPaUnits); axposNor = get(gca, 'position'); axWidLenInches = axposNor(3:4) .* figposInches(3:4);else set(gca, 'units', 'inches'); axposInches = get(gca, 'position'); set(gca, 'units', OrigAxUnits); axWidLenInches = axposInches(3:4);end% Multiply inches by the following to get data units:scX = diff(get(gca, 'XLim'))/axWidLenInches(1);scY = diff(get(gca, 'YLim'))/axWidLenInches(2);sc = max([scX;scY]); %max selects the dimension limited by % the plot box.Width = shaftwidth*sc;HeadWidth = headwidth*sc;HeadLength = headlength*sc;uvmag = abs(u + i*v);% Arrow lengths in plot data units:L = uvmag*sc/UVperIn;% base of arrows. Don't plot if outside boundaries (except for keys for which clip is off)[xs, ys] = m_ll2xy(x,y, 'clip', clip);%[xsp, ysp] = m_ll2xy(x+0.1*u./uvmag, y+0.1*v.*cos(y*pi/180)./uvmag, 'clip', clip);% Vector angles in the Cartesian data-unit system of m_map:%Ang = angle( (xsp-xs) + i*(ysp-ys) );% ABove angle calc could fail when arrows were near boundaries. Replace with this.% Now we calculate angles. Use a small offset, and keep clipping off to prevent odd things% happening.% - RP 7/Jun/06[xsp, ysp] = m_ll2xy([x x+0.00001*u./uvmag]',[y y+0.00001*v.*cos(y*pi/180)./uvmag]' , 'clip', 'off');Ang = angle( diff(xsp)' + i*diff(ysp)' );if ~isempty(key), Ang = 0; endnvec = length(L);Zero = zeros(nvec,1);One = ones(nvec,1);% Normal arrow dimensions:HL = Zero+HeadLength;HW = Zero+HeadWidth;W = Zero+Width;% Distinguish zero-length vectors from non-zero:mm = (L < 100*eps);i_zero = find(mm);i_nonzero = find(~mm);% Don't plot if length is zero.if ~isempty(i_zero) HL(i_zero) = NaN; HW(i_zero) = NaN; W(i_zero) = NaN;endif ~isempty(i_nonzero) ii = i_nonzero; if HeadLength == 0, %% square end; no arrowhead W(ii) = Width; HW(ii) = Width; HL(ii) = Zero(ii); % Thanks for Pierre Jaccard for this fix else % If the arrow length is less than the headlength, % omit the arrow shaft and just plot a head scaled % to the length. i_short = ii( find(L(ii) < HeadLength) ); W(i_short) = 0; HL(i_short) = L(i_short); HW(i_short) = HL(i_short) * (HeadWidth/HeadLength); endend% Just a change of variable names for historical reasons:Y = ys;X = xs;% It is not clear whether non-zero elevations will be useful;% that depends on whether the entire m_map system will work% with 3-D views, as in making a surface plot of topography.% Then one might want to have a current profile represented% as a stack of vectors at appropriate heights above the topog.Z = z(:);Xzero = Zero;if centered, Xzero = -L/2;endnV = 7*nvec; % number of Vertices: 7 per arrow.Vert = zeros(nvec,3);Vert(1:7:nV,:) = [Xzero, W/2, Z ]; % back corner of shaftVert(2:7:nV,:) = Vert(1:7:nV,:) + ... [(L-HL), Zero, Zero]; % shaft-head junctionVert(3:7:nV,:) = Vert(2:7:nV,:) + ... [Zero, (HW-W)/2, Zero]; % point of barbVert(4:7:nV,:) = [Xzero + L, Zero, Z]; % tip of arrow%% This could be done more efficiently with fancier indexing, but%% it is probably not a bottleneck, hence not worth the trouble.% Reflect the top half to get the bottom half.% First replicate:Vert(5:7:nV,:) = Vert(3:7:nV,:);Vert(6:7:nV,:) = Vert(2:7:nV,:);Vert(7:7:nV,:) = Vert(1:7:nV,:);% Then negate y to reflect:Vert(5:7:nV,2) = -Vert(5:7:nV,2);Vert(6:7:nV,2) = -Vert(6:7:nV,2);Vert(7:7:nV,2) = -Vert(7:7:nV,2);% Make an index array for operating on all vertices of each vector:ii = (1:nvec);ii = ii(ones(7,1),:);ii = ii(:);%% Rotate:Vxy = exp(i*Ang(ii)).*(Vert(:,1) + i*Vert(:,2));%% Translate:Vxy = Vxy + X(ii) + i*Y(ii);%%Vert(:,1) = real(Vxy);Vert(:,2) = imag(Vxy);Faces = [1:nV].'; %TopFaces = reshape(Faces,7,nvec).';% Extremely narrow patches don't show up on the screen (although they seem% to be printed OK) when EdgeColor is 'none', so when the arrows are all% the same color, set the EdgeColor to be the same as FaceColor.% Set clip off here so arrows are complete - RP 7/Jun/06hp = patch('Faces', Faces, 'Vertices', Vert, 'tag', 'm_vec','clip','off');if ischar(c) | (size(c,1) == 1 & size(c,2) == 3), set(hp, 'EdgeColor', c, 'FaceColor', c, 'LineWidth', 0.1);else set(hp, 'EdgeColor', 'none', 'FaceColor','Flat', ... 'FaceVertexCdata', c);endif ~isempty(keyvars) set(hp, keyvars{:});endif ~isempty(key) ht = text(X(1), Y(1)-0.5*HW, Z(1), key, ... 'color', c, 'horiz','left','vert','top', 'tag','m_vec', ... 'clipping','off'); set(hp,'clipping','off')else ht = [];endif nargout==0 clear hp htend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -