【Matlab绘图】【笔记】【线性图】

line_fewer_markers.m

% line_fewer_markers - line with controlled amount of markers and correct legend behaviour
% 
%   LINE_FEWER_MARKERS(X,Y,NUM_MARKERS) adds the line in vectors X and Y to the current axes
%   with exactly NUM_MARKERS markers drawn.
% 
%   LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...) plots the data
%   stored in the vectors X and Y.
%
%   LINE_FEWER_MARKERS returns handles to LINE/MARKER objects.
% 
%   [H1,H2,H3] = LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...) 
%   performs the actions as above and returns the handles of all the plotted lines/markers.
%   H1    = handle to the main marker(1 point); it may be put in array and used with legend
%   H2    = handle to the continuous line (as in H2=plot())
%   H3    = handle to all other markers
%
%   Property/Value pairs and descriptions:
%       
%       Spacing    - 'x'      : ordinary uniform along x
%                  - 'curve'  : equal lengths along curve y(x)
%                  - 'logx'   : to be used with logarithmic x scale
% 
%       LockOnMax  - 0        : first marker on 1st data point
%                  - 1        : offset all markers such that one marker on first max of y(x)
% 
%       LegendLine - 'on'     : default, reproduce linestyle also in legend
%                  - 'off'    : shows only marker in legend
% 
%       LineSpec: same as for LINE: LineStyle,LineWidth,Marker,MarkerSize,MarkerFaceColor...
%
%
%   Example: plot 3 curves with 9,9, and 15 markers each, using different input styles
% 
%      figure; hold on;
%      t  = 0:0.005:pi;
%      line_fewer_markers(t*180/pi,cos(t) ,9,  '--bs','spacing','curve');
%      line_fewer_markers(t*180/pi,sin(t) ,9,  '-.ro','MarkerFaceColor','g', ...
%                                                     'markersize',6,'linewidth',2);
%      grey1 = [1 1 1]*0.5;
%      line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','marker','h','color',grey1, ...
%                                    'markerfacecolor',grey1,'linewidth',2,'LockOnMax',1);
%      leg = legend('cos','sin','sin*cos','location','best');
%
% Inspired by Ioannis Filippidis's answer: 
% http://www.mathworks.com/matlabcentral/answers/2165-too-many-markers
% 
% rev.4, Massimo Ciacci, October 17, 2014
% 
function [H1,H2,H3] = line_fewer_markers(x,y,num_Markers, varargin)


%% find marker spec in varargin and remove it; extract special params: LockOnMax,Spacing
if mod(length(varargin),2)
    if ischar(varargin{1})
      linspec   = varargin{1};
      extraArgs = varargin(2:end);
      [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec,extraArgs);
    else
      error('odd sized [param | val] list, missing one param ?');
    end
else
      [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin{:});  
end

%% input size check
if  isvector(x) &&  isvector(y)
    % make x,y row vectors
    if iscolumn(x), x = x.'; end
    if iscolumn(y), y = y.'; end
else
    error('line_fewer_markers: input arguments must be 1D vectors');
end

% How the method works: plots 3 times: 
% a) once only the line with all points with the style                                        'r--' and invisible handle, 
% b) last time the markers, using fewer points with style                                     'ro' and again invisible handle.
% c) once with a visible handle, only the first point, using the complete style you specified (e.g. 'r--o')

%% a) once only the line with all points with the style                                                                
H2 = line(x   ,y   ,varargInNoMk{:});                               %no markers here
hasbehavior(H2,'legend',0);                                         %prevent to appear in legends!

%% b) last time the markers, using fewer points with style                                                             
if     (strcmp(Spacing,'x') || strcmp(Spacing,'X'))
    ti = round(linspace(1,length(x),num_Markers));
elseif (strcmp(Spacing,'logx') || strcmp(Spacing,'log'))
    xi = logspace(log10(x(2)),log10(x(end-1)),num_Markers);
    ti = floor(interp1(x,(1:length(x)),xi));
