I am working on the following code:
function myquiver
clc
R=2.3;
C=1.2;
V=@(t) 3*sqw(t,1,10);
F=@(t,VC) (V(t)-VC)/(R*C);
[T,VC]=meshgrid(linspace(0,25,10),linspace(0,0.5,10));
S=(3*sqw(T,1,10)-VC)/(R*C);
L=sqrt(1+S.^2);
quiver(T,VC,1./L,S./L,'r','ShowArrowhead','off','AutoScale','off')
axis([0,25,0,0.5])
shg
function y=sqw(t,T,d)
r=mod(t,T);
y=(r<d*T/100);
This produces the following image:
Now, what I want to do is make each of the quiver arrows the same length based on the axes. I don't want to change axis([0,25,0.05]). That is exactly what I want. But how can I scale each quiver arrow so that they are all the same length in this particular image?
I am hoping to see an idea that I can use should I do another plot with say axis([0,10,-30,50]).
I'm hoping to see a full code example and an image.
Thanks.
Let's consider two coordinate systems. First, the world coordinate system, which the data are in. For example 1./L
and S./L
are world coordinate representations. Second, the plot coordinate system which we define such that one unit of distance is the width and height of the plot window. I.e. a horizontal vector with unit length in plot coordinates would exactly span the entire plot width, and similarly a vertical vector with unit length in plot coordinates would exactly span the entire plot height.
What you appear to be asking is how to scale each vector so that they are all some fixed length in plot coordinates. It's not difficult to see that for some vector defined in world coordinates (x_world, y_world)
the following functions transform the world coordinate to plot coordinates.
x_plot = x_world / x_span
y_plot = y_world / y_span
Where x_span
and y_span
are the width and height of the plot in world coordinates (in your case 25
and 0.5
respectively).
We would like to know what scaling factor to apply to x_world
and y_world
so that (x_plot, y_plot)
is some fixed length. Observe that we must apply the same scaling factor in x and y to retain the original direction. Mathematically this can be described by the equation
d = sqrt((s*x_world / x_span)^2 + (s*y_plot / y_span)^2)
where d
is the desired length in plot coordinates and s
is the scale factor we need to determine.
Solving the equation for s
we get
s = d/sqrt((x_world / x_span)^2 + (y_plot / y_span)^2)
which gives us a solution.
function myquiver
xmin = 0; xmax = 25;
ymin = 0; ymax = 0.5;
R=2.3;
C=1.2;
V=@(t) 3*sqw(t,1,10);
F=@(t,VC) (V(t)-VC)/(R*C);
[T,VC]=meshgrid(linspace(xmin,xmax,10),linspace(ymin,ymax,10));
S=(3*sqw(T,1,10)-VC)/(R*C);
L=sqrt(1+S.^2);
x_span = xmax - xmin;
y_span = ymax - ymin;
% Compute the scale factor so that vectors are 10% of plot window
d = 0.1;
X_world = 1./L;
Y_world = S./L;
s = d ./ sqrt((X_world / x_span).^2 + (Y_world / y_span).^2);
quiver(T,VC,s.*X_world,s.*Y_world,'r','ShowArrowhead','off','AutoScale','off')
axis([xmin,xmax,ymin,ymax])
% force the axis to be square
axis('square');
function y=sqw(t,T,d)
r=mod(t,T);
y=(r<d*T/100);
One thing to note here is that we used axis('square')
. This was necessary to ensure an equal scaling relationship between plot coordinates and screen/pixel coordinates. Since this may not be desirable (maybe we don't want a square plot!), then we can fix this by dividing x_span
by the aspect ratio of the axis (in pixels). Unfortunately, we can't get the aspect ratio before the plot is created. In order to implement the generalized solution we basically have two options.
I chose to pursue option two. First I plotted without axis('square')
, then played with the window until it was about the same size as the original figure that you posted. Next, I queried the position of the figure and aspect ratio as follows
>> get(gcf, 'Position')
ans = 666 223 672 505
>> set(gca, 'Units', 'Pixels');
>> get(gca, 'Position')
ans = 88.3600 56.5500 520.8000 411.5750
This tells us that for this figure position the aspect ratio of the axis in pixels is 520.8 / 411.575
. Using this knowledge, we modify the function to plot equal length vectors for this non-square axis as follows.
function myquiver
xmin = 0; xmax = 25;
ymin = 0; ymax = 0.5;
R=2.3;
C=1.2;
V=@(t) 3*sqw(t,1,10);
F=@(t,VC) (V(t)-VC)/(R*C);
[T,VC]=meshgrid(linspace(xmin,xmax,10),linspace(ymin,ymax,10));
S=(3*sqw(T,1,10)-VC)/(R*C);
L=sqrt(1+S.^2);
aspect = 520.8 / 411.575;
x_span = (xmax - xmin) / aspect;
y_span = ymax - ymin;
% Compute the scale factor so that vectors are 10% of y-direction of plot window
d = 0.1;
X_world = 1./L;
Y_world = S./L;
s = d ./ sqrt((X_world / x_span).^2 + (Y_world / y_span).^2);
quiver(T,VC,s.*X_world,s.*Y_world,'r','ShowArrowhead','off','AutoScale','off')
axis([xmin,xmax,ymin,ymax])
% Make the figure have the desired position/size
set(gcf, 'Position', [666 223 672 505]);
function y=sqw(t,T,d)
r=mod(t,T);
y=(r<d*T/100);