Matlab: Feather plot on non-horizontal axis - matlab

Is it possible to draw a feather plot of inclined arrows, over a non-horizontal axis in Matlab? for instance, over a circle or other curve.
Thanks!

Sure. You want to use quiver and define the tails (x and y) and direction vectors (dx and dy)
t = linspace(0, 2*pi, 20);
x = cos(t);
y = sin(t);
dx = 0.25 * x;
dy = 0.25 * y;
q = quiver(x, y, dx, dy, 1);
You'll need to do a little math to come up with the exact positions and vectors based upon your problem but this should definitely be able to give you the desired result.

Related

Generate coordinate points with circle pattern points in Octave

I want to generate 300 samples of both types, red and blue, of coordinate points with these patterns.
Using rand() for x and then calculate y using Pythagorean theorem doesn't help because for the same x, we can have different y.
As suggested by Luis Mendo, you can use the typical rand function of matlab to generate random points in polar coordinates as follows:
figure
hold on
red = sampleCircle([1.4 1.6], 300);
plot(red(:, 1), red(:, 2), 'r*');
blue = sampleCircle([0 0.5], 300);
plot(blue(:, 1), blue(:, 2), 'b*');
function X = sampleCircle(rangeR, n)
r = rand(n, 1) * diff(rangeR) + rangeR(1);
theta = rand(n, 1) * 2*pi;
X = r .* [cos(theta) sin(theta)];
end

Graphing a Line given x,y, and z angle

I have this piece of MATLAB code that outputs x,y, and z angles and I would like draw a line using them. Can someone point me in the right direction on how to do this?
C = pi;
A = pi;
B = pi;
Z = [cos(C),-sin(C),0; sin(C),cos(C),0; 0,0,1];
X = [1,0,0;0,cos(A),-sin(A);0,sin(A),cos(A)];
Y = [cos(B),0,sin(B);0,1,0;-sin(B),0,cos(B)];
R =(X*Y)*Z;
yaw=atan2(R(2,1),R(1,1))
pitch=atan2(-R(3,1),sqrt(R(3,2)^2+R(3,3)^2))
roll=atan2(R(3,2),R(3,3))
X, Y, and Z are not angles, they are rotation matrices defined by the angles A, B, and C.
it's not clear what's the meaning of "draw a line using them", they are just used to rotate vectors in the 3D space.
here is an example of drawing a rotated vector with them:
% define rotation angles (around the axes)
C = pi/2;
A = pi/4;
B = pi/4;
% generate rotation matrices
Z = [cos(C),-sin(C),0; sin(C),cos(C),0; 0,0,1];
X = [1,0,0;0,cos(A),-sin(A);0,sin(A),cos(A)];
Y = [cos(B),0,sin(B);0,1,0;-sin(B),0,cos(B)];
R =(X*Y)*Z;
% generate a vector and rotate it
v = [1;1;1];
u = R*v;
% plot
quiver3(0,0,0,v(1),v(2),v(3));
hold on
quiver3(0,0,0,u(1),u(2),u(3));
xlim([-1 1]); ylim([-1 1]); zlim([-1 1])
axis square
legend('original','rotated')

MATLAB projectile motion with air resistance

I am trying to calculate maximum distance and maximum height of a projectile for an angle theta below.
I assume my way of plotting the graphs of distance against theta and height against theta (on the same graph) are wrong. Any pointers on that will be helpful.
e=100;
m = 1;
g = 9.8;
cd = 0.55;
r = 0.02;
p = 1.21;
a = pi*r^2;
v = sqrt((2*e)/m);
k = (1/2)*cd*a*p;
% For loop to calculate Distance and
for theta = (0:pi/4);
vx = v*cos(theta);
vy = v*sin(theta);
t = sqrt(m/(g*k))*atan(vy*sqrt(k/(m*g)));
x = (m/k)* log((1/vx)+(k/m)*t) - log(1/(vx));
h = (m/k)*(log(cos(atan(vy*sqrt(k/(m*g))-sqrt((g*k)/m)*t))-log(cos((atan(vy*sqrt(k/m*g)))))));
plot (x, theta);
plot (h, theta);
end
You don't need to loop through different values of theta. Try this instead:
theta = (0:0.01:pi/4); % theta = [0 0.01 0.02 0.03 ... pi/4]
vx = v*cos(theta);
vy = v*sin(theta);
t = sqrt(m/(g*k)) * atan(vy .* sqrt(k/(m*g))); % element wise matrix multiplication
x = (m/k)* log((1./vx)+(k/m)*t) - log(1./(vx));
h = (m/k)*(log(cos(atan(vy .* sqrt(k/(m*g))- sqrt((g*k)/m)*t))-log(cos((atan(vy .* sqrt(k/m*g)))))));
plot (x, theta);
plot (h, theta);
x vs theta:
Also try this:
MATLAB: Creating a Function to Plot Projectile with Drag
MATLAB: Numerical approximation of projectile motion with air resistance
Hope this helps!
The variable t is not defined. Also the loop variable should be integer, for example:
N = 10;
for i = 0:N-1
theta = pi/4*i/(N-1)
(...)
end

