如何在MATLAB中平滑旋转3D绘图?

时间:2010-12-02 19:51:35

标签: matlab rotation plot smooth

如果我尝试使用

使用plot3围绕我当前的数字旋转相机
while true; camorbit(0.9,-0.1); drawnow; end

然后即使在8核MacPro上,旋转也会暂时挂起一段时间(example)。

我可以顺利吗?

EDIT1:

虽然我的原始问题还没有解决方案,但我设法用getframe函数制作了一部更好的电影。但它不允许记录徒手旋转,并且在MATLAB2010b for Mac中存在很大的错误。

%# fix wrong figure position in MATLAB2010b for Mac - depends on your layout
correctedPosition = get(gcf,'Position') + [21 -125 0 0];

fps = 60; sec = 10;

vidObj = VideoWriter('newfile.avi');
vidObj.Quality = 100;
vidObj.FrameRate = fps;

open(vidObj);
for i=1:fps*sec
  camorbit(0.9,-0.1);
  writeVideo(vidObj,getframe(gcf, correctedPosition));
end
close(vidObj);

EDIT2:

我在MATLAB Central创建了一个类似的主题。

EDIT3:

您可以自己尝试downloading one of my figures

3 个答案:

答案 0 :(得分:4)

我会说你正在绘制的大量积分导致经济放缓。一个选项是缩减采样..也可以使用较低级别的函数进行绘制(检查this related post以获得plot3 / scatter3 / line performance的比较)。

考虑以下针对速度优化的动画:

[X Y Z] = sphere(64);
X = X(:); Y = Y(:); Z = Z(:);

%# set-up figure
hFig = figure('Backingstore','off', 'renderer','zbuffer');

%# use lower-level function LINE
line(0.50*[X,X], 0.50*[Y,Y], 0.50*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','r')
line(0.75*[X,X], 0.75*[Y,Y], 0.75*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','g')
line(1.00*[X,X], 1.00*[Y,Y], 1.00*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','b')
view(3)

%# freeze the aspect ratio to override stretch-to-fill behaviour
axis vis3d

%# fix the axes limits manually
%#set(gca, 'xlim',[-1 1], 'ylim',[-1 1], 'zlim',[-1 1])
axis manual

%# maybe even remove the tick labels
%set(gca, 'xticklabel',[], 'yticklabel',[], 'zticklabel',[])

%# animate (until figure is closed)
while ishandle(hFig); camorbit(0.9,-0.1); drawnow; end

alt text

注意我们如何使用Z缓冲区renderer,并关闭Backingstore属性。


编辑:

如果我理解正确,你要做的是录制一个截屏视频(使用第三方应用),同时手动旋转图形,但在你的情况下,这些手动旋转是“跳跃”。另一方面,在一个while循环中用CAMORBIT / VIEW动画你的数字正在顺利运行......

我提出了另一种解决方案:首先使用鼠标旋转图形,然后在每个步骤(方位角,仰角)上写下这些视图配置。然后,您可以在录制视频时使用VIEW功能重放它们,例如:

v = [...];   %# matrix where each row specify Az/El of view
for i=1:size(v,1)
    view( v(i,:) )
    drawnow
end

缺点是你必须用小步骤按下/旋转/释放(ROTATE3D对象不会暴露鼠标动作事件)

我写了一个简单的函数来帮助你完成这个过程。它加载保存的图形,启用3d旋转,并跟踪每一步的中间位置。完成后,按“完成”按钮返回视图列表...

function v = rotationDemo(figFileName)
    views = [];                     %# list of views (Az,El)

    hFig = hgload(figFileName);     %# load the saved figure

    views(1,:) = get(gca,'View');   %# store initial view

    %# add a button, used to terminate the process
    hButton = uicontrol('Style','pushbutton', 'Position',[400 1 80 20], ...
                        'String','Done?', 'Callback',@buttonCallback);
    set(hFig, 'Toolbar','figure')   %# restore toolbar

    %# start 3d rotation, and handle post-callback to record intermediate views
    h = rotate3d(hFig);             %# get rotation object
    set(h, 'ActionPostCallback',@rotateCallback)
    set(h, 'Enable','on')           %# enable rotation

    msgbox('Rotate the view step-by-step', 'rotate3d', 'warn', 'modal')

    uiwait(hFig)                    %# wait for user to click button
    delete(hButton)                 %# delete button on finish
    set(h, 'Enable','off')          %# disable rotation
    v = round(views);               %# return the list of views

    %# callback functions
    function rotateCallback(o,e)
        views(end+1,:) = get(e.Axes,'View');  %# add current view to list
    end
    function buttonCallback(o,e)
        uiresume(gcbf)                        %# uiresume(hFig)
    end
end

alt text

你可以调用上面的函数,然后重放动画:

v = rotationDemo('smooth_rotation.fig');
for i=1:size(v,1)
    view(v(i,:))
    drawnow
end

我们可以通过简单插值来平滑过渡:

v = rotationDemo('smooth_rotation.fig');
n = size(v,1);
nn = linspace(1,n,100)';     %'# use 100 steps
vv = round( [interp1(v(:,1),nn) interp1(v(:,2),nn)] );
for i=1:size(vv,1)
    view(vv(i,:))
    DRAWNOW                  %# or PAUSE(..) to slow it down
end

作为旁注,我应该提到ROTATE3D和CAMORBIT有不同的效果。 ROTATE3D更改当前轴的View属性,而CAMORBIT控制当前轴的相机属性CameraTarget / CameraPosition / CameraUpVector

答案 1 :(得分:2)

我认识到你在常规MATLAB图上所说的相同的抽搐动作。但是当我尝试运行Amro的代码,创建了一部电影(* .AVI)时,它在我的Mac笔记本上看起来也很流畅。

我使用的电影制作代码如下:

%在制作电影时添加了“关闭”数字的“可见”属性(虽然我不确定这是否会使情况更好),如下所示:

  

hFig = figure('Backingstore','off','visible','off','renderer','zbuffer');

%然后,我用一个简单的AVI生产循环替换了Amro的while循环,如下所示:

  

aviobj = AVIFILE( 'test.avi'); %创建AVI文件

     

表示I = 1:360

     

camorbit(0.9,-0.1);的DrawNow;

     

aviobj = ADDFRAME(aviobj,hFig); %将帧添加到AVI文件

     

结束

     

aviobj =接近(aviobj); %关闭AVI文件

     

接近(hFig); %close hFig

问题:   在渲染图形之前,是否有助于抽取某些点或创建密度图?

[参考文献。关于各种渲染选项:http://www.mathworks.com/support/tech-notes/1200/1201.html]

我希望上面的评论会有所帮助。

答案 2 :(得分:1)

我不知道这是否会对您的问题有所帮助,但由于某种原因,我使用pause(0.001)而不是drawnow取得了更好的成功,以强制更新图形窗口

您可能还会看到rotate3d是否更快。

核心数量并不重要,因为matlab中的许多函数都不支持多线程。


解决方法是像现在一样继续,但将图形窗口写入电影文件。然后你可以播放电影。

相关问题