Plot vertical lines at a certain time - matlab

I want to plot a line at a certain "x" (being a scalar) value so every second, a vertical line with certain values will be drawn. I know that one way to plot a vertical line (without considering time) is to declare a vector like:
y=0:0.01:5;
or something like:
y=3:0.01:6;
and write plot(x,y);
Also, I've done "animated" plots using the "pause" parameter but I don't know how to do that in this case. Thanks for your help.

Another way I can suggest is to use plot in combination with hold on. With plot, you'd only specify two points where each point has the same x value, but the y value can change to whatever you want. When you draw points using plot, the default behaviour is that a line is drawn in between the points. If we specify two points having the same x coordinate, but different y coordinates, we would essentially draw a vertical line in between these points.
For example, given that you want to have every "second" have a vertical line, we can do something like this:
ystart = [-1 -2 -3 -1 -2 -3];
yend = [1 2 3 1 2 3];
figure; hold on;
for idx = 1 : numel(ystart)
plot([idx idx], [ystart(idx) yend(idx)]);
end
This is what we get:
We define two arrays of 6 elements where ystart denote the starting y point and yend denote the ending y point. We spawn a new figure, use hold on to plot multiple lines on the same graph, then use a for loop with plot so that we draw a line in between two points: (x,y) = (idx, ystart(idx)) and (x,y) = (idx, yend(idx)). idx goes from 1 to 6. Obviously, you can change the location of where the x values are being plotted by specifying another array... call it x:
x = 0:2:10; %// Time values
ystart = [-1 -2 -3 -1 -2 -3];
yend = [1 2 3 1 2 3];
figure; hold on;
for idx = 1 : numel(ystart)
plot([x(idx) x(idx)], [ystart(idx) yend(idx)]);
end
Here, we will draw vertical lines starting from x = 0 up to x = 10 in steps of 2. The result would basically be the same, but the x values would be different, as well as where the vertical lines are being drawn.

There are several ways to plot vertical lines in Matlab. The easiest recommendation is the line function:
line(X,Y) adds the line defined in vectors X and Y to the current
axes. If X and Y are matrices of the same size, line draws one line
per column.
Call this as many times as you want.
h=line(X,Y)
will give you properties of the line
Another way is to
X= X0*(Y./Y)
then
plot(X,Y)
will plot a vertical line at the point X0. Another thing you can do is draw a line using the above line function from the point (X0, min(Y)) to the point (X0, max(Y)) which is the most elegant solution. If you are trying to create a movie, you will need to access the properties of this line using h=line(X,Y). To move the line to a new position, you will have to set the properties of this line by calling set(h, Property, value). For example in your movie, you need to move it to a new position so you will set that property. This way, by minimum change of data, you can move a line or show its accelerating.

Related

Plotting circles with complex numbers in MATLAB

