Перейти к содержанию
    

Как в матлабе нарисовать стрелочки вместо линий? (Matlab arrow plot)

Здравствуйте. Вопрос такой. Вот есть у меня вектор значений X и вектор значений Y какого-то процесса, который последовательно передвигается от одной точки к другой. Если я напишу plot(X, Y), то мне нарисует изломанную кривую из прямых линий, соединяющих мои точки в X и Y. Вроде мне так и надо. Но мне бы ещё к этому в конце каждой линии, соединяющей мои точки в X и Y, пририсовать хвостик у стрелочки. А желательно ещё и номерок подписать, какая это по счёту стрелочка. Чтобы я понимал, в какой очерёдности и в каком направлении движется процесс.

Я попробовал annotation. И всё бы хорошо, но там точные координаты не задать, там либо в пикселях, либо в см и т.п., короче привязано к самому окошку графика. А мне бы в единицах измерения моего процесса.

feather, quiver смотрел - вроде не то.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 01.09.2022 в 07:44, Krys сказал:

А мне бы в единицах измерения моего процесса

text

В 01.09.2022 в 07:44, Krys сказал:

Но мне бы ещё к этому в конце каждой линии, соединяющей мои точки в X и Y, пририсовать хвостик у стрелочки

Тут скорее всего только самому, комбинируя plot и hold on/off. Вот как тут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вектора значений X и Y известны

x = [3.2, 1, 2.5, 7.123456, 3, 2];
y = [2.1, 3, 6, 4, 3.5, 2];

вычисляем значения, необходимые для функции quiver

dx = diff(x);
dy = diff(y);

выводим график со стрелочками

quiver(x(1:end-1),y(1:end-1),dx,dy,0);
grid on;
xlim([0;10]);
ylim([0;10]);

image.thumb.png.00595e971d36f9fdaf925a3686e3f0e8.png

выводим очерёдность

for i = 1:numel(x)
    text(x(i),y(i),num2str(i));
end

image.thumb.png.e7e8c55cb617bd5612d8a76cdc701040.png

 

как вариант можно вывести направление переходов по середине отрезков

dx = diff(x);
dy = diff(y);

quiver(x(1:end-1),y(1:end-1),dx/2,dy/2,0);
hold on;
plot(x,y,'.-');
hold off;
grid on;
xlim([0;10]);
ylim([0;10]);

for i = 1:numel(x)
    text(x(i),y(i),num2str(i));
end

image.thumb.png.b33f622dc9bac38b1d8e3d675ff599f3.png

в некоторых случаях так нагляднее

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

On 9/2/2022 at 12:55 AM, Самурай said:

Вот как тут.

Спасибо. Хотел напрямую слямзить этот код. Но он бажный. В некоторых направлениях стрелки рисует нормально, в некоторых коряво. В результате свой написал (см.ниже).

 

 

On 9/4/2022 at 2:03 PM, stealthisname said:
quiver

Огромное спасибо за подсказку. Да, я смотрел эту функцию, но не так понял. Посчитал, что 3й и 4й аргументы это модуль и угол вектора. Испугался полярных координат, что типа некогда искать функции по пересчёту.
В результате по примеру по ссылке из второго сообщения сделал свою функцию:

Spoiler
%% function to generate x and y arrays for plot function to plot lines with
%%  arrows (vectors)
% INPUTS:
%   X, Y - vectors of x and y as it could be plotted by plot function
%       (without arrows, as is)
% OUTPUTS:
%   xVec, yVec - arrays (vectors) with x and y coodinates for plot function
%       to plot lines with arrows
%   xVecM, yVecM - matrix of vectors, each column contains one line with
%       arrow (one vector). It can be useful to plot each vector separately
%       in different plot function in a loop
%   xArrow, yArrow - arrays (vectors) with x and y coordinates for plot
%       function to plot only arrows (can be useful to plot arrows with
%       anoter plot function call with different color, for example)

function [xVec, yVec, xVecM, yVecM, xArrow, yArrow] = pvec(X, Y)

arLenFac = 0.05;  % factor of lenght of arrow relative to vector length
arAngDeg = 20;    % angle of arrow relative to vector line in degree
arAng = deg2rad(arAngDeg);
vecSize = 6; % number of points to plot one vector
nPoints = length(X);
vecM = zeros(vecSize, nPoints-1);
arrowM = vecM;

% conversion inputs into complex numbers and then finding length and angle
inCompl = complex(X, Y);
inDif = diff(inCompl);
angVec = angle(inDif);
lenVec = abs(inDif);

% arrow up and down parts angles
upArAng = angVec + arAng;
dnArAng = angVec - arAng;