Plotting wind speed and wind direction over time

I'm trying to make a plot that can display both wind speed and wind direction over time. A colleague suggested adding a line pointing in the wind direction to each point on a time-series plot of wind speed.
I thought it would be fairly simple to calculate the line. I used trig formulas from here. However the plot is not displaying as I'd expect. All of the lines look as if they have zero slope rather than vary from -1 to 1.
Here is my code:
wdates = [ 7.357325746759259E5; 7.357325747916667E5; 7.357325749074074E5; 7.357325750231481E5; 7.357325751388889E5; 7.357325752546296E5; 7.357325753703704E5; 7.357325754861111E5; 7.357325756018518E5; 7.357325757175926E5; 7.357325758333333E5; 7.357325759490741E5; 7.357325760648148E5];
topspeed = rand(size(wdates)) * 2;
toprdir = [0 pi/6 pi/4 pi/3 pi/2 2*pi/3 3*pi/4 pi 5*pi/4 4*pi/3 3*pi/2 5*pi/3 7*pi/4];
toprdir = toprdir';
h = figure(1);
plot(wdates,topspeed,'s');
datetick('x')
hold all;
%find slope
topslopes = tan(toprdir);
for i=1:length(wdates)
%find start point.
clear x;
clear y;
x(1) = wdates(i);
y(1) = topspeed(i);
d = .0001;
%x(2) = d * cos(atan(topslopes(i))) + x(1); %did not work?
%y(2) = d * sin(atan(topslopes(i))) + y(1); %did not work?
x(2) = d * cos(toprdir(i)) + x(1);
y(2) = d * sin(toprdir(i)) + y(1);
plot(x,y);
end
And here is the result.
You are seeing that all the lines look like they have a slope of zero because your axes have very different ranges.
Instead, create a scaling factor based on your axes ranges. Note that, I just approximated values for dy, dx, but you should calculate what they should be based on your data and physical dimensions of each of your axis (e.g. make sure a 45 deg line looks like 45 degrees). You can use "axis square" to make dimensions the same.
dy = 1;
dx = 0.001;
x(2) = dx * cos(toprdir(i)) + x(1);
y(2) = dy * sin(toprdir(i)) + y(1);
With these lines modified, the resulting graph looks as follows:

draw ellipse and ellipsoid in MATLAB