I want to make a figure in MATLAB as described in the following image
What I did is the following:
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure;
scatter(x,y,radius)
How do I add an angle theta to the plot to represent a complex number z = radius.*exp(1j*theta) at every spacial coordinates?
Technically speaking, those are only circles if x and y axes are scaled equally. That is because scatter always plots circles, independently of the scales (and they remain circles if you zoom in nonuniformly. + you have the problem with the line, which should indicate the angle...
You can solve both issues by drawing the circles:
function plotCirc(x,y,r,theta)
% calculate "points" where you want to draw approximate a circle
ang = 0:0.01:2*pi+.01;
xp = r*cos(ang);
yp = r*sin(ang);
% calculate start and end point to indicate the angle (starting at math=0, i.e. right, horizontal)
xt = x + [0 r*sin(theta)];
yt = y + [0 r*cos(theta)];
% plot with color: b-blue
plot(x+xp,y+yp,'b', xt,yt,'b');
end
having this little function, you can call it to draw as many circles as you want
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure
hold on
for i = 1:length(x)
plotCirc(x(i),y(i),radius(i),theta(i))
end
I went back over scatter again, and it looks like you can't get that directly from the function. Hopefully there's a clean built-in way to do this, and someone else will chime in with it, but as a backup plan, you can just add the lines yourself.
You'd want a number of lines that's the same as the length of your coordinate set, from the center point to the edge at the target angle, and fortunately 'line' does multiple lines if you feed it a matrix.
You could just tack this on to the end of your code to get the angled line:
x_lines = [x; x + radius.*cos(theta)];
y_lines = [y; y + radius.*sin(theta)];
line(x_lines, y_lines, 'Color', 'b')
I had to assign the color specifically, since otherwise 'line' makes each new line cycle through the default colors, but that also means you could easily change the line color to stand out more. There's also no center dot, but that'd just be a second scatter plot with tiny radius. Should plot most of what you're looking for, at least.
(My version of Matlab is old enough that scatter behaves differently, so I can only check the line part, but they have the right length and location.)
Edit: Other answer makes a good point on whether scatter is appropriate here. Probably better to draw the circle too.

Equally spaced x-value for values that are not equally spaced

I'm trying to display a discrete plot with values on the x-axis that are not equally space but I want them to appear equally spaced. I would like a stem plot with the first stick not on the y-axis, and I'd also like to have an horizontal dashed line at y=1.
So far here is what I tried.
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
xv = [1 2 3 4];
stem(xv,y);
set(gca,'XTickLabel',x);
Unfortunately, this is not what I expected. The value on the x-axis are not right and the sticks start on the y-axis and end on the figure edge.
How can I fix this?
EDIT: I initially forgot the horizontal dashed line. Added this.
You just need two tiny additions:
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
xv = [1 2 3 4];
stem(xv, y);
xlim([min(xv)-1 max(xv)+1]); % <--
set(gca, 'xtick', xv); % <--
set(gca, 'xticklabel', x);
You (also) need to explicitly set the xtick option, so that only these ticks are drawn, and no other.
With xlim, you can manipulate the x-axis limits. (Left and right limit might be modified to your needs.)
To add the horizontal dashed line, just add the following at the end:
hold on;
plot([min(xv)-1 max(xv)+1], [1 1], 'k--');
hold off;
(Start and end points of the line might be modified to your needs.)
From Matlab R2018b on, you could also use yline.
The output then looks like this:
When you have a sequence of values that you want to plot equally spaced without any special treatment to what each value actually is, you're essentially defining a set of categories.
MATLAB is good at handling these nicely without any extra trickery to lay them out uniformly on your axes if you declare the values explicitly as categorical.
All you need, therefore, is:
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
stem(categorical(x),y);
yline(1,'--');
ylim([0 1.5]) % Make some space on the y-axis so the horizontal line doesn't sit on the top edge

Extend a line through 3 points matlab

Im just trying to draw a line through the following points in matlab. Currently the line extends only to the points. I need to to extend and intercept the x axis. The code is below
A = [209.45 198.066 162.759];
B = [1.805 1.637 1.115];
plot(A,B,'*');
axis([0 210 0 2]);
hold on
line(A,B)
hold off
If you want to augment your points with a corresponding y==0 point, I suggest using interp1 to obtain the x-intercept:
A = [209.45 198.066 162.759];
B = [1.805 1.637 1.115];
x0 = interp1(B,A,0,'linear','extrap'); %extrapolate (y,x) at y==0 to get x0
[newA, inds] = sort([x0 A]); %insert x0 where it belongs
newB = [0 B];
newB = newB(inds); %keep the same order with B
plot(A,B,'b*',newA,newB,'b-');
This will use interp1 to perform a linear interpolant, with extrapolation switched on. By interpolating (B,A) pairs, we in effect invert your linear function.
Next we add the (x0,0) point to the data, but since matlab draws lines in the order of the points, we have to sort the vector according to x component. The sorting order is then used to keep the same order in the extended B vector.
Finally the line is plotted. I made use of plot with a linespec of '-' to draw the line in the same command as the points themselves. If it doesn't bother you that the (x0,0) point is also indicated, you can plot both markers and lines together using plot(newA,newB,'*-'); which ensures that the colors match up (in the above code I manually set the same blue colour on both plots).

Matlab extend plot over all axis range

I'm trying to use Matlab for some data plotting. In particular I need to plot a series of lines, some times given two points belonging to it, some times given the orthogonal vector.
I've used the following to obtain the plot of the line:
Line given two points A = [A(1), A(2)] B = [B(1), B(2)]:
plot([A(1),B(1)],[A(2),B(2)])
Line given the vector W = [W(1), W(2)]':
if( W(1) == 0 )
plot( [W(1), rand(1)] ,[W(2), W(2)])
else
plot([W(1), W(1) + (W(2)^2 / W(1))],[W(2),0])
end
where I'm calculating the intersection between the x-axis and the line using the second theorem of Euclid on the triangle rectangle formed by the vector W and the line.
My problem as you can see from the picture above is that the line will only be plotted between the two points and not on all the range of my axis.
I have 2 questions:
How can I have a line going across the whole axis range?
Is there a more easy and direct way (maybe a function?) to plot the line perpendicular to a vector? (An easier and more clean way to solve point 2 above.)
Thanks in advance.
Do you know the bounds of your axis for displaying the plot? If so, you can specify the range of the plot with the axis([xmin, xmax, ymin, ymax]) function.
So, from your question, if you know the slope m and intercept b, you can make sure your function plots the line across the whole window by specifying:
plot([xmin, xmax], [m*xmin + b, m*xmax + b]);
axis([xmin, xmax, min(m*xmin+b, m*xmax+b), max(m*xmin+b, m*xmax+b)]);
where xmin and xmax are values you specify as the range of your x-axis. This will make your line go from the corner of your plot to the other corner. If you want a buffer in the y-direction, then add one like so:
buffer = 5; % for example, you set this to something that looks good.
axis([xmin, xmax, min(m*xmin+b, m*xmax+b)-buffer, max(m*xmin+b, m*xmax+b)+buffer]);

Draw a line through two points

Using MatLab, I know how to create a line segment connecting two points using this code:
line([0 1],[0 1])
This draws a straight line segment from the point (0,0) to the point (1,1).
What I am trying to do is continue that line to the edge of the plot. Rather than just drawing a line between these two points I want to draw a line through those two points that spans the entire figure for any set of two points.
For this particular line and a x=-10:10, y=-10:10 plot I could write:
line([-10 10], [-10 10]);
But I would need to generalize this for any set of points.
Solve the line equation going through those two points:
y = a*x + b;
for a and b:
a = (yp(2)-yp(1)) / (xp(2)-xp(1));
b = yp(1)-a*xp(1);
Find the edges of the plotting window
xlims = xlim(gca);
ylims = ylim(gca);
or take a edges far away, so you can still zoomout, later reset the x/y limits.
or if there is no plot at the moment, define your desired edges:
xlims = [-10 10];
ylims = [-10 10];
Fill in those edges into the line equation and plot the corresponding points:
y = xlims*a+b;
line( xlims, y );
And reset the edges
xlim(xlims);
ylim(ylims);
There is one special case, the vertical line, which you'll have to take care of separately.
What about
function = long_line(X,Y,sym_len)
dir = (Y-X)/norm(Y-X);
Yp = X + dir*sym_len;
Xp = X - dir*sym_len;
line(Xp,Yp);
end
being sym_len one half of the expected length of the plotted line around X?