elseif (strcmp(Spacing,'curve') || strcmp(Spacing,'Curve'))
    scaleY     = 3/4; % 1/1 figure aspect ratio
    yNrm       = (y-min(y))./(max(y)-min(y))*scaleY;             %NORMALIZE y scale in [0 1], height of display is prop to max(abs(y))        
    xNrm       = (x-min(x))./(max(x)-min(x));                    %NORMALIZE x scale in [0 1]   
    
    if (sum(isinf(yNrm))>0) || sum(isinf(x))>0                   %spacing along curve not possible with infinites
        ti = round(linspace(1,length(x),num_Markers)); 
    else
        t        = 1:length(x);                                
        s        = [0 cumsum(sqrt(diff(xNrm).^2+diff(yNrm).^2))];%measures length along the curve
        si       = (0:num_Markers-1)*s(end)/(num_Markers-1);     %equally spaced lengths along the curve
        si(end)  = s(end);                                       %fix last point to be within the curve                    
        ti       = round(interp1(s,t,si));                       %find x index of markers
    end
else
    error('invalid spacing parameter');
end
if LockOnMax
    %set one ti on max if found
    [Mv,idx]   = max(y); idx=idx(1);
    [mv,idxti] = min(abs(idx-ti));
    deltati    = ti(idxti)-idx;
    ti         = max(1,min(ti-deltati,length(y)));
end    
xi = x(ti);
yi = y(ti);           
H3 = line(xi,yi,varargInNoMkNoLn{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc,'LineStyle','none');  %plot markers only
hasbehavior(H3,'legend',0); %prevent to appear in legends!

%% c) once with a visible handle, only the first point, using the complete style you specified                         
if strcmp(LegendLine,'on')
    H1 = line(xi(1),yi(1),varargInNoMk{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc);
else
    H1 = line(xi(1),yi(1),varargInNoMk{:},'linestyle','none','Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc);
end


%-------------------------------------------------------------
% PARSE FUNCTIONS
%-------------------------------------------------------------
% varargInNoMk = list of property pairs, marker specs removed 
% varargInNoMkNoLn = list of property pairs, marker specs and line specs removed 
function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin)
lm =[]; ms =[]; mfc=[]; LockOnMax=[]; Spacing=[]; LegendLine=[];
varargInNoMk = {};
varargInNoMkNoLn = {};
arg_index = 1;
while arg_index <= length(varargin)
	arg = varargin{arg_index};
    % extract special params and marker specs from arg list
    if strcmp(arg,'marker') || strcmp(arg,'Marker') || strcmp(arg,'Mk')  || strcmp(arg,'mk')
        lm              = varargin{arg_index+1};
    elseif strcmp(arg,'MarkerSize') || strcmp(arg,'markersize') || strcmp(arg,'Mks')  || strcmp(arg,'mks')
        ms              = varargin{arg_index+1};        
    elseif strcmp(arg,'MarkerFaceColor') || strcmp(arg,'markerfacecolor')||strcmp(arg,'MFC')||strcmp(arg,'mfc')
        mfc             = varargin{arg_index+1};
    elseif strcmp(arg,'LockOnMax') || strcmp(arg,'lockonmax')
        LockOnMax       = varargin{arg_index+1};
    elseif strcmp(arg,'Spacing')   || strcmp(arg,'spacing') 
        Spacing         = varargin{arg_index+1};
    elseif strcmp(arg,'LegendLine')   || strcmp(arg,'legendline') 
        LegendLine      = varargin{arg_index+1};
    else
        % keep other params in arg list for line command
        varargInNoMk    = {varargInNoMk{:},  varargin{arg_index},  varargin{arg_index+1}};
        if ~strcmp(arg,'LineStyle') && ~strcmp(arg,'linestyle') 
           % exclude line params for marker only plot
           varargInNoMkNoLn = {varargInNoMkNoLn{:},  varargin{arg_index},  varargin{arg_index+1}};
        end
    end
    arg_index = arg_index + 2;	
end
%EXTRA DEFAULTS ARE SET HERE
if isempty(lm),         lm          = 'o'   ; end
if isempty(ms),         ms          = 10    ; end
if isempty(mfc),        mfc         = 'none'; end
if isempty(LockOnMax),  LockOnMax   = 1     ; end
if isempty(Spacing),    Spacing     = 'x'   ; end %%'x' -> marker delta-x constant; 'curve' : spacing constant along the curve length
if isempty(LegendLine), LegendLine  = 'on'  ; end 

%-------------------------------------------------------------
% Parse LineSpec string and other arguments
% varargInNoMk     = list of property pairs, marker specs removed 
% varargInNoMkNoLn = list of property pairs, marker specs and line specs removed 
function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec, extraArgs)
%          b     blue          .     point              -     solid
%          g     green         o     circle             :     dotted
%          r     red           x     x-mark             -.    dashdot 
%          c     cyan          +     plus               --    dashed   
%          m     magenta       *     star             (none)  no line
%          y     yellow        s     square
%          k     black         d     diamond
%          w     white         v     triangle (down)
%                              ^     triangle (up)
%                              <     triangle (left)
%                              >     triangle (right)
%                              p     pentagram
%                              h     hexagram
varargInNoMk     = {};
varargInNoMkNoLn = {};

