对数刻度上相同(可视)大小的图块

问题描述 投票:0回答:1

我想在具有对数x轴的图中标记一些峰。我在考虑使用patch,因为我需要一个回调,该回调在用户单击标记时响应。 Verticespatch属性以数据为单位,而不是像素。但是,我希望这些补丁以相同的视觉宽度和高度出现,但是我无法找到一种方法来计算导致相同宽度(以像素为单位)的宽度(以数据为单位)。

我以为这不可能太复杂,但是我完全陷于困境,也许为了尝试简单的答案尝试了太多。

[我知道这不完全与Matlab相关,但是我很高兴使用patch以外的其他东西,只要它提供了单击鼠标即可响应的功能。

peakpos = [50 500 5000];
peakheight = [5000 7500 10000];

x = 0:5e4;
y = zeros(numel(x),1);
for k = 1:3
    y(peakpos(k)) = peakheight(k);
end

ax = axes(figure());
plot(ax, x,y);
ax.XScale = 'log';
ax.Units = 'pixels';

dataperpx_y = diff(ax.YLim)/ax.Position(4);

ax.YLim = [0 1e4+30 * dataperpx_y];
ax.NextPlot = 'add';
for k = 1:3
    patch(ax, ...
        'Faces', [1 2 3], ...
        'Vertices', ...
            [ x(peakpos(k)) peakheight(k)+5*dataperpx_y
              x(peakpos(k)) - 25 peakheight(k)+15*dataperpx_y  
              x(peakpos(k)) + 25 peakheight(k)+15*dataperpx_y 
            ], ...
        'ButtonDownFcn', @(h,e)display(h.Vertices));
end
matlab matlab-figure logarithm
1个回答
0
投票

好吧,正如我所想,这并不太复杂。我不知道我到底在哪里卡住,但有一点令人困惑的是,将轴的XScale属性设置为log会使轴使用十进制对数,而log()函数是自然的对数。

在以线性比例绘制log10(x)之后,解决方案非常明显:

peakpos = [50 500 5000];
peakheight = [5000 7500 10000];

x = 0:5e4;
y = zeros(numel(x),1);
for k = 1:3
    y(peakpos(k)) = peakheight(k);
end

ax = subplot(2,1,1);

plot(ax, log10(x),y);
%ax.XScale = 'log';
ax.Units = 'pixels';

dataperpx_y = diff(ax.YLim)/ax.Position(4);
dataperpx_x = diff(ax.XLim)/ax.Position(3);
ax.YLim = [0 1e4+30 * dataperpx_y];
ax.NextPlot = 'add';
for k = 1:3
    patch(ax, ...
        'Faces', [1 2 3], ...
        'Vertices', ...
            [ log10(x(peakpos(k))) peakheight(k)+5*dataperpx_y
              log10(x(peakpos(k))) - 5*dataperpx_x peakheight(k)+15*dataperpx_y  
              log10(x(peakpos(k))) + 5*dataperpx_x peakheight(k)+15*dataperpx_y 
            ], ...
        'ButtonDownFcn', @(h,e)display(h.Vertices));
end

ax = subplot(2,1,2);

plot(ax, x, y);
ax.XScale = 'log';
ax.Units = 'pixels';
dataperpx_y = diff(ax.YLim)/ax.Position(4);
dataperpx_x = diff(log10(ax.XLim))/ax.Position(3);
ax.YLim = [0 1e4+30 * dataperpx_y];
ax.NextPlot = 'add';

for k = 1:3
    patch(ax, ...
        'Faces', [1 2 3], ...
        'Vertices', ...
            [ x(peakpos(k)) peakheight(k)+5*dataperpx_y
              x(peakpos(k)) / 10^(5*dataperpx_x) peakheight(k)+15*dataperpx_y  
              x(peakpos(k)) * 10^(5*dataperpx_x) peakheight(k)+15*dataperpx_y 
            ], ...
        'ButtonDownFcn', @(h,e)display(h.Vertices));
end

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.