How to make the quiver() arrow head size fixed?

Hi all-
When I use the quiver() function to plot an arrow in my scatterplot, I noticed that the size of the arrow head is different, depending on how big the arrow itself is (its length basically).
Any ideas on how to make the arrow head size fixed independent of the arrow length? Or if it is at least possible to do?
Best.

1 comentario

muhkuhmw
muhkuhmw el 16 de Oct. de 2017
Editada: muhkuhmw el 16 de Oct. de 2017
Did you find a good solution? I am struggling with the same problem. I willl possible try this: stackoverflow - In Matlab how do I change the arrow head style in quiver plot?

Iniciar sesión para comentar.

Respuestas (5)

KSSV
KSSV el 29 de Ag. de 2017
Editada: Adam Danz el 7 de Abr. de 2023

3 votos

3 comentarios

muhkuhmw
muhkuhmw el 16 de Oct. de 2017
How is this supposed to help? The only match for Head and Size is
MaxHeadSize Maximum size of arrowhead, specified as a scalar value in units relative to the length of the arrow.
This doesn't help me enlarging my too small arrow heads. Neither does any of the other parameters.
I agree with you.

Iniciar sesión para comentar.

V.G. de Bie
V.G. de Bie el 14 de Nov. de 2017

3 votos

Just divide MaxHeadSize by the length of the arrow, then the heads will be the same size.

3 comentarios

KAE
KAE el 11 de Feb. de 2020
How to do this if I am plotting many vectors at once? Do I have to loop through all my datapoints and do a separate call to quiver?
Rik
Rik el 11 de Feb. de 2020
There doesn't seem to be a method to make the head a fixed size, so it does indeed look like you need to call quiver for every data point. I would suggest grouping them by approximate size so you don't have that many graphics objects.
Iuliu Ardelean
Iuliu Ardelean el 7 de Jun. de 2022
Doesn't seem to work?

Iniciar sesión para comentar.

broken_arrow
broken_arrow el 24 de Sept. de 2021
Editada: broken_arrow el 27 de Sept. de 2021
I agree quiver and quiver3 should have a built in option for constant arrow head size (@MathWorks Support Team). Dividing by the length doesn't work properly for me (doesn't really yield a constant head size). Here is a function I wrote to solve the problem for quiver3:
function out_arrowhandles =...
quiver3addarrowheads(in_quivhandle,in_arrowheadlength,in_arrowtipangle)
% Adds arrow heads with constant size to quiver3 plot.
% Arrow heads have the same inclination relative to the z plane as the vectors.
%
% Input arguments:
% in_quivhandle: Handle of quiver plot to be appended
% in_arrowheadlength: Desired arrow head length in vector length units
% in_arrowtipangle: Desired arrow head tip angle in degrees (°)
%
% Output arguments:
% out_arrowhandles: Handles to arrow head lines
X = reshape(in_quivhandle.XData,1,[]);
Y = reshape(in_quivhandle.YData,1,[]);
Z = reshape(in_quivhandle.ZData,1,[]);
U = reshape(in_quivhandle.UData,1,[]);
V = reshape(in_quivhandle.VData,1,[]);
W = reshape(in_quivhandle.WData,1,[]);
aux_Xend = X + U;
aux_Yend = Y + V;
aux_Zend = Z + W;
aux_orthvectors = cross([U;V;W],[U;V;W+1]);
aux_orthvectors = aux_orthvectors ./ vecnorm(aux_orthvectors);
if ~any(aux_orthvectors,1)
aux_orthvectors(:,~any(aux_orthvectors,1)) = [1;0;0];
end
aux_arrowtips1 = in_arrowheadlength * (-[U;V;W] ./ vecnorm([U;V;W]) -...
tand(in_arrowtipangle)*aux_orthvectors);
aux_arrowtips2 = aux_arrowtips1 +...
2*in_arrowheadlength*tand(in_arrowtipangle)*aux_orthvectors;
aux_arrowhandle1 = quiver3(in_quivhandle.Parent,aux_Xend,aux_Yend,aux_Zend,...
aux_arrowtips1(1,:),aux_arrowtips1(2,:),aux_arrowtips1(3,:),...
'LineWidth',in_quivhandle.LineWidth,'Color',in_quivhandle.Color,...
'ShowArrowHead','off','AutoScale','off');
aux_arrowhandle2 = quiver3(in_quivhandle.Parent,aux_Xend,aux_Yend,aux_Zend,...
aux_arrowtips2(1,:),aux_arrowtips2(2,:),aux_arrowtips2(3,:),...
'LineWidth',in_quivhandle.LineWidth,'Color',in_quivhandle.Color,...
'ShowArrowHead','off','AutoScale','off');
out_arrowhandles = [aux_arrowhandle1 aux_arrowhandle2];
end
Run the function directly after quiver3 (with 'AutoScale' and 'ShowArrowHead' set to 'off') or combine both into a customquiver3 function if you want an all in one solution. To adapt the function for 2D quiver, append your 2D input vectors by Z=W=0 (cross only works on 3D vectors) and discard the z coordinate (0) before plotting. If you want a different inclination of the arrow heads, modify the cross product accordingly.
Also note that the arrow heads will look "skewed" if daspect of x and y axis differs.

3 comentarios

Rik
Rik el 24 de Sept. de 2021
It looks like you should post this on the File Exchange. That is probably a better place to share your functions.
broken_arrow
broken_arrow el 24 de Sept. de 2021
I think it may not be polished well enough for FEX (which already has more complex "arrow plotting" functions like https://www.mathworks.com/matlabcentral/fileexchange/14056-arrow3). This is more of a quick "copy and paste" solution - and a reminder for Mathworks to provide a native option ;)
Rik
Rik el 24 de Sept. de 2021
It has documentation and a rudimentary form of input validation, I woul say that makes it more polished than a third of the submissions. You don't have to go to the same lengths as I currently do before getting on the file exchange.
But it's your call of course.

Iniciar sesión para comentar.

Francesco Bernardini
Francesco Bernardini el 25 de Mzo. de 2024
Editada: Francesco Bernardini el 25 de Mzo. de 2024
Maybe it's too naive, but when you pass U and V why don't you just divide by the norm of [U,V]?
You will be always plotting unit vectors with the right orientation, and if you need them longer for graphical purposes you just rescale everything by some constant factor.
Here a sample function that I defined to update dynamically the graphic handles of a set of points with quiver:
function updateHandles(handlePoint,Point,handleArrow,Arrow,scaling)
%This function updates the graphic handles of a point and of its applied vector
set(handlePoint, "XData", Point(1), "YData", Point(2));
if(norm(Arrow)~=0)
set(handleArrow, "XData", Point(1), "YData", Point(2),...
"UData",scaling * Arrow(1) / norm(Arrow), "VData", scaling * Arrow(2) / norm(Arrow));
else
set(handleArrow, "XData", Point(1), "YData", Point(2),...
"UData",0, "VData", 0);
end
end
Doug
Doug el 10 de Jun. de 2024

0 votos

I ended up bypassing the quiver functionality altogether and drawing individual arrows where I wanted them. The comment by Olle Trollberg on 29 Aug 2023 from here:
certainly helped me figure out how to do it. Annotations coordinates are in Figure space, not Axes space, so you need to convert from one to the other. For my application determining where to place each arrow was only a few lines of code in a for loop in which I hand-calculated the gradients between points and then drew the arrow.

Categorías

Más información sobre Vector Fields en Centro de ayuda y File Exchange.

Preguntada:

el 28 de Ag. de 2017

Comentada:

el 25 de Oct. de 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by