Krys 2 September 1, 2022 Posted September 1, 2022 · Report post Здравствуйте. Вопрос такой. Вот есть у меня вектор значений X и вектор значений Y какого-то процесса, который последовательно передвигается от одной точки к другой. Если я напишу plot(X, Y), то мне нарисует изломанную кривую из прямых линий, соединяющих мои точки в X и Y. Вроде мне так и надо. Но мне бы ещё к этому в конце каждой линии, соединяющей мои точки в X и Y, пририсовать хвостик у стрелочки. А желательно ещё и номерок подписать, какая это по счёту стрелочка. Чтобы я понимал, в какой очерёдности и в каком направлении движется процесс. Я попробовал annotation. И всё бы хорошо, но там точные координаты не задать, там либо в пикселях, либо в см и т.п., короче привязано к самому окошку графика. А мне бы в единицах измерения моего процесса. feather, quiver смотрел - вроде не то. Quote Share this post Link to post Share on other sites More sharing options...
Самурай 9 September 1, 2022 Posted September 1, 2022 · Report post В 01.09.2022 в 07:44, Krys сказал: А мне бы в единицах измерения моего процесса text В 01.09.2022 в 07:44, Krys сказал: Но мне бы ещё к этому в конце каждой линии, соединяющей мои точки в X и Y, пририсовать хвостик у стрелочки Тут скорее всего только самому, комбинируя plot и hold on/off. Вот как тут. 1 Quote Share this post Link to post Share on other sites More sharing options...
stealthisname 7 September 4, 2022 Posted September 4, 2022 · Report post вектора значений 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]); выводим очерёдность for i = 1:numel(x) text(x(i),y(i),num2str(i)); end как вариант можно вывести направление переходов по середине отрезков 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 в некоторых случаях так нагляднее 1 Quote Share this post Link to post Share on other sites More sharing options...
Krys 2 September 7, 2022 Posted September 7, 2022 · Report post 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 в том, что стрелки выглядят красиво только при одинаковом масштабе по вертикали и горизонтали. А у меня это просто ужасно разные масштабы, и стрелки вообще ломают весь график, на графике видно только стрелки ))) Пока не представляю, как исхитриться, чтобы при моих условиях красиво было нарисовано. Quote Share this post Link to post Share on other sites More sharing options...
stealthisname 7 September 7, 2022 Posted September 7, 2022 · Report post пробуем работу Вашей функции 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 явно не то, что хотелось, и чем больше разница по масштабу у осей - тем страшнее результат идём другим путём строим исходный график без стрелочек, для вычисления масштабов 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 проверяем, что всё работает при другом отношении масштабов (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 1 Quote Share this post Link to post Share on other sites More sharing options...
Krys 2 September 7, 2022 Posted September 7, 2022 · Report post 2 hours ago, stealthisname said: Spoiler Вот-вот, именно это у меня и получалось ))) 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 такой же финт провернуть? Quote Share this post Link to post Share on other sites More sharing options...
Krys 2 September 7, 2022 Posted September 7, 2022 · Report post 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 Так что в принципе вопрос можно считать решённым. Quote Share this post Link to post Share on other sites More sharing options...