Iam beginner to matlab. Still learning it.Recently i have been asked to compute curl of three velocity components and plot its contour w.r.t circumferential angle along x-axis and radius along y-axis. The data u,v and w is pre-calculated by me as follows
u = V * Cos(beta) * cos(alpha); % V is velocity in m/s and alpha,beta are angles in radians
similarly
v = V * cos(beta) * sin(alpha);
w = V * sin(alpha)
Someone recently commented out saying that to enable mat lab's curl functionality my u,v and w data should be in Cartesian coordinate. I relied saying that though my initial data is in spherical coordinates(V,alpha,beta) but iam using coordinate conversion on u,v and w and transforming my data to Cartesian coordinate.
He further replied saying that "not only u,v,w should be Cartesian but its relative data x,y,z should also need to be Cartesian coordinate"
I dint get it. Can anyone say what he was trying to say or if i can use the curl functionality in matlab
I shall be gretful for your help and answer
I have not tried the function, but as far as it concerns the coordinates u, v, w defines the force for each gridspace from x, y, z. However, the help on mathworks homepage says that x, y, z
must be monotonic, but do not need to be uniformly spaced.
This may be a trouble for spherical coordinates, when transformed to cartesians. I assume that weakly monotonic for any coordinate (but not all of them) would work, but spherical coordinates does not apply for that. What you could try is to transform the coordinates but make sure that the grid is monotonic. I mean, you make sure the grid in Cartesian coordinates is kept monotonic instead of the spherical.
So the answer is then more explicitly x, y, z, need to be non decreasing with at least 1 coordinate at the time which is increasing, but the force of each point can have the value of spherical coordinate transformed to its corresponding Cartesian value.
Except for this I would like to advise you to use the formal definition of spherical coordinates, which defines alpha as the angle from z to the xy-plane (alpha = 0 is the z-axis). I would also recommend you to use the more common coordinate names. r, phi and theta.
Related
I want to morph sphere, using the following equation:
R=1+k*(cos(4*elev)+sin(4*az)),
Spherical coordinates elev and az are transferred as gl_Vertex. The problem is to calculate normals for such morphing. I may calculate them, just shifting az and elev a bit, the obtain 2 more "virtual" vertices and use standard approach with cross-product, but it looks rather ugly and expensive approach.
Is their are any way to calculate normals also parametrically for such kind of morphing?
UPDATE:
Thanks to #meowgoesthedog, but I still have problems. My implementation of this formula (code below) did not work:
Am i correct and it should be:
cos(theta)*(k*(cos(4*theta)+sin(4*phi))+1) or cos(theta*(k*(cos(4*theta)+sin(4*phi))+1))?
Are normals calculated in cartesian coordinate system?
My code in Matlab:
close all
clear all
N=100;
phi_range=linspace(-pi,pi,N+2);
theta_range=linspace(-pi/2,pi/2,N);
phi_range([1,end])=[];
k=6;
% generate morphed sphere
PHI=repmat(phi_range,N,1);
THETA=repmat(theta_range',1,N);
R=1+k*cos(4*THETA)+k*sin(4*PHI);
% convert to cartesian coordinates
[X,Y,Z]=sph2cart(PHI,THETA,R);
%% meowgoesthedog formula
S=k.*(cos(4.*THETA)+sin(4.*PHI))+1;
V1_x = cos(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_y = sin(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_z = -sin(THETA).*S-4.*k.*sin(4.*THETA).*cos(THETA);
V2_x = sin(THETA).*(4.*k.*cos(PHI).*cos(4.*PHI)-sin(PHI).*S);
V2_y = sin(THETA).*(4.*k.*sin(PHI).*cos(4.*PHI)+cos(PHI).*S);
V2_z = 4.*k.*cos(THETA).*cos(4.*THETA);
V1=cat(3,V1_x,V1_y,V1_z);
V2=cat(3,V2_x,V2_y,V2_z);
Normals=cross(V1,V2);
% normalize
Normals=Normals./sqrt(sum(Normals.^2,3));
%% plot and compare results:
hold all
surfnorm(X,Y,Z,'EdgeAlpha',0.5)
quiver3(X,Y,Z,Normals(:,:,1),Normals(:,:,2),Normals(:,:,3),'m')
On figures below red - correct normals, magenta which I calculate.
We can compute an analytical expression for the normal using differential geometry. Let's first state the form of the Cartesian parametric coordinate:
Locally at any point on the surface, there is a 2D coordinate system spanned by the unit vectors in the directions of increasing θ and φ.
These vectors are given by:
The normal is simply given by the cross-product of these two vectors (un-normalized):
After some very tedious algebra we obtain:
(The formula becomes too long to legibly display past this point, and probably not as efficient to evaluate either.)
EDIT
It appears that I have used the conventional definition of θ (angle from the +Z axis) instead of Matlab's elev. Redefining the equations this would give:
Where ψ = ½π - θ is the elevation.
I have a set of points in 3D in cartesian coordinates X,Y,Z. To every such point I associate a value which is stored in a vector C. I want to be able to colour the surface given by X,Y,Z with colors given by C. Alternatively, if possible, I would like to associate to each point a color from a finite number of given colors. In Matlab this is possible with surf(X,Y,Z,C), but X,Y must be in grid form (generated by meshgrid), not in general form, like in my case.
I managed to do this in the case of the sphere, but the procedure is not pretty, and it uses heavily the parametrization of the sphere. Here's an example of what I want to do (in the case of the sphere).
Is there a way to do this type of surface coloring in Matlab? (if it helps, I can also provide a triangulation of the surfaces in addition to the points X,Y,Z)
Is there another piece of software which can do similar things and can interface in some way with Matlab?
I based this off of Matlab's Representing Data as a Surface. Does this work?
xlin = linspace(min(x),max(x),33);
ylin = linspace(min(y),max(y),33);
[X,Y] = meshgrid(xlin,ylin);
f = scatteredInterpolant(x,y,z);
Z = f(X,Y);
g = scatteredInterpolant(x,y,c);
C = g(X,Y);
surf(X, Y, Z, C)
Thanks Ander Biguri for suggesting patch. Here's what I've come up with, and it seems to work fine.
function patch_color_plot(struc)
% struc is a structure containing at least the following:
% points - the coordinate of the points in a 3xN matrix
% t - the triangulation matrix
% x_0s - the point values
fac = struc.t;
vert = struc.points;
fvc = struc.x_0s;
p = patch('Faces',fac,'Vertices',vert,'FaceVertexCData',...
fvc,'FaceColor','interp');
set(p,'EdgeColor','none')
axis equal
axis off`
Here's a sample result:
and another one with a torus:
here's another example:
I am using ray tracing and at the beginning I assumed a plane surface so I used the equation of the plane surface which is :
Ax + BY + CZ +d = 0
while A,B and C are the component of the normal vector of the Plane Normal = [A B C]
and using the Ray equation : Ray = Source + t*Direction
And then solve it for t and I can find the intersection points.
My question now that I have function in matlab to read the surface of the object but the object may not be plane surface and I am getting the data of the surface [X Y Z] of the surface but I don't know which equation should I use to find t and then the intersection point. And I even have a function to give me the normal vector at each point
If you can edit the tags the get the right ones please do it.
It might not be a plane, but you can always calculate a normal vector at each point. You'll just have to work harder to do it. Take two partial derivatives in planar coordinates, cross those vectors, and that's the normal at the point.
If your surface is defined as a height Z on a some X-Y grid, you can solve it easily using fzero. This would exclude some complex shapes, but might work for standard optics problems like a ray hitting a lens. Assume that X, Y and Z are 2-d matrices with the same shape. You can then do a 2d interpolation like
z_interp = interp2(X,Y,Z,x_interp,y_interp)
If this is not the case, you should try to define your own function that can calculate z based on x and y.
For the line, we have
x_ray = x_source + t * x_dir
y_ray = y_source + t * y_dir
z_ray = z_source + t * z_dir
So you can now define a function that calculates the height above the surface as a function of t as
height_above_plane = #(t) z_source + t * z_dir - interp2(X, Y, Z, ...
x_source + t*x_dir, y_source + t*y_dir)
Note that this might not be the shortest distance from the point to the plane, it is just the height measured along the z-direction. The time the ray hits the surface can now be found by searching for the t for which the height is zero. This can be done for arbitrary functions using fzero:
t_intercept = fzero(height_above_plane, 0);
This should work well for simple cases where the function defining the surface is relatively smooth and the ray crosses the surface only once. It might be possible to transform cases with more complex geometry into such a simple case.
If you can get the X Y Z of the surface and you said you can get the normal vector in each point so what is your problem now?
The X Y Z of the surface are the intersection points and if you have the normal vector in each point so you can calculate whatever you want ( the reflected or the refracted rays).
I think you have no troubles at all
I need to plot this function
theta = (-pi:0.01:pi);
f = 3*10^9;
c = 299792458;
da = 2;
Here's my code, but I'm not sure it's correct. I dont know where exactly dot mark should be. How to set X-Axis in degress?
beta = (2*pi*f)/c;
const= (da*beta)/2;
j= (cos(theta)+1).*(besselj(1,const*sin(theta))./(const*sin(theta)));
My another question is how to plot this function in polar coordinates.
I made something like this.
polar(theta,j);
Is it possible to rotate that function(by y-axis) to get 3D plot?
Things are quite right to me, although I wouldn't use the symbol j as a variable because (as i does) it is the symbol for the imaginary unit (sqrt(-1)). Doing so you are overriding it, thus things will work until you don't need complex numbers.
You should use element-wise operations such as (.*) when you aim at combining arrays entries element by element, as you correctly did to obtain F(\theta). In fact, cos(theta) is the array of the cosines of the angles contained in theta and so on.
Finally, you can rotate the plot using the command Rotate 3D in the plot window. Nonetheless, you have a 2D curve (F(\theta)) therefore, you will keep on rotating a 2D graph obtaining some kind of perspective view of it, nothing more. To obtain genuine information you need an additional dependent variable (Or I misunderstood your question?).
EDIT: Now I see your point, you want the Surface of revolution around some axis, which I suppose by virtue of the symmetry therein to be theta=0. Well, revolution surfaces can be obtained by a bit of analytic geometry and plotted e.g. by using mesh. Check this out:
% // 2D polar coordinate radius (your j)
Rad= (cos(theta)+1).*(besselj(1,const*sin(theta))./(const*sin(theta)));
Rad = abs(Rad); % // We need its absolute value for sake of clarity
xv = Rad .* cos(theta); % // 2D Cartesian coordinates
yv = Rad .* sin(theta); % // 2D Cartesian coordinates
phi = -pi:.01:pi; % // 3D revolution angle around theta = 0
% // 3D points of the surface
xf = repmat(xv',size(phi));
yf = yv' * cos(phi);
zf = yv' * sin(phi);
mesh(xf,yf,zf)
You can also add graphics effects
this is done via
mesh(xf,yf,zf,'FaceColor','interp','FaceLighting','phong')
camlight right
and a finer angular discretization (1e-3).
I've run simulations which have given me data points corresponding to X number of different radii, and Y number of angles each one was evaluated at. This means that I have X times Y data points which I need to plot.
I am currently plotting it in an non-ideal fashion: I am using the x and y axes as the r and theta axes. This means that my data appears as a sinusoidal trend which increases with radius on a Cartesian grid, not the circle which it physically represents. This is how I am currently plotting my data:
surf(r_val, th_val, v_val);
What I wish to do is plot my data on a cylindrical axis, such like that of the function polar(), but in R3 space. I would rather not download a toolbox, or modify the existing polar function; if there is no other solution then I will obviously end up doing this anyways.
Thanks for your help!
G.
Also, I am using Matlab 2012a
EDIT:
r_val = 1x8 vector containing unique radii
th_val = 1x16 vector containing unique angles
v_val = 8x16 matrix containing voltages corresponding to each position
NOTE: (after answered)
The truly ideal solution does not exist to this problem, as Matlab currently supports no true polar axes methods. Resource found here.
You should transform your coordinates to Cartesian coordinates before plotting them. MATLAB has builtin functions for perfroming coordiante transformations. See, for example pol2cart, which transforms polar or cylindrical coordinates to Cartesian coordinates. In your case you would simply use something like:
[x, y] = pol2cart(th_val, r_val);
surf(x, y, v_val);
Edit: Given that th_val and r_val are vectors of differing lengths it is necessary to first create a grid of points before calling pol2cart, along the lines of:
[R, T] = meshgrid(r_val, th_val);
[x, y] = pol2cart(T, R);
surf(x, y, v_val);