【问题标题】:Plot shaded region around lines绘制线条周围的阴影区域
【发布时间】:2015-01-26 13:45:51
【问题描述】:

我正在寻找一种方法来围绕我根据点分布计算的每条线绘制一个阴影区域(参见附图)。该区域应具有固定宽度(绘制线上方和下方 10 个像素)。事情比平时要复杂一些,因为编写代码是为了考虑一系列数据集,并且对于每一组我需要绘制几条曲线(数字从一组变化到另一组)。我尝试了各种方法,包括errorbar(f(xx,:), threshold_distance_fit),都没有成功。

你建议如何解决这个问题?

这是我用来绘制数据集和曲线的代码:

g = figure; xlabel('Omega'); ylabel('Y_detector');
plot(Angle, Y_measured, '*'); hold on;
f = zeros(number_centers, 180);
for xx = 1:number_centers
   for deg = 1:180
       % f is the fitting function
       f(xx, deg) = double((R_fit(xx)*sind(alpha_fit(xx)+deg)/0.05)+113);
   end
   plot(1:180, f(xx,:), '.'); hold on;
 end

【问题讨论】:

  • 看看patch
  • 听起来是个糟糕的建议,但对具有所需线宽的线条进行后处理(假设您将绘图保存为矢量图形)可以获得最佳结果。使用patch 和可选的FaceAlpha 属性是一个选项,但请注意整个阴影区域将由三角形构建。对于多个绘图,会有大量的三角形,显示图形会变得非常慢。

标签: matlab plot


【解决方案1】:

一个很好的可能性是创建具有更大线宽的相同图并使其透明。不幸的是,这在 MATLAB 中并不容易,但有某种解决方法。您可以使用z=0 创建一个surface 图,它看起来就像一个图。

请注意,如果xy 分别是大小为1 x n1 x m 的向量,那么surface 假定z 是大小为m x n 的矩阵。因此,您需要制作xyz 矩阵。您可以通过[x;x] 轻松做到这一点(假设x 是一个行向量)。

然后您可以指定曲面图的线宽、颜色和不透明度(alpha 值)。

例如

x = 0:0.01:2*pi;
y = sin(2*x);
z = zeros(size(x));

hold on;
surface([x;x],[y;y],[z;z], 'linew',20, 'edgecolor','r', 'edgealpha',0.2);
plot(x,y,'-r');
hold off;

创建:

【讨论】:

    【解决方案2】:

    我在使用patchsurface 之间犹豫不决,而hbaderts 在提出surface 选项时更快,所以我将向您展示如何使用patch

    我将在我的示例中提供更多构造细节,但如果您愿意,最终您可以将我的补丁替换为表面对象。

    首先我开始构建一系列看起来像你的曲线:

    colorCollection = get(0,'defaultAxesColorOrder') ;
    nPlot = 4 ;
    
    h.fig  = figure ;
    h.ax   = axes('NextPlot','add') ;
    
    x = linspace(0,180) ;
    f = zeros( nPlot , numel(x) ) ;
    for k=1:nPlot
        f(k,:) = sin(k*x/180*pi) * 180 ;
        h.plotf(k) = plot( x , f(k,:) , '.' , 'Color',colorCollection(k,:) ) ;
    end
    

    这将创建并绘制 4 条曲线。接下来是解决您“上方 10 像素和下方 10 像素”的请求。绘制的曲线或任何补丁/曲面将没有“像素”的概念,而只有数据空间中的值。所以你必须知道如何将像素转换为数据或反过来。

    %// retrieve a few propery values
    xlim = get(h.ax,'XLim') ;               %// axes X limits
    ylim = get(h.ax,'YLim') ;               %// axes Y limits
    set( [h.ax h.fig] , 'Unit','Pixels')    %// set the axes units in pixel
    axpos = get( h.ax,'Position') ;         %// get the coordinates of the axes object on the figure (in pixels)
    nPix.W = round(axpos(3)) ;              %// axes WIDTH  , in [pixel]
    nPix.H = round(axpos(4)) ;              %// axes HEIGHT , in [pixel]
    
    %// calculate the vertical data/pixel ratio (to know how much "y" value
    %// will correspond to "10" pixels)
    nPixelOverlap = 10 ;                            %// this is defined in your question
    pixelRatio  = (ylim(2)-ylim(1)) ./ nPix.H ;     %// =0.0052 in my example. => 1pixel=0.0052*y
    dataOverlap = nPixelOverlap .* pixelRatio ;     %// how much I have to add or remove to a curve to cover 10 pixels
    

    一旦我有了这个神奇的系数dataOverlap,我就可以构建必须包含每条曲线的图形对象,它们的较高和较低Y 边界将是曲线的值,分别加上和减去dataOverlap .

    在您的情况下,您似乎没有大向量(没有那么多 x 值),因此下面的部分解决方案可能对您的问题来说是多余的。但是,如果您必须对大型数据向量(例如数千个或更糟,数百万个元素)做同样的事情,那么创建具有这么多点的许​​多补丁(甚至表面)很可能几乎会冻结您的图形(如果响应时间非常慢,如果不会更糟)。一个简单的方法是绘制一个下采样版本。由于我们已经计算了轴跨越的像素数,我们可以创建这个大小的图形对象(所以我们基本上每个像素只有一个x 点,仅此而已)。

    %// define a minimal "x" vector to populate every pixel in the axes
    x4interp = linspace(xlim(1),xlim(2),nPix.W) ;
    
    xpatch = [x4interp fliplr(x4interp)] ;          %// common X vector for all the patch objects
    ypatch = zeros( nPlot , numel(xpatch) ) ;       %// preallocate Y arrays for each patch (one patch per initial curve)
    for k=1:nPlot
        ytemp = interp1( x , f(k,:) , x4interp ) ;  %// reinterp the "k-th" curve value on the new "x" axis
        %// prepare the patch "Y" data (=the curve reinterpolated value + and - the overlap
        ypatch( k , : ) = [ytemp-dataOverlap fliplr(ytemp)+dataOverlap] ;
        %// plot the actual patch
        h.patch(k) = patch( xpatch , ypatch(k,:) , colorCollection(k,:) , 'FaceAlpha',0.2 , 'EdgeColor','none' ) ;
    end
    

    如果你一次性执行这个例子,你应该会得到非常相似的东西(颜色可能会有所不同,具体取决于你使用的 Matlab 版本):

    正如我上面所说的,对于这个例子来说,最后一点重新插值是多余的(补丁实际上比曲线有 更多 个数据点),但好处是它具有很强的可扩展性。如果您的初始曲线有 107 个点,您可以使用完全相同的方法,补丁不会占用您的内存(您的曲线可能)。


    请注意,像素/数据比率的计算取决于屏幕图形的大小。如果调整图形大小,则不会更新计算。您要么必须重新执行计算部分并更新图形对象,要么最简单的方法是先将图形设置为所需的大小,然后执行计算并绘制图形对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-30
      • 1970-01-01
      • 2017-03-13
      • 2022-01-17
      • 2021-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多