arLen = lenVec * arLenFac; % arrow length

% up and down arrow parts Cartesian coordinates from origin, that means
%   coordinates diff
[upArDifX, upArDifY] = pol2cart(upArAng, arLen);
[dnArDifX, dnArDifY] = pol2cart(dnArAng, arLen);
upArDifCompl = complex(upArDifX, upArDifY);
dnArDifCompl = complex(dnArDifX, dnArDifY);


% full coordinates of up and down parts of arrow from the end of vector line
upArCompl = inCompl(2 : end) - upArDifCompl;
dnArCompl = inCompl(2 : end) - dnArDifCompl;

% filling the points for plot function to draw full vector with arrow (can
%   be used to plot vectors one-by-one)
vecM(1, :) = inCompl(1 : end - 1);
vecM(2, :) = inCompl(2 : end);
vecM(3, :) = upArCompl;
vecM(4, :) = NaN;
vecM(5, :) = dnArCompl;
vecM(6, :) = inCompl(2 : end);

% only arrows preparation
arrowM(1, :) = NaN;
arrowM(2 : end, :) = vecM(2 : end, :);

% reshaping 2-dim matrix into 1-dim to plot
vec = reshape(vecM, [], 1);
arrows = reshape (arrowM, [], 1);

% final separation for x and y part for output variables
xVecM = real(vecM);
yVecM = imag(vecM);

xVec = real(vec);
yVec = imag(vec);

xArrow = real(arrows);
yArrow = imag(arrows);

end

 

И потом увидел ваше сообщение. Да, quiver в принципе повторяет то, что я сделал, только куда проще.

К сожалению, общая проблема моей функции и quiver в том, что стрелки выглядят красиво только при одинаковом масштабе по вертикали и горизонтали. А у меня это просто ужасно разные масштабы, и стрелки вообще ломают весь график, на графике видно только стрелки ))) Пока не представляю, как исхитриться, чтобы при моих условиях красиво было нарисовано.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

пробуем работу Вашей функции pvec на неудобных данных (Y много больше X )

x = [3.2, 1, 2.5, 7.123456, 3, 2];
y = [2.1, 3, 6, 4, 3.5, 2]*100;

[xVec, yVec] = pvec(x,y);
plot(xVec,yVec);
grid on;

for i = 1:numel(x)
    text(x(i),y(i),num2str(i));
end

image.thumb.png.9288a4bf9ed8b08383f3fcdc634a9580.png

явно не то, что хотелось, и чем больше разница по масштабу у осей - тем страшнее результат

идём другим путём

строим исходный график без стрелочек, для вычисления масштабов

plot(x,y);

если на результирующей картинке этот график не единственный, то добавляем другие построения, если они могут изменить размеры осей

вычисляем отношение масштабов для нашего графика

norm_coef = diff(xlim)/diff(ylim);

компенсируем разницу в масштабах

if(norm_coef<0)
    x_norm = x/norm_coef;
    y_norm = y;
    [xVec, yVec] = pvec(x_norm,y_norm);
    xVec = xVec*norm_coef;
    yVec = yVec;
else
    x_norm = x;
    y_norm = y*norm_coef;
    [xVec, yVec] = pvec(x_norm,y_norm);
    xVec = xVec;
    yVec = yVec/norm_coef;
end

выводим график со стрелочками

plot(xVec,yVec);
grid on;

for i = 1:numel(x)
    text(x(i),y(i),num2str(i));
end

image.thumb.png.8db3fe98a3a7a5da323924baf7fbb4e5.png

проверяем, что всё работает при другом отношении масштабов (X много больше Y )

x = [3.2, 1, 2.5, 7.123456, 3, 2]*123;
y = [2.1, 3, 6, 4, 3.5, 2];

plot(x,y);
norm_coef = diff(xlim)/diff(ylim);

if(norm_coef<0)
    x_norm = x/norm_coef;
    y_norm = y;
    [xVec, yVec] = pvec(x_norm,y_norm);
    xVec = xVec*norm_coef;
    yVec = yVec;
else
    x_norm = x;
    y_norm = y*norm_coef;
    [xVec, yVec] = pvec(x_norm,y_norm);
    xVec = xVec;
    yVec = yVec/norm_coef;
end

plot(xVec,yVec);
grid on;

for i = 1:numel(x)
    text(x(i),y(i),num2str(i));
end

image.thumb.png.e7e35bf046870b7c4fc3d0eecbf6b9e3.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, stealthisname said:
Spoiler

image.thumb.png.9288a4bf9ed8b08383f3fcdc634a9580.png

 

Вот-вот, именно это у меня и получалось )))

 

2 hours ago, stealthisname said:

идём другим путём

