MATLAB: surf Plot after rotating my data - matlab

This question entails rotating an image given as a 3D matrix where the first dimension is width, 2nd dimension is height, and 3rd dimension contains x,y,z coordinates.
Currently I am plotting a surface using the following code
Fig.sub1im=surf(ToFparam.ROI.XYZ(:,:,1),ToFparam.ROI.XYZ(:,:,2),ToFparam.ROI.XYZ(:,:,3),zeros(ToFparam.ROI.height,ToFparam.ROI.width,3));
Now, I have a 3-D matrix where it's a 100x50x3. All x data is in the first...page or layer of the 3rd dimension, y is the second layer...z the third. Now I need to apply a 3x3 rotation matrix on the x y and z data. I know how to reshape a matrix to do this I think....just put it into a 3 row by...50000 column matrix then apply the matrix.
Next I need to update my plot in a loop. I was going to then do the following, where I have also included my new matrix calculation.
ToFparam.ROI.XYZ_Vector = ToFparam.ROI.XYZ;
ToFparam.ROI.XYZ_Vector = reshape(ToFparam.ROI.XYZ, [size(ToFparam.ROI.XYZ,1)*size(ToFparam.ROI.XYZ,2),3]);
ToFparam.ROI.XYZ_Vector = ToFparam.ROI.XYZ_Vector';
ToFparam.ROI.XYZ_DICOM = inv(DICOMparam.calib.navi2dicom(1:3,1:3))*inv(Naviparam.data.Endo_RefHomMat(1:3,1:3))*ToFparam.ROI.XYZ_Vector;
%refresh plot standard cuts
set(Fig.sub1im,'CData', Color);
set(Fig.sub1im, 'XData', ToFparam.ROI.XYZ_DICOM(1,:) + DICOMPos(1)/Fig.sub2samp);
set(Fig.sub1im, 'YData', ToFparam.ROI.XYZ_DICOM(2,:) + DICOMPos(2)/Fig.sub2samp);
set(Fig.sub1im, 'ZData', ToFparam.ROI.XYZ_DICOM(3,:) + DICOMPos(3)/Fig.sub2samp);
When I update my plot, I get no errors, but it doesn't look like it's plotting it correctly. It seems like it makes a huge offset on my data and positions it somewhere I don't want it to be positioned. I wouldn't expect that a rotation matrix effects the scaling, just the orientation. Let me know if there are any faster/better ways to accomplish this surf plot, thanks!

