Matlab 3D坐标轴对齐

phymhan/matlab-axis-label-alignment

参考:Ligong Han (2022). phymhan/matlab-axis-label-alignment (https://github.com/phymhan/matlab-axis-label-alignment), GitHub. Retrieved April 4, 2022.

效果图
                 在这里插入图片描述
    在这里插入图片描述
example

clc
clear
z = peaks;
figure('color', [1 1 1])
surf(z);
set(gca, 'dataaspectratio', [1 1 0.5], 'projection', 'perspective', 'box', 'on')
xlabel('This is an x label', 'fontsize', 16, 'fontweight', 'bold', 'color', [1 0 0])
ylabel('This is a y label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 0])
zlabel('This is a z label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 1])

% Add the following after you plot your figures
h = rotate3d;
set(h, 'ActionPreCallback', 'set(gcf,''windowbuttonmotionfcn'',@align_axislabel)')
set(h, 'ActionPostCallback', 'set(gcf,''windowbuttonmotionfcn'','''')')
set(gcf, 'ResizeFcn', @align_axislabel)
align_axislabel([], gca)
axislabel_translation_slider;

align_axislabel.m

function align_axislabel(~,ax)
% This function first rotates x, y and z labels to the direction of their 
% corresponding axes when a rotate operation has finished. So that labels 
% will be parallel to axes. Then, moves the axis labels to a proper 
% distance from the axes by calling 'axislabel_translation'.
% The function is used as an 'ActionPostCallback', which is a callback 
% function of a rotate3d object.
% It still works when the projection mode is perspective or when the data 
% aspect ratio is not [1 1 1].
%
% Example 1: % set ActionPostCallback to align_axislabel
%  h = rotate3d;
%  set(h,'ActionPostCallback',@align_axislabel);
%
% Example 2: % set WindowButtonMotionFcn to align_axislabel
%  h = rotate3d;
%  set(h,'ActionPreCallback',...
%      'set(gcf,''windowbuttonmotionfcn'',@align_axislabel)')
%  set(h,'ActionPostCallback',...
%      'set(gcf,''windowbuttonmotionfcn'','''')')
%
% Jul/13/2015, Adds a trans_mode option
% Feb/06/2015
% Apr/10/2016

% trans_mode controls the way we define trans_vec_x and trans_vec_y, which
% is an input argument passed to function axislabel_translation.
% Take x-axis for example. If trans_mode == 2, the translation direction is
% parallel to y-axis, and if trans_moede == 1, the translation direction is
% perpendicular to x-axis.
trans_mode = 1;

if isa(ax,'struct')
    h_a = ax.Axes;
elseif isa(ax,'matlab.graphics.axis.Axes')
    h_a = ax;
else
    h_a = gca;
end

proj_mode = get(h_a,'projection');
if strcmpi(proj_mode,'orthographic')
    proj_mode = 1;
else
    proj_mode = 2;
end
data_aspect_ratio = get(h_a,'dataaspectratio');
data_aspect_ratio = data_aspect_ratio(:);

set(h_a, 'DataAspectRatio', data_aspect_ratio); % optional, you can comment this line out

x_lim = get(h_a,'xlim');
y_lim = get(h_a,'ylim');
z_lim = get(h_a,'zlim');
cam_pos = get(h_a,'cameraposition');
cam_tar = get(h_a,'cameratarget');
cam_vec = cam_pos-cam_tar;
N = norm(cam_vec,2); % Near field
[az,el] = view; % get current azimuth and elevation angles
if abs(el) == 90
    az = atan2d(sind(az)*data_aspect_ratio(2),cosd(az)*data_aspect_ratio(1));
end % Adjust az when el == 90
az = az/180*pi;
el = pi/2-el/180*pi;
% Rotation Matrices
R_az = [cos(-az),-sin(-az),0,0;sin(-az),cos(-az),0,0;0,0,1,0;0,0,0,1];
R_el = [1,0,0,0;0,cos(-el),-sin(-el),0;0,sin(-el),cos(-el),0;0,0,0,1];
% Translation Matrices
T_tar = [1,0,0,-cam_tar(1);0,1,0,-cam_tar(2);0,0,1,-cam_tar(3);0,0,0,1];
T_cam = [1,0,0,0;0,1,0,0;0,0,1,-N;0,0,0,1];
pnt = [x_lim(1),y_lim(1),z_lim(1),1;...
    x_lim(2),y_lim(1),z_lim(1),1;...
    x_lim(2),y_lim(2),z_lim(1),1;...
    x_lim(1),y_lim(2),z_lim(1),1;...
    x_lim(1),y_lim(1),z_lim(2),1;...
    x_lim(2),y_lim(1),z_lim(2),1;...
    x_lim(2),y_lim(2),z_lim(2),1;...
    x_lim(1),y_lim(2),z_lim(2),1]';
pnt_cam = zeros(4,8);
if proj_mode == 1
    F = N+100; % Far field, the value would not influence the projection
    a = -(F+N)/(F-N);
    b = -2*F*N/(F-N);
    M_orth = [N,0,0,0;0,N,0,0;0,0,a,b;0,0,-1,0];
    pnt_cam = zeros(4,4);
    for kk = 1:8
        p = pnt(:,kk);
        p = T_tar*p;
        p(1:3) = p(1:3)./data_aspect_ratio;
        p = R_el*R_az*p;
        p = T_cam*p;
        pnt_cam(:,kk) = M_orth*p;
    end
    x_vec = pnt_cam(:,2)-pnt_cam(:,1);
    y_vec = pnt_cam(:,4)-pnt_cam(:,1);
    z_vec = pnt_cam(:,5)-pnt_cam(:,1);
    % find the most-left point
    [~,ix] = min(pnt_cam(1,:));
    % find the lowest point
    [~,iy] = min(pnt_cam(2,:));
    switch ix % use ix to determine z axis, then use iy to determine x and y axis
        case {1,5}
            trans_pnt_z = [x_lim(1),y_lim(1),(z_lim(1)+z_lim(2))/2]';
            if iy == 2
                trans_vec_x_edge = pnt_cam(1:2,2)-pnt_cam(1:2,3);
                trans_vec_y_edge = pnt_cam(1:2,2)-pnt_cam(1:2,1);
                trans_pnt_x = (pnt(1:3,2)+pnt(1:3,1))/2;
                trans_pnt_y = (pnt(1:3,3)+pnt(1:3,2))/2;
            else % iy == 4
                trans_vec_x_edge = pnt_cam(1:2,4)-pnt_cam(1:2,1);
                trans_vec_y_edge = pnt_cam(1:2,4)-pnt_cam(1:2,3);
                trans_pnt_y = (pnt(1:3,4)+pnt(1:3,1))/2;
                trans_pnt_x = (pnt(1:3,3)+pnt(1:3,4))/2;
            end
        case {2,6}
            trans_pnt_z = [x_lim(2),y_lim(1),(z_lim(1)+z_lim(2))/2]';
            if iy == 3
                trans_vec_x_edge = pnt_cam(1:2,3)-pnt_cam(1:2,2);
                trans_vec_y_edge = pnt_cam(1:2,3)-pnt_cam(1:2,4);
                trans_pnt_y = (pnt(1:3,3)+pnt(1:3,2))/2;
                trans_pnt_x = (pnt(1:3,4)+pnt(1:3,3))/2;
            else % iy == 1
                trans_vec_x_edge = pnt_cam(1:2,1)-pnt_cam(1:2,4);
                trans_vec_y_edge = pnt_cam(1:2,1)-pnt_cam(1:2,2);
                trans_pnt_x = (pnt(1:3,1)+pnt(1:3,2))/2;
                trans_pnt_y = (pnt(1:3,4)+pnt(1:3,1))/2;
            end
        case {3,7}
            trans_pnt_z = [x_lim(2),y_lim(2),(z_lim(1)+z_lim(2))/2]';
            if iy == 4
                trans_vec_x_edge = pnt_cam(1:2,4)-pnt_cam(1:2,1);
                trans_vec_y_edge = pnt_cam(1:2,4)-pnt_cam(1:2,3);
                trans_pnt_x = (pnt(1:3,4)+pnt(1:3,3))/2;
                trans_pnt_y = (pnt(1:3,1)+pnt(1:3,4))/2;
            else % iy == 2
                trans_vec_x_edge = pnt_cam(1:2,2)-pnt_cam(1:2,3);
                trans_vec_y_edge = pnt_cam(1:2,2)-pnt_cam(1:2,1);
                trans_pnt_y = (pnt(1:3,2)+pnt(1:3,3))/2;
                trans_pnt_x = (pnt(1:3,1)+pnt(1:3,2))/2;
            end
        case {4,8}
            trans_pnt_z = [x_lim(1),y_lim(2),(z_lim(1)+z_lim(2))/2]';
            if iy == 1
                trans_vec_x_edge = pnt_cam(1:2,1)-pnt_cam(1:2,4);
                trans_vec_y_edge = pnt_cam(1:2,1)-pnt_cam(1:2,2);
                trans_pnt_y = (pnt(1:3,1)+pnt(1:3,4))/2;
                trans_pnt_x = (pnt(1:3,2)+pnt(1:3,1))/2;
            else % iy == 3
                trans_vec_x_edge = pnt_cam(1:2,3)-pnt_cam(1:2,2);
                trans_vec_y_edge = pnt_cam(1:2,3)-pnt_cam(1:2,4);
                trans_pnt_x = (pnt(1:3,3)+pnt(1:3,4))/2;
                trans_pnt_y = (pnt(1:3,2)+pnt(1:3,3))/2;
            end
    end
else
    for kk = 1:8
        p = pnt(:,kk);
        p = T_tar*p;
        p(1:3) = p(1:3)./data_aspect_ratio;
        p = R_el*R_az*p;
        p = T_cam*p;
        z = p(3);
        M_pers = [-N/z,0,0,0;0,-N/z,0,0;0,0,-N,0;0,0,0,1];
        pnt_cam(:,kk) = M_pers*p;
    end
    % find the most-left point
    [~,ix] = min(pnt_cam(1,:));
    % find the lowest point
    [~,iy] = min(pnt_cam(2,:));
    % find the proper axis to label
    switch ix % use ix to determine z axis, then use iy to determine x and y axis
        case {1,5}
            z_vec = pnt_cam(:,5)-pnt_cam(:,1);
            trans_pnt_z = [x_lim(1),y_lim(1),(z_lim(1)+z_lim(2))/2]';
            if iy == 2
                x_vec = pnt_cam(:,2)-pnt_cam(:,1);
                y_vec = pnt_cam(:,3)-pnt_cam(:,2);
                trans_vec_x_edge = pnt_cam(1:2,2)-pnt_cam(1:2,3);
                trans_vec_y_edge = pnt_cam(1:2,2)-pnt_cam(1:2,1);
                trans_pnt_x = (pnt(1:3,2)+pnt(1:3,1))/2;
                trans_pnt_y = (pnt(1:3,3)+pnt(1:3,2))/2;
            else % iy == 4
                y_vec = pnt_cam(:,4)-pnt_cam(:,1);
                x_vec = pnt_cam(:,3)-pnt_cam(:,4);
                trans_vec_x_edge = pnt_cam(1:2,4)-pnt_cam(1:2,1);
                trans_vec_y_edge = pnt_cam(1:2,4)-pnt_cam(1:2,3);
                trans_pnt_y = (pnt(1:3,4)+pnt(1:3,1))/2;
                trans_pnt_x = (pnt(1:3,3)+pnt(1:3,4))/2;
            end
        case {2,6}
            z_vec = pnt_cam(:,6)-pnt_cam(:,2);
            trans_pnt_z = [x_lim(2),y_lim(1),(z_lim(1)+z_lim(2))/2]';
            if iy == 3
                y_vec = pnt_cam(:,3)-pnt_cam(:,2);
                x_vec = pnt_cam(:,4)-pnt_cam(:,3);
                trans_vec_x_edge = pnt_cam(1:2,3)-pnt_cam(1:2,2);
                trans_vec_y_edge = pnt_cam(1:2,3)-pnt_cam(1:2,4);
                trans_pnt_y = (pnt(1:3,3)+pnt(1:3,2))/2;
                trans_pnt_x = (pnt(1:3,4)+pnt(1:3,3))/2;
            else % iy == 1
                x_vec = pnt_cam(:,1)-pnt_cam(:,2);
                y_vec = pnt_cam(:,4)-pnt_cam(:,1);
                trans_vec_x_edge = pnt_cam(1:2,1)-pnt_cam(1:2,4);
                trans_vec_y_edge = pnt_cam(1:2,1)-pnt_cam(1:2,2);
                trans_pnt_x = (pnt(1:3,1)+pnt(1:3,2))/2;
                trans_pnt_y = (pnt(1:3,4)+pnt(1:3,1))/2;
            end
        case {3,7}
            z_vec = pnt_cam(:,7)-pnt_cam(:,3);
            trans_pnt_z = [x_lim(2),y_lim(2),(z_lim(1)+z_lim(2))/2]';
            if iy == 4
                x_vec = pnt_cam(:,4)-pnt_cam(:,3);
                y_vec = pnt_cam(:,1)-pnt_cam(:,4);
                trans_vec_x_edge = pnt_cam(1:2,4)-pnt_cam(1:2,1);
                trans_vec_y_edge = pnt_cam(1:2,4)-pnt_cam(1:2,3);
                trans_pnt_x = (pnt(1:3,4)+pnt(1:3,3))/2;
                trans_pnt_y = (pnt(1:3,1)+pnt(1:3,4))/2;
            else % iy == 2
                y_vec = pnt_cam(:,2)-pnt_cam(:,3);
                x_vec = pnt_cam(:,1)-pnt_cam(:,2);
                trans_vec_x_edge = pnt_cam(1:2,2)-pnt_cam(1:2,3);
                trans_vec_y_edge = pnt_cam(1:2,2)-pnt_cam(1:2,1);
                trans_pnt_y = (pnt(1:3,2)+pnt(1:3,3))/2;
                trans_pnt_x = (pnt(1:3,1)+pnt(1:3,2))/2;
            end
        case {4,8}
            z_vec = pnt_cam(:,8)-pnt_cam(:,4);
            trans_pnt_z = [x_lim(1),y_lim(2),(z_lim(1)+z_lim(2))/2]';
            if iy == 1
                y_vec = pnt_cam(:,1)-pnt_cam(:,4);
                x_vec = pnt_cam(:,2)-pnt_cam(:,1);
                trans_vec_x_edge = pnt_cam(1:2,1)-pnt_cam(1:2,4);
                trans_vec_y_edge = pnt_cam(1:2,1)-pnt_cam(1:2,2);
                trans_pnt_y = (pnt(1:3,1)+pnt(1:3,4))/2;
                trans_pnt_x = (pnt(1:3,2)+pnt(1:3,1))/2;
            else % iy == 3
                x_vec = pnt_cam(:,3)-pnt_cam(:,4);
                y_vec = pnt_cam(:,2)-pnt_cam(:,3);
                trans_vec_x_edge = pnt_cam(1:2,3)-pnt_cam(1:2,2);
                trans_vec_y_edge = pnt_cam(1:2,3)-pnt_cam(1:2,4);
                trans_pnt_x = (pnt(1:3,3)+pnt(1:3,4))/2;
                trans_pnt_y = (pnt(1:3,2)+pnt(1:3,3))/2;
            end
    end
end

if trans_mode == 1
    trans_vec_x = [x_vec(2),-x_vec(1)]';
    trans_vec_y = [y_vec(2),-y_vec(1)]';
    trans_vec_z = [-z_vec(2),z_vec(1)]';
    if trans_vec_x'*trans_vec_x_edge < 0
        trans_vec_x = -trans_vec_x;
    end
    if trans_vec_y'*trans_vec_y_edge < 0
        trans_vec_y = -trans_vec_y;
    end
elseif trans_mode == 2
    trans_vec_x = trans_vec_x_edge;
    trans_vec_y = trans_vec_y_edge;
    trans_vec_z = [-z_vec(2),z_vec(1)]';
end

% Normalize translation vectors
trans_vec_x = trans_vec_x/norm(trans_vec_x,2);
trans_vec_y = trans_vec_y/norm(trans_vec_y,2);
trans_vec_z = trans_vec_z/norm(trans_vec_z,2);

% Compute rotation angles
theta_x = atan2d(x_vec(2),x_vec(1));
theta_y = atan2d(y_vec(2),y_vec(1));
theta_z = atan2d(z_vec(2),z_vec(1));
if abs(theta_x) >= 90
    theta_x = theta_x+180;
end
if abs(theta_y) >= 90
    theta_y = theta_y+180;
end
% if abs(theta_z) >= 90
%     theta_z = theta_z+180;
% end
set(get(h_a,'xlabel'),'rotation',theta_x);
set(get(h_a,'ylabel'),'rotation',theta_y);
set(get(h_a,'zlabel'),'rotation',theta_z);

%% Axis label translation
axislabel_translation(h_a,...
    [trans_pnt_x,trans_pnt_y,trans_pnt_z],...
    [trans_vec_x,trans_vec_y,trans_vec_z],...
    'character')
end

axislabel_translation_slider.m

function axislabel_translation_slider
% Create UI figure window and components

global AXISALIGN_TRANS_A AXISALIGN_TRANS_B
if isempty(AXISALIGN_TRANS_A), AXISALIGN_TRANS_A = 1; end
if isempty(AXISALIGN_TRANS_B), AXISALIGN_TRANS_B = 1; end

h_f = uifigure('Position',[100 100 350 275]);

% cg = uigauge(fig,'Position',[100 100 120 120]);

sld1 = uislider(h_f,...
    'Position',[50 200 250 3],...
    'Limits',[0 5],...
    'ValueChangingFcn',@(sld,event) sliderMoving1(event));
sld1.Value = 1;
sld2 = uislider(h_f,...
    'Position',[50 75 250 3],...
    'Limits',[0 5],...
    'ValueChangingFcn',@(sld,event) sliderMoving2(event));
sld2.Value = 1;
end

% Create ValueChangingFcn callback
function sliderMoving1(event)
global AXISALIGN_TRANS_A
AXISALIGN_TRANS_A = event.Value;
align_axislabel([],gca);
end

function sliderMoving2(event)
global AXISALIGN_TRANS_B
AXISALIGN_TRANS_B = event.Value;
align_axislabel([],gca);
end

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

勉为其难免免

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

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

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

打赏作者

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

抵扣说明:

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

余额充值