动态调整自定义刻度的数量 [英] Dynamically adapt number of self defined ticks

查看:106
本文介绍了动态调整自定义刻度的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SO的示例为例,我想根据当前视图调整轴刻度.这是默认行为,除非有人设置了自己定义的刻度数,

Taking an example from SO, I'd like to adapt the axis ticks dependent on the current view. This is the default behavior, unless one sets a self defined number of ticks,

结果显示在下面的图片中.左侧是默认行为,右侧是带有自定义刻度的图形.当使用自定义的Z刻度旋转图时,其编号将不适应当前可用空间(请参见右下图).

The resulting behavior is demonstrated in the picture below. On the left side the default behavior, on the right side the figure with self defined ticks. When rotating the plot with the self defined Z ticks, their number won't be adapted to the currently available space (see right bottom figure).

是否有一个简单,通用的解决方案,而没有像camva()这样获得当前角度的奇特的东西?我不希望对数据本身进行缩放,因为它是一个很大的数据集,而是要使用自定义的刻度和刻度标签.它需要与MATLAB Version: 8.0.0.783 (R2012b)一起使用.

Is there a simple, general solution for that without some fancy things like getting current angle by camva()? I'd wish to not scale the data itself, since it's a big dataset, but to use self defined ticks and tick-labels. It needs to work with MATLAB Version: 8.0.0.783 (R2012b).

代码

%# 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_))

推荐答案

如注释中@bdecaf所示,您可以为z刻度变化时编写事件处理程序,以便相应地自定义刻度标签.这是使用未记录

As indicated by @bdecaf in the comments, you could write an event handler for when the z-ticks change, in order to customize the tick labels accordingly. This is using undocumented functionality.

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

This is convenient because we still let MATLAB automatically decide on the best number of ticks to use depending on the screen space available for the axis, we just customize the format of the labels displayed.

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

当然标签不必一定是数字的,只要您具有某种比例尺,就可以使用自定义标签来插值以确定要使用的标签.

Of course the labels don't have to be numerical, you could use any custom labels as long as you have some kind of scale along which you can interpolate values to figure what label to use.

设置事件监听器的简便方法:

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

(在这种情况下,无需将evsetappdata一起存储在GUI中.

(in this case, there is no need to store ev inside the GUI with setappdata. This syntax bind the listener to the lifecycle of the GUI object).

为回应评论,这是另一个示例:

In response to comments, here is another example:

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

该想法是创建轴的隐藏的副本与原始对象保持3D旋转同步.第二个轴将具有自动刻度线,而我们可以根据需要自定义第一个轴的刻度线(类似于在刻度线更改时在隐藏轴上注册回调的情况).

The idea is to create a hidden copy of the axis, kept in sync with the original one on 3D rotation. This second axis will have automatic tick marks, while we customize the ticks of first axis as we wish (similar to before we register a callback on the hidden axis for when the ticks change).

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

Again I'm using this hidden axis as a way to let MATLAB deal with the task of determining the best number of ticks given the view (this is a lot easier than messing with camera angles and matrix transformations in order to find out the length of the projected axis in pixels).

在上面的示例中,我只是将刻度数设置为比自动数({2,4,10}而不是{3,5,11})少一个,但是您可以使用任何想要的映射.

In the example above, I'm simply setting the number of ticks one less than the automatic number ({2,4,10} instead of {3,5,11}), but you could use any kind of mapping you want.

这篇关于动态调整自定义刻度的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