How do I draw an ellipse and an ellipsoid using MATLAB?
(x^2/a^2)+(y^2/b^2)=1
n=40;
a=0; b=2*pi;
c=0; d=2*pi;
for i=1:n
u=a+(b-a)*(i-1)/(n-1);
for j=1:m
v=a+(d-c)*(j-1)/(m-1);
x(i,j)=sin(u)*cos(v);
y(i,j)=sin(u)*sin(v);
z(i,j)=cos(u);
end
end
mesh(x,y,z);
But I want the shape?
Ellipse article on Wikipedia had a simple JavaScript code to draw ellipses.
It uses the parametric form:
x(theta) = a0 + ax*sin(theta) + bx*cos(theta)
y(theta) = b0 + ay*sin(theta) + by*cos(theta)
where
(a0,b0) is the center of the ellipse
(ax,ay) vector representing the major axis
(bx,by) vector representing the minor axis
I translated the code into a MATLAB function:
calculateEllipse.m
function [X,Y] = calculateEllipse(x, y, a, b, angle, steps)
%# This functions returns points to draw an ellipse
%#
%# #param x X coordinate
%# #param y Y coordinate
%# #param a Semimajor axis
%# #param b Semiminor axis
%# #param angle Angle of the ellipse (in degrees)
%#
narginchk(5, 6);
if nargin<6, steps = 36; end
beta = -angle * (pi / 180);
sinbeta = sin(beta);
cosbeta = cos(beta);
alpha = linspace(0, 360, steps)' .* (pi / 180);
sinalpha = sin(alpha);
cosalpha = cos(alpha);
X = x + (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
Y = y + (a * cosalpha * sinbeta + b * sinalpha * cosbeta);
if nargout==1, X = [X Y]; end
end
and an example to test it:
%# ellipse centered at (0,0) with axes length
%# major=20, ,minor=10, rotated 50 degrees
%# (drawn using the default N=36 points)
p = calculateEllipse(0, 0, 20, 10, 50);
plot(p(:,1), p(:,2), '.-'), axis equal
The answers from Jacob and Amro are very good examples for computing and plotting points for an ellipse. I'll address some easy ways you can plot an ellipsoid...
First, MATLAB has a built-in function ELLIPSOID which generates a set of mesh points given the ellipsoid center and the semi-axis lengths. The following creates the matrices x, y, and z for an ellipsoid centered at the origin with semi-axis lengths of 4, 2, and 1 for the x, y, and z directions, respectively:
[x, y, z] = ellipsoid(0, 0, 0, 4, 2, 1);
You can then use the function MESH to plot it, returning a handle to the plotted surface object:
hMesh = mesh(x, y, z);
If you want to rotate the plotted ellipsoid, you can use the ROTATE function. The following applies a rotation of 45 degrees around the y-axis:
rotate(hMesh, [0 1 0], 45);
You can then adjust the plot appearance to get the following figure:
axis equal; %# Make tick mark increments on all axes equal
view([-36 18]); %# Change the camera viewpoint
xlabel('x');
ylabel('y');
zlabel('z');
Also, if you want to use the rotated plot points for further calculations, you can get them from the plotted surface object:
xNew = get(hMesh, 'XData'); %# Get the rotated x points
yNew = get(hMesh, 'YData'); %# Get the rotated y points
zNew = get(hMesh, 'ZData'); %# Get the rotated z points
I've adapted this excellent ellipse plotting script from MATLAB Central for your requirement of
function plotEllipse(a,b,C)
% range to plot over
%------------------------------------
N = 50;
theta = 0:1/N:2*pi+1/N;
% Parametric equation of the ellipse
%----------------------------------------
state(1,:) = a*cos(theta);
state(2,:) = b*sin(theta);
% Coordinate transform (since your ellipse is axis aligned)
%----------------------------------------
X = state;
X(1,:) = X(1,:) + C(1);
X(2,:) = X(2,:) + C(2);
% Plot
%----------------------------------------
plot(X(1,:),X(2,:));
hold on;
plot(C(1),C(2),'r*');
axis equal;
grid;
end
Note: change N to define the resolution of your ellipse
Here's an ellipse centered at (10,10) with a = 30 and b = 10
Ellipse article on Wikipedia and Rotation matrix.
Rewrite that functions:
rotate by rotAngle counter-clockwise around (0,0)
Coordinate transform to (cx, cy)
function [X,Y] = calculateEllipse(cx, cy, a, b, rotAngle)
%# This functions returns points to draw an ellipse
%#
%# #param x X coordinate
%# #param y Y coordinate
%# #param a Semimajor axis
%# #param b Semiminor axis
%# #param cx cetner x position
%# #param cy cetner y position
%# #param angle Angle of the ellipse (in degrees)
%#
steps = 30;
angle = linspace(0, 2*pi, steps);
% Parametric equation of the ellipse
X = a * cos(angle);
Y = b * sin(angle);
% rotate by rotAngle counter clockwise around (0,0)
xRot = X*cosd(rotAngle) - Y*sind(rotAngle);
yRot = X*sind(rotAngle) + Y*cosd(rotAngle);
X = xRot;
Y = yRot;
% Coordinate transform
X = X + cx;
Y = Y + cy;
end
and an example to test it:
[X,Y] = calculateEllipse(0, 0, 20, 10, 0);
plot(X, Y, 'b'); hold on; % blue
[X,Y] = calculateEllipse(0, 0, 20, 10, 45);
plot(X, Y, 'r'); hold on; % red
[X,Y] = calculateEllipse(30, 30, 20, 10, 135);
plot(X, Y, 'g'); % green
grid on;
Create two vectors, one of the x-coordinates of the points of the circumference of the ellipsoid, one of the y-coordinates. Make these vectors long enough to satisfy your accuracy requirements. Plot the two vectors as (x,y) pairs joined up. I'd drop the for loops from your code, much clearer if you use vector notation. Also I'd format your question using the SO markup for code to make it all clearer to your audience.
The simplest way might be to use the Matlab function
pdeellip(xc,yc,a,b,phi)
For example:
pdeellip(0,0,1,0.3,pi/4)
However, this is simple solution is good to have a quick glance how the ellipse looks like. If you want to have a nice plot, look at the other solutions.
I don't know in which version of Matlab this was added, but it's available at least from version R2012b on.