For anyone interested, I have found the solution.
If you ever want to rotate a 3-D matrix where the x,y,z data is located in the 3rd dimension, use the following for maximum speed and efficiency.
[m,n,z]=size(inMatrix);
outMatrix=reshape((A*(reshape(double(inMatrix),[m*n 3]))')',[m n 3]);
Where inMatrix is your initial 3d matrix, outMatrix is your output 3d matrix, and A is your rotation matrix. Can be extremely useful when wanting to code rotations in images, since images will have 2 dimensions along their width and height, and the 3rd dimension will be the x, y and z coordinates. This will allow you to easily plot an initial data set, rotate it, then replot it.

Related

Quiver plot in X-Z plane instead of X-Y plane

In MATLAB, quiver will plot a vector field on the x-y plane by default. Is there a way to rotate the image so that is lies on the x-z plane?
I have tried creating a 3D matrix and using commands like streamslice and quiver3. However I have a large number of data points that are irregularly spaced so this results in some inaccurate interpolation and matrices that are too big.
It seems the easiest option would be to use a command like rotate, but that doesn't seem to work with quiver.
You should just use quiver3 and add zero-valued (or whatever constant y you want) inputs in the dimensions that you don't care about
[x,y] = meshgrid(0:0.2:2,0:0.2:2);
u = cos(x).*y;
v = sin(x).*y;
Q = quiver3(x, zeros(size(x)), y, u, zeros(size(u)), v);
axis equal

MeshGrid for Triangle Elements

I want to build a contourf plot of a certain aspect in my Plate. The plate is divided in triangle elements, which I have the coordinates (x,y) of each knot of the triangle.
So, How can I make a meshgrid for my knots so I can make my contourf plot?? I have the coordinates of everything and have the value of my function Z in each knot. (I'm a beginner in Matlab, sorry for this "basic" question)
If your goal is just to visualise the triangles then there is another way that's probably simpler and more robust (see the end of this post).
If you definitely need to generate contours then you will need to interpolate your triangular mesh over a grid. You can use the scatteredInterpolant class for this (documentation here). It takes the X and Y arguments or your triangular vertices (knots), as well as the Z values for each one and creates a 'function' that you can use to evaluate other points. Then you create a grid, interpolate your triangular mesh over the grid and you can use the results for the countour plot.
The inputs to the scatteredInterpolanthave to be linear column vectors, so you will probably need to reshape them using the(:)`notation.
So let's assume you have triangular data like this
X = [1 4; 8 9];
Y = [2 3; 4 5];
Z = [0.3 42; 16 8];
you would work out the upper and lower limits of your range first
xlimits = minmax(X(:));
ylimits = minmax(Y(:));
where the (:) notation serves to line up all the elements of X in a single column.
Then you can create a meshgrid that spans that range. You need to decide how fine that grid should be.
spacing = 1;
xqlinear = xlimits(1):spacing:xlimits(2);
yqlinear = ylimits(1):spacing:ylimits(2);
where linspace makes a vector of values starting at the first one (xlimits(1)) and ending at the third one (xlimits(2)) and separated by spacing. Experiment with this and look at the results, you'll see how it works.
These two vectors specify the grid positions in each dimension. To make an actual meshgrid-style grid you then call meshgrid on them
[XQ, YQ] = meshgrid(xqlinear, yqlinear);
this will produce two matrices of points. XQ holds the x-coordinates of every points in the grid, arranged in the same grid. YQ holds the y-coordinates. The two need to go together. Again experiment with this and look at the results, you'll see how it works.
Then you can put them all together into the interpolation:
F = scatteredInterpolant(X(:), Y(:), Z(:));
ZQ = F(XQ, YQ);
to get the interpolated values ZQ at each of your grid points. You can then send those data to contourf
contourf(XQ, YQ, ZQ);
If the contour is too blocky you will probably need to make the spacing value smaller, which will create more points in your interpolant. If you have lots of data this might cause memory issues, so be aware of that.
If your goal is just to view the triangular mesh then you might find trimesh does what you want or, depending on how your data is already represented, scatter. These will both produce 3D plots with wireframes or point clouds though so if you need contours the interpolation is the way to go.

3D scatter plot with 4D data

I need to plot a 3D figure with each data point colored with the value of a 4th variable using a colormap. Lets say I have 4 variables X,Y,Z and W where W = f(X,Y,Z). I want a 3D plot with X, Y, and Z as the three axis. The statement scatter3(X,Y,Z,'filled','b') gives me a scatter plot in 3D but I want to incorporate the value of Z in the graph by representing the points as an extra parameter (either with different areas :bigger circles for data points with high value of Z and small circles for data points with low value of Z or by plotting the data points with different colors using a colormap). However, I am a novice in MATLAB and dont really know how to proceed. Any help will be highly appreciated.
Thanks in advance!
So just use z for the size vector (4th input) as well as the color vector (5th input):
z = 10*(1:pi/50:10*pi);
y = z.*sin(z/10);
x = z.*cos(z/10);
figure(1)
scatter3(x,y,z,z,z)
view(45,10)
colorbar
The size vector needs to be greater 0, so you may need to adjust your z accordingly.
You are already nearly there... simply use
scatter3(X,Y,Z,s,W);
where s is the point size (scalar, e.g. 3) and W is a vector with your W values.
You might also want to issue an
set(gcf, 'Renderer','OpenGL');
where gcf gets your current figure you are plotting in to significantly increase responsiveness when scattering a lot of data.

Matlab - plot image gradients using vector representation

I have computed the gradients from every pixel location of a grayscale image, both on X and Y axis and this can result in a vector representation for each pixel location. I want to obtain a plot figure similar to the one illustrated bellow:
My image has 1000 x 1002 dimensions and I have computed the gradients for each pixel on X and Y directions so I have 2 matrices, each one having 1000 x 1002 dimensions.
I am interested in obtaining a plot similar to the one illustrated in the image above, where I show basically the direction of each vector obtained from the computed gradients. I do not care about the magnitude of the vector, so basically each arrow can have the same length.
Do you know how can I obtain something similar to this?
It works in my case:
[DX,DY] = imgradient(imageIn);
%show gradient
figure;
[x,y]=meshgrid(1:1:500);
figure
quiver(x,y,DX,DY)
hold off

Matlab - Multiple 2D plots along a 3rd dimension

I'm trying to plot many 2D plots (x,y).
But...
each 2D plot is for a constant z.
So really my data is (x,y,z) but not z(x,y), which I believe are the requirements for using the "surf" command.
Could anyone help with this?
Example,
x = velocity
y = drag
I have multiple runs of y(x) for a constant temperature, z.
I just want to plot each (x,y) along a 3rd axis, temperature z.
Ideally I'd also want some sort of contour between the (x,y) plots so I can show the peaks/troughs etc.
Any help would be great.
If the runs are not independent (there is some trend over multiple runs) then it may make sense to use surf. You then need to construct your data such you have an X,Y, and Z - in this case I'd suggest you use the drag measurements as your Z (height).
Assuming that you have all the drag/velocity data in drag and velocity which are both of size [data points x number of runs]:
% construct matrix of run numbers
runs = repmat(1:numruns, [1, datapoints]);
runs = reshape(runs, datapoints, numruns);
% plot and label
surf(runs,velocity,drag);
xlabel('runs')
ylabel('velocity')
zlabel('drag')