Спасибо за подсказку! Попробую разобраться )

Я так понимаю, вы в матлабе далеко не новичок. Не загляните в тему? https://electronix.ru/forum/index.php?app=forums&module=forums&controller=topic&id=168358

9 minutes ago, Krys said:

Попробую разобраться )

Разобрался! Очень просто оказывается. Как здорово, что вам приходят в голову такие вещи, со стороны кажется: ну почему я сам не догадался ))

2 hours ago, stealthisname said:

пробуем работу Вашей функции pvec

Я так понимаю, можно и с помощью quiver такой же финт провернуть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Krys said:

Разобрался!

На основе вашей подсказки доработал свою функцию (изменения под комментариями со словами aspect ratio):

Spoiler
%% function to generate x and y arrays for plot function to plot lines with
%%  arrows (vectors)
% INPUTS:
%   X, Y - vectors of x and y as it could be plotted by plot function
%       (without arrows, as is)
% OUTPUTS:
%   xVec, yVec - arrays (vectors) with x and y coodinates for plot function
%       to plot lines with arrows
%   xVecM, yVecM - matrix of vectors, each column contains one line with
%       arrow (one vector). It can be useful to plot each vector separately
%       in different plot function in a loop
%   xArrow, yArrow - arrays (vectors) with x and y coordinates for plot
%       function to plot only arrows (can be useful to plot arrows with
%       anoter plot function call with different color, for example)
%   aspRat - aspect ratio (X:Y)

function [xVec, yVec, xVecM, yVecM, xArrow, yArrow, aspRat] = pvec(X, Y)

arLenFac = 0.05;  % factor of lenght of arrow relative to vector length
arAngDeg = 20;    % angle of arrow relative to vector line in degree
arAng = deg2rad(arAngDeg);
vecSize = 6; % number of points to plot one vector
nPoints = length(X);
vecM = zeros(vecSize, nPoints-1);
arrowM = vecM;

% changing to equal aspect ratio
[xMin, xMax] = bounds(X);
[yMin, yMax] = bounds(Y);
aspRat = (xMax - xMin) / (yMax - yMin);
X = X / aspRat;

% conversion inputs into complex numbers and then finding length and angle
inCompl = complex(X, Y);
inDif = diff(inCompl);
angVec = angle(inDif);
lenVec = abs(inDif);

% arrow up and down parts angles
upArAng = angVec + arAng;
dnArAng = angVec - arAng;

arLen = lenVec * arLenFac; % arrow length

% up and down arrow parts Cartesian coordinates from origin, that means
%   coordinates diff
[upArDifX, upArDifY] = pol2cart(upArAng, arLen);
[dnArDifX, dnArDifY] = pol2cart(dnArAng, arLen);
upArDifCompl = complex(upArDifX, upArDifY);
dnArDifCompl = complex(dnArDifX, dnArDifY);


% full coordinates of up and down parts of arrow from the end of vector line
upArCompl = inCompl(2 : end) - upArDifCompl;
dnArCompl = inCompl(2 : end) - dnArDifCompl;

% filling the points for plot function to draw full vector with arrow (can
%   be used to plot vectors one-by-one)
vecM(1, :) = inCompl(1 : end - 1);
vecM(2, :) = inCompl(2 : end);
vecM(3, :) = upArCompl;
vecM(4, :) = NaN;
vecM(5, :) = dnArCompl;
vecM(6, :) = inCompl(2 : end);

% returning to original aspect ratio
vecM = complex(real(vecM) * aspRat, imag(vecM));

% only arrows preparation
arrowM(1, :) = NaN;
arrowM(2 : end, :) = vecM(2 : end, :);

% reshaping 2-dim matrix into 1-dim to plot
vec = reshape(vecM, [], 1);
arrows = reshape (arrowM, [], 1);

% final separation for x and y part for output variables
xVecM = real(vecM);
yVecM = imag(vecM);

xVec = real(vec);
yVec = imag(vec);

xArrow = real(arrows);
yArrow = imag(arrows);

end

 

И вызывающий её код теперь выглядит вот так:

Spoiler
[~, ~, ~, ~, xArrow, yArrow, aspRat] = pvec(coe, res);
figure; hold on;
daspect([aspRat 1 1]);
plot(coe, res);
plot(xArrow, yArrow);
dx = diff(coe);
dy = diff(res);
str = num2str((1 : length(coe)-1).');
text(coe(1:end-1), res(1:end-1), str);
hold off;

 

Теперь выглядит неплохо:

Spoiler

Screenshot_5.png.b6f92ddf284b1867e5d83aeec8180b3f.png

Так что в принципе вопрос можно считать решённым.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...