Используйте timer
Как сказано в комментариях, единственный способ контролировать время в MATLAB - это использовать их класс timer
. Даже если это ограничено, Mathworks прямо заявляет, что вы не можете ожидать точности до миллисекунды.
Следующий код приближается к тому, что вы просили. Он создает таймер, который запускает каждый period
и выполняет функцию (которая будет вращать сферу).
Хитрость заключается в том, чтобы определить period
(называемый TimeIncrement
в коде) и шаг углового вращения, чтобы движение было плавным и достигалось за заданное время.
Даже с таймером, и особенно для малого целевого времени, он не будет точным с точностью до миллисекунды. Я установил minTimeIncrement
(на основе моей машины), который используется для ослабления числа оборотов ( увеличение углового шага ) в случае, если TimeIncrement
недостаточно для рендеринга одного поворота. Возможно, вам придется настроить его для вашей собственной машины.
%% Create and display the sphere
clear all,clf reset,clc, close all
figure
[x,y,z] = sphere(270) ;
s = surf(x,y,z,z,'EdgeColor','none');
axis vis3d
xlabel('X-axis')
ylabel('Y-axis')
zlabel('Z-axis')
%% Parameters
minTimeIncrement = 0.040 ; % I worked that out on my machine.
% You may have to adjust for your
TotalRotationTime = 3.5 ; % in second
Nangles = 360 ; % number of angle rotations to complete a full turn
TimeIncrement = TotalRotationTime / Nangles ; % Time step between each rotation
AngularIncrement = 360 / Nangles ; % angle to rotate at each iteration
% Here we make sure to respect the timing. If the number of rotation
% increment does not fit into the total time allowed, the rotation increments
% are extended so they will be less of them.
if TimeIncrement < minTimeIncrement
warning('Period too small, the angle increment will be adjusted')
TimeIncrement = minTimeIncrement ;
Nangles = TotalRotationTime / TimeIncrement ;
AngularIncrement = 360 / Nangles ; % angle to rotate at each iteration
end
%% Create the timer and start it
t = timer ;
t.ExecutionMode = 'fixedRate' ;
t.Period = TimeIncrement ;
t.TimerFcn = @(htimer,evt) UpdateSphere(htimer,evt,s,AngularIncrement) ;
t.StopFcn = 'delete(t)' ; % for self cleanup
start(t) ;
Редактировать: Извините, только что понял, что забыл опубликовать код для функции обратного вызова. Код для UpdateSphere.m
:
function UpdateSphere( ht , evt , s , ang_increment )
%UpdateSphere Rotate the sphere and update the title display
%% Define a few persistent variables
persistent currentAngle ;
persistent StartTime ;
%% Initialise or update persistent variables
if isempty(currentAngle)
currentAngle = 0 + ang_increment ;
% else
% currentAngle = currentAngle + ang_increment ;
end
if isempty(StartTime)
StartTime = tic ;
end
%% do the rotation
% To insure we will not go over 360 degrees
ang_increment = min(ang_increment , 360 - currentAngle) ;
currentAngle = currentAngle + ang_increment ;
rotate(s,[1,1,1],ang_increment)
strTitle = sprintf('Angle = %5.1f ° / Time = %7.3f s',currentAngle,toc(StartTime)) ;
title(strTitle);
drawnow
%% Stop the timer and reset counter if we reached a full rotation
if currentAngle >= 360
currentAngle = 0 ;
StartTime = [] ;
stop(ht) ;
end
end
![enter image description here](https://i.stack.imgur.com/0m0it.gif)