foundLine           = false;
stringSearch        = {'-.','--','-',':'};
for ii=1:4
    if strfind(linspec, stringSearch{ii})
        foundLine   = true;
        ls          = stringSearch{ii};
        linspec     = setdiff(linspec,ls);
        break
    end
end
if foundLine
    varargInNoMk    = {varargInNoMk{:},'lineStyle',ls};
else
    varargInNoMk    = {varargInNoMk{:},'lineStyle','-'};    
end

if ~isempty(linspec)
    foundCol            = false;
    stringSearch        = {'b','g','r','c','m','y','k','w'};
    for ii=1:8
        if strfind(linspec, stringSearch{ii})
            foundCol    = true;
            colspec     = stringSearch{ii};
            linspec     = setdiff(linspec,colspec);
            break
        end
    end
    if foundCol
        varargInNoMk    = {varargInNoMk{:},'color',colspec};
        varargInNoMkNoLn    = {varargInNoMkNoLn{:},'color',colspec};
    end    
end

if ~isempty(linspec)
    foundMk             = false;
    stringSearch        = {'.','o','x','+','*','s','d','v','^','<','>','p','h'};
    for ii=1:13
        if strfind(linspec, stringSearch{ii})
            foundMk     = true;
            mkspec      = stringSearch{ii};
            break
        end
    end
    if foundMk, lm = mkspec; else lm = 'none'; end
else
    lm = 'none';
end


[extraArgs1,unused,lm2,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(extraArgs{:});
if strcmp(lm,'none') && ~strcmp(lm2,'none') %if other marker specified in Property Pairs take that one
    lm = lm2;
end
varargInNoMk       = {varargInNoMk{:},extraArgs1{:}};
varargInNoMkNoLn   = {varargInNoMkNoLn{:},extraArgs1{:}};

test_lfm.m

clear all; close all;

figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]);
xlabel('x');ylabel('y');title('a family plot with nice legend');

x       = (1:1000);
xMid    = (x(1)+2*x(end))/3;
parVals = [1 1.5 2 3]; 

