动态调整自定义滴答的数量

时间:2014-10-30 06:55:46

标签: matlab plot labels

考虑an example from SO,我想根据当前视图调整轴刻度。这是默认行为,除非设置自定义的滴答数,

结果行为如下图所示。在左侧是默认行为,在右侧是具有自定义刻度的图形。使用自定义的Z刻度旋转绘图时,它们的编号将不适应当前可用的空间(参见右下图)。

是否有一个简单的通用解决方案,没有像camva()获取当前角度等奇特的东西?我希望不扩展数据本身,因为它是一个大数据集,但使用自定义的刻度和刻度标签。它需要与MATLAB Version: 8.0.0.783 (R2012b)一起使用。

enter image description here

代码

%# sample graph vertices and edges (similar to your data)
[adj,XYZ] = bucky;
[r, c] = find(adj);
edges = [r c];      %# M-by-2 matrix holding the vertex indices
points = XYZ';      %# 3-by-N matrix of points X/Y/Z coordinates

%# build a list of separated lines
e = edges';
e(end+1,:) = 1;
e = e(:);
p = points(:,e);
p(:,3:3:end) = NaN;

figure
line(p(1,:), p(2,:), p(3,:));
view(3)

% Now the same with self defined ticks
figure
line(p(1,:), p(2,:), p(3,:));
view(3)
z = points(3, :);
fac = 3.14159265359;
tickstep = (max(z)-min(z))/9;
ticklabels_ = min(z):tickstep:max(z);
set(gca, 'ZTick', ticklabels_)
set(gca, 'ZTickLabel', sprintf('%.3f|',ticklabels_))

2 个答案:

答案 0 :(得分:6)

如评论中@bdecaf所示,您可以为z-ticks更改时编写事件处理程序,以便相应地自定义tick标签。这是使用undocumented functionality

这很方便,因为我们仍然让MATLAB根据轴可用的屏幕空间自动确定要使用的最佳刻度数,我们只需自定义所显示标签的格式。

实施例

function customize_ticks_example()
    % data
    [adj,XYZ] = bucky;
    [r,c] = find(adj);
    edges = [r c];
    points = XYZ';
    e = edges';
    e(end+1,:) = 1;
    e = e(:);
    p = points(:,e);
    p(:,3:3:end) = NaN;

    % plot
    hFig = figure;
    line(p(1,:), p(2,:), p(3,:), ...
        'LineWidth',2, 'Marker','.', 'MarkerSize',20);
    ax = handle(gca);
    view(3), grid on, box on
    xlabel x, ylabel y, zlabel z
    rotate3d on

    % listen to changes on ZTick property
    ev = handle.listener(ax, findprop(ax,'ZTick'), ...
        'PropertyPostSet', @onZTickChange);
    setappdata(hFig, 'my_ztick_listener', ev);
end

function onZTickChange(~,e)
    % get the new 'ZTick', and format them as needed
    labels = num2str(e.NewValue(:),'%g $');

    % update the 'ZTickLabel'
    set(double(e.AffectedObject), 'ZTickLabel',labels)
end

animation

当然,标签不必是数字标记,只要您有某种比例尺,就可以使用任何自定义标签,您可以在其中插入值以确定要使用的标签。


编辑:

set the event listener的简便方法:

ev = addlistener(gca, 'ZTick', 'PostSet', @onZTickChange);

(在这种情况下,不需要使用evsetappdata存储在GUI中。This syntax将侦听器绑定到GUI对象的生命周期。)


编辑2:

在回应评论时,这是另一个例子:

function example_manual_ticks
    %% some 3d plot
    hFig = figure;
    sphere
    view(3), grid on, box on
    xlabel x, ylabel y, zlabel z

    %% create a hidden copy of the axis
    hax1 = gca;
    hax2 = copyobj(hax1, hFig);
    set(hax2, 'Visible','off', 'Color','none', 'HitTest','off', ...
        'XLimMode','manual', 'YLimMode','manual', 'ZLimMode','manual')
    delete(get(hax2, 'Children'))
    uistack(hax2, 'bottom')

    % sync axes on 3d rotation
    hlink = linkprop([hax1,hax2], {'CameraPosition','CameraUpVector'});
    setappdata(hax1, 'my_axes_linkprop', hlink);
    rotate3d on

    % respnd to changes in ZTick axis property
    ev = addlistener(hax2, 'ZTick', 'PostSet',@(o,e) onZTickChange(o,e,hax1));

    %% animation
    el = 90 .* sin(linspace(0,2*pi,100) + asin(1/3));
    for n=1:numel(el)
        view(-37.5, el(n))
        drawnow
    end
end
function onZTickChange(~,e,ax)
    % determine number of ticks
    num_ticks = numel(e.NewValue);
    new_num_ticks = num_ticks - 1;

    % interpolate new ticks along the axis limits
    limits = get(ax, 'ZLim');
    zticks = linspace(limits(1), limits(2), new_num_ticks);
    zticks_labels = num2str(zticks(:), '%.2f ($)');

    % update ticks
    set(ax, 'ZTick',zticks, 'ZTickLabel',zticks_labels)
    drawnow
end

animation2

我们的想法是在3D旋转时创建一个隐藏的copy轴,kept in sync和原始轴。第二个轴将具有自动刻度标记,同时我们根据需要自定义第一个轴的刻度线(类似于在刻度线更改时在隐藏轴上注册回调之前)。

我再次使用这个隐藏的轴作为让MATLAB处理给定视图确定最佳滴答数的任务的方法(这比弄乱摄像机角度和矩阵变换要容易得多)找出投影轴的长度(以像素为单位)。

在上面的示例中,我只是将滴答数设置为小于自动数({2,4,10}而不是{3,5,11}),但您可以使用任何类型的映射

答案 1 :(得分:0)

在2015b中,不再支持 PostSet 属性(https://de.mathworks.com/matlabcentral/answers/231377-problem-with-addlistener-to-xlim)。

如果手动更改大小,则可以使用 WindowMouseRelease SizeChanged 属性。我改编了https://stackoverflow.com/a/26705913/2295776中的代码,但是该动画在此示例中不再起作用:

flex: 1;