Matlab 3D data interpolation - matlab

I have a set of x,y and z data (each is a 3000 by 1 matrix) and I would like to interpolate this data to have a set of values for the z height at evenly spaced x and y values. I assume I need to mesh grid the x and y data sets, but I don't know how to interpolate for the z data. The data points are the unique vertices taken from an STL file, and so I'm looking to smooth out the resulting surface.
Any help much appreciated ,
Tom.

you have the matlab function interp2
then your code will be zi = interp2(x,y,z,xi,yi);
you can generate evenly spaced xi and yi using mesh grid
xi and yi will be the value of x and y at which you will make the interpolation, they are on a square form. E.g., if you want to interpolate at xi = 1 2 3 and yi = 4 5, then
xi will look like
[1 2 3;
1 2 3]
and yi,
[4 4 4;
5 5 5]
hope it helps!

Related

Count occurrences and stretch array in matlab

Let
input = [0 0 0 5 5 7 8 8];
I now want to transform this vector into the form
output = [3 3 3 3 5 5 6 8];
Which basically is a stairs plot.
Explanation
The input vector is used to plot data points along the x-axis. The y-axis is thereby provided by 1:length(input). So the resulting plot shows the cumulative number of datapoints along the y-axis and the time of occurrence along the x-axis.
I now want to fit a model against my dataset. Therefor I need a vector that provides the correct value for a certain time (x-value).
The desired output vector basically is the result of a stairs plot. I am looking for an efficient way to generate the desired vector in matlab. The result of
[x, y] = stairs(input, 1:length(input));
did not bring me any closer.
It can be done with bsfxun as follows:
x = [0 0 0 5 5 7 8 8];
y = sum(bsxfun(#le, x(:), min(x):max(x)), 1);
This counts, for each element in 1:numel(x), how many elements of x are less than or equal to that.

drawing 3d contour plot from 3d vector

I want to draw a contour plot for 3D data.
I have a force in x,y,z directions I want to plot the contour3 for that
the dimensions of the Fx = 21x21X21 same for Fy and Fz
I am finding force = f*vector(x,y,z)
Then
Fx(x,y,z) = force(1)
Fy(x,y,z) = force(2)
Fz(x,y,z) = force(3)
I did the following but it is not working with me ?? why and how can I plot that
FS = sqrt(Fx.^2 + Fy.^2 + Fz.^2);
x = -10:1:10;
[X,Y] = meshgrid(x);
for i=1:length(FS)
for j = 1:length(FS)
for k=1:length(FS)
contour3(X,Y,FS(i,j,k),10)
hold on
end
end
end
This is the error I am getting
Error using contour3 (line 129)
When Z is a vector, X and Y must also be vectors.
Your problem is that FS is not the same shape as X and Y.
Lets illustrate with a simple example:
X=[1 1 1
2 2 2
3 3 3];
Y=[1 2 3
1 2 3
1 2 3];
Z=[ 2 4 5 1 2 5 5 1 2];
Your data is probably something like this. How does Matlab knows which Z entry corresponds to which X,Y position? He doesnt, and thats why he tells you When Z is a vector, X and Y must also be vectors.
You could solve this by doing reshape(FS,size(X,1),size(X,2)) and will probably work in your case, but you need to be careful. In your example, X and Y don't seem programatically related to FS in any way. To have a meaningful contour plot, you need to make sure that FS(ii,jj,k)[ 1 ] corresponds to X(ii,jj), else your contour plot would not make sense.
Generally you'd want to plot the result of FS against the variables your are using to compute it, such as ii, jj or k, however, I dont know how these look like so I will stop my explanation here.
[ 1 ]: DO NOT CALL VARIABLES i and j IN MATLAB!
I'm not sure if this solution is what you want.
Your problem is that contour and contour3 are plots to represent scalar field in 2D objects. Note that ball is 2D object - every single point is defined by angles theta and phi - even it is an object in "space" not in "plane".
For representation of vector fields there is quiver, quiver3, streamslice and streamline functions.
If you want to use contour plot, you have to transform your data from vector field to scalar field. So your data in form F = f(x,y,z) must be transformed to form of H = f(x,y). In that case H is MxN matrix, x and y are Mx1 and Nx1 vectors, respectively. Then contour3(x,y,H) will work resulting in so-called 3D graph.
If you rely on vector field You have to specify 6 vectors/matrices of the same size of corresponding x, y, z coordinates and Fx, Fy, Fz vector values.
In that case quiver3(x,y,z,Fx,Fy,Fz) will work resulting in 6D graph. Use it wisely!
As I comment the Ander's answer, you can use colourspace to get more dimensions, so You can create 5D or, theoretically, 6D, because you have x, y, z coordinates for position and R, G, B coordinates for the values. I'd recommend using static (x,y,R,G,B) for 5D graph and animated (x,y,t,R,G,B) for 6D. Use it wisely!
In the example I show all approaches mentioned above. i chose gravity field and calculate the plane 0.25 units below the centre of gravity.
Assume a force field defined in polar coordinates as F=-r/r^3; F=1/r^2.
Here both x and yare in range of -1;1 and same size N.
F is the MxMx3 matrix where F(ii,jj) is force vector corresponding to x(ii) and y(jj).
Matrix H(ii,jj) is the norm of F(ii,jj) and X, Y and Z are matrices of coordinates.
Last command ensures that F values are in (-1;1) range. The F./2+0.5 moves values of F so they fit into RGB range. The colour meaning will be:
black for (-1,-1,-1),
red for (1,-1,-1),
grey for (0,0,0)
Un-comment the type of plot You want to see. For quiver use resolution of 0.1, for other cases use 0.01.
clear all,close all
% Definition of coordinates
resolution=0.1;
x=-1:resolution:1;
y=x;
z=-.25;
%definition of matrices
F=zeros([max(size(x))*[1 1],3]); % matrix of the force
X=zeros(max(size(x))*[1 1]); % X coordinates for quiver3
Y=X; % Y coordinates for quiver3
Z=X+z; % Z coordinates for quiver3
% Force F in polar coordinates
% F=-1/r^2
% spherical -> cartesian transformation
for ii=1:max(size(x))
for jj=1:max(size(y))
% temporary variables for transformations
xyz=sqrt(x(ii)^2+y(jj)^2+z^2);
xy= sqrt(x(ii)^2+y(jj)^2);
sinarc=sin(acos(z/xyz));
%filling the quiver3 matrices
X(ii,jj)=x(ii);
Y(ii,jj)=y(jj);
F(ii,jj,3)=-z/xyz^2;
if xy~=0 % 0/0 error for x=y=0
F(ii,jj,2)=-y(jj)/xyz/xy*sinarc;
F(ii,jj,1)=-x(ii)/xyz/xy*sinarc;
end
H(ii,jj)=sqrt(F(ii,jj,1)^2+F(ii,jj,2)^2+F(ii,jj,3)^2);
end
end
F=F./max(max(max(F)));
% quiver3(X,Y,Z,F(:,:,1),F(:,:,2),F(:,:,3));
% image(x,y,F./2+0.5),set(gca,'ydir','normal');
% surf(x,y,Z,F./2+.5,'linestyle','none')
% surf(x,y,H,'linestyle','none')
surfc(x,y,H,'linestyle','none')
% contour3(x,y,H,15)

How do I add up two scatter points with the same values of x but different values of y?

On a stem plot, how can I add points that have the same values of x but different values of y?
For example, given the following code:
x = [1 2 3 6 6 4 5];
y = [3 6 1 8 9 4 2];
stem(x,y);
If you plot x, and y, this will be the output:
I want to add up (6,8) and (6,9) so it becomes (6,17), just like what the image is showing.
How can I achieve this?
Use accumarray with x and y so you can bin or group like entries together that share the same x. Once these values are binned, you can sum all of the values that share the same bin together. As such, we see that for x = 6, we have y = 8 and y = 9. accumarray allows you to group multiple y values together that share the same x. Once these values are grouped, you then apply a function to all of the values in the same group to produce a final output for each group. In our case, we want to sum them, so we need to use the sum function:
x = [1 2 3 6 6 4 5];
y = [3 6 1 8 9 4 2];
Z = accumarray(x(:), y(:), [], #sum);
stem(unique(x), Z);
xlim([0 7]);
We use unique on X so that we have no repeats for X when plotting the stem plot. unique also has the behaviour of sorting your x values. Doing x(:) and y(:) is so that you can make your input data either as row or column vectors independently. accumarray accepts only column vectors (or matrices, but we won't go there) and so doing x(:) and y(:) ensures that both inputs are column vectors.
We get:
The above code assumes that x is integer and starting at 1. If it isn't, then use the third output of unique to assign each number a unique ID, then run this through accumarray. When you're done, use the output of accumarray like normal:
[xu,~,id] = unique(x);
Z = accumarray(id, y(:), [], #sum);
stem(xu, Z);

drow cumulative distribution function in matlab

I have two vectors of the same size. The first one can have any different numbers with any order, the second one is decreasing (but can have the same elements) and consists of only positive integers. For example:
a = [7 8 13 6];
b = [5 2 2 1];
I would like to plot them in the following way: on the x axis I have points from a vector and on the y axis I have the sum of elements from vector b before this points divided by the sum(b). Therefore I will have points:
(7; 0.5) - 0.5 = 5/(5+2+2+1)
(8; 0.7) - 0.7 = (5+2)/(5+2+2+1)
(13; 0.9) ...
(6; 1) ...
I assume that this explanation might not help, so I included the image
Because this looks to me as a cumulative distribution function, I tried to find luck with cdfplot but with no success.
I have another option is to draw the image by plotting each line segment separately, but I hope that there is a better way of doing this.
I find the values on the x axis a little confusing. Leaving that aside for the moment, I think this does what you want:
b = [5 2 2 1];
stairs(cumsum(b)/sum(b));
set(gca,'Ylim',[0 1])
And if you really need those values on the x axis, simply rename the ticks of that axis:
a = [7 8 13 6];
set(gca,'xtick',1:length(b),'xticklabel',a)
Also grid on will add grid to the plot

Generalize this matlab code for non-square matrices

I am working on some fourier transform code in matlab, and have come across the following:
xx = meshgrid(1:N);
% Center on DC
xx = xx - dcN;
% normalize dynamic range from -1 to 1
xx = xx./max(abs(xx(:)));
% form y coordinate from negative transpose of x coordinate (maintains symmetry about DC)
yy = -xx';
% compute the related radius of the x/y coordinates centered on DC
rr = sqrt(xx.^2 + yy.^2);
How can I generalize this for non-square matrices? This code is assuming my matrix is square, so dcN is the center of the square matrix (in other words, with 11x11, dcN = 6).
The math doesnt work out for that yy variable when the transpose is taken for a non-square matrix.
I have tried to figure out if I can make a meshgrid going from "top to bottom" instead of left to right - but I havent been able to figure taht out either.
Thanks
I have tried to figure out if I can
make a meshgrid going from "top to
bottom" instead of left to right - but
I havent been able to figure taht out
either.
>> N=5
N =
5
>> rot90(meshgrid(N:-1:1))
ans =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
From your question I guess that you want to find rr, i.e. the distance of any element in the matrix from the center.
If you want this for a M-by-N array, you'd do the following
%# note that using meshgrid instead of ndgrid will swap xx and yy
[xx,yy] = ndgrid(-(M-1)/2:(M-1)/2,-(N-1)/2:(N-1)/2);
%# normalize to the max of xx,yy
nrm = max((M-1)/2,(N-1)/2);
xx = xx./nrm;
yy = yy./nrm;
rr = sqrt(xx.^2+yy.^2)