num_Markers = 8; %<--------
LineTypes   = {'-.','-','--'};
MarkerTypes = {'h','o','s','d','^','v','>','<','p'};
colors      = {'m','r','b',[1 1 1]*0.5};
for ip=1:length(parVals)
    col           =  colors{1+mod(ip,length(colors))};
    ls            =  LineTypes{1+mod(ip,length(LineTypes))};
    lm            =  MarkerTypes{1+mod(ip,length(MarkerTypes))};
    g             =  parVals(ip);
    y             =  1 + 1/g*abs(1e4./(xMid + (x-xMid/g).^(2-0.2*g)));   % a function that changes with parameter g
    legCell{ip}   = ['fA, g=',num2str(g)];         %legend text    
    [p1,p2,p3]    = line_fewer_markers(x,y,num_Markers,'color',col,'linestyle',ls, 'linewidth',2, 'marker', lm, 'markerfacecolor',col,'LockOnMax',1,'Spacing','curve','parent',gca);
end
lh = legend(legCell,'Location','NorthWest');

 test_lfm_In_PlotYY.m

clear all; close all;

figure(10); hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]);
x=(1:10);
y1=x.^2;y2=x.^3;

f1 = @(x,y)line_fewer_markers(x,y,5,'ro');
f2 = @(x,y)line_fewer_markers(x,y,8,'-.bs','Spacing','curve','markerfacecolor','g');%,'LegendLine','off');
[yH,lh1,lh2] = plotyy(x,y1,x,y2,f1,f2)

xlabel('x');
ylabel(yH(1),'x^2')
ylabel(yH(2),'x^3')
legend([lh1,lh2],{'curve 1','curve 2'},'location','northwest')
set(gcf,'position',[100 100 900 600]);

test_lfm_logScale.m 

clear all; close all;

figure; hold on; grid on;
set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]);
xlabel('f');ylabel('|H| [dB]');

f = logspace(log10(100),log10(10e6),100);
pS1= -2*pi*1e4;
pS2= -2*pi*1e5;
pS3= -2*pi*1e6;
G1 = -pS1./(pS1+2*pi*j*f);
G2 = -pS2./(pS2+2*pi*j*f);
G3 = -pS3./(pS3+2*pi*j*f);
h1=line_fewer_markers(f,20*log10(abs(G1)),8,'rs','spacing','logx','linewidth',2,'markerfacecolor','r')
h2=line_fewer_markers(f,20*log10(abs(G2)),8,'bp','spacing','logx','linewidth',2)
h3=line_fewer_markers(f,20*log10(abs(G3)),8,'mv','spacing','logx','linewidth',2,'markersize',6)
set(gca,'XScale','log')

legend([h1,h2,h3],'G1','G2','G3','location','southwest');

test_lfm_shortExample.m 

clear all; close all;

figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]);
xlabel('x');ylabel('y');title('a family plot with nice legend');
t  = 0:0.005:pi;
line_fewer_markers(t*180/pi,cos(t)         ,9,  '--bs','spacing','curve');
line_fewer_markers(t*180/pi,sin(t)         ,9,  '-.ro','MFC','g','Mks',6,'linewidth',2);
grey1 = [1 1 1]*0.5;
line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1);
leg = legend('cos','sin','sin*cos','location','best');

test_lfm_shortExample_noLine.m 

clear all; close all;

figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]);
xlabel('x');ylabel('y');title('a family plot with nice legend');
t  = 0:0.005:pi;
grey1 = [1 1 1]*0.5;
% line_fewer_markers(t*180/pi,cos(t)         ,9,  '--bs','spacing','curve');
% line_fewer_markers(t*180/pi,sin(t)         ,9,  '-.ro','MFC','g','Mks',6,'linewidth',2);
% line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1);

line_fewer_markers(t*180/pi,cos(t)         ,9,  '--bs','spacing','curve','LegendLine','off');
line_fewer_markers(t*180/pi,sin(t)         ,9,  '-.ro','MFC','g','Mks',6,'linewidth',2,'LegendLine','off');
line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1,'LegendLine','off');


leg = legend('cos','sin','sin*cos','location','best');
% https://ww2.mathworks.cn/matlabcentral/fileexchange/42560-line_fewer_markers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

资源存储库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值