MATLAB: Plot 3D surface from irregular data points - matlab

Let's say I have a vector of x coordinates, a matrix of y coordinates and corresponding z values:
xcoordinates = [1 2 3 4 5];
ycoordinates = repmat(xcoordinates,5,1)+rand(5,5);
z = zeros(5,5);
for x=xcoordinates
for y=1:5
z(x,y) = sqrt(x^2+ycoordinates(x,y)^2);
end
end
How do I plot a surface determined by the z values at the points given by the corresponding x and y values? The first x value defines the x value for all y values in the first row of the matrix, the second x value to all values in the second row and so on.
(If the answer is griddata I would like some additional pointers. How can I get my data into the correct format?)

mesh(repmat(xcoordinates,5,1), ycoordinates, z)
By the way, you could easily vectorize this computation:
x = repmat(1:5, 5, 1);
y = x + rand(5,5);
z = sqrt(x.^2+y.^2);
mesh(x', y, z)

Related

How to make a 2D contour plot with given data point in Octave/MATLAB?

I have a matrix whose three columns correspond to x, y and f values. I want to make a contour plot of f(x,y) in the x,y plane from these data with Octave/MATLAB.
Let's say, the matrix M is
x1 y1 f1
x2 y2 f2
x3 y3 f3
. . .
. . .
I found the function contourf requires f to be a matrix (whereas I have a vector with corresponding points).
How to generate this plot?
The x, y, and z variables that you pass to contourf are all matrices of the same size. For every point you need an x, y, and z value. You can use meshgrid to make matrices that have all the combinations of x and y values.
This example is from the doc for contourf. I added some comments to explain what is happening
% Create a vector of x values
x = linspace(-2*pi,2*pi);
% Create a vector of y values
y = linspace(0,4*pi);
% Make matrices with all combinations of x and y values for plotting
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
contourf(X,Y,Z)
This is the result of the above code

discretise domain of x and y with 0.01 separation between points

I am looking to calculate an array from a formula using x and y variables, the domain of x is (0,50) and y is (0,30) . I am asked to discretise the domain of x and y with 0.01 separation between points, then compute L(x,y) (which I have a formula for)(This will be points of a graph, ultimately I'm looking for the min lengths between points)
I'm not sure what I need to define in my script because if I define x and y as arrays with 0.01 separation they end up being uneven and unable to calculate as the arrays are uneven
%change these values for A, B and C positions
Ax=10;
Ay=5;
Bx=15;
By=25;
Cx=40;
Cy=10;
x = 0:0.01:50; % Array of values for x from 0-50 spaced at 0.01
y = 0:0.01:30; % Array of values for y from 0-30 spaced at 0.01
%length of point P from A, B and C and display
Lpa=sqrt((Ax-x).^2+(Ay-y).^2);
Lpb=sqrt((Bx-x).^2+(By-y).^2);
Lpc=sqrt((Cx-x).^2+(Cy-y).^2);
L=Lpa+Lpb+Lpc
I am getting an error telling me the two matrix are not even which makes sense to not work but I'm not sure how to define a matrix that will result in the minimum x and y values I am after.
Any help would be greatly appreciated.
You want to calculate L for each possible pair of x and y. In other words, for the first value of x = 0, you will calculate L for all y values from 0 to 30, then for next value of x = 0.01, you will do the same and so on.
MATLAB has a really cool function called meshgrid to create a matrix for every pair of x and y. So after generating x and y, change your code to the following to get a 2D matrix for L -
[X, Y] = meshgrid(x, y)
%length of point P from A, B and C and display
Lpa = sqrt((Ax - X).^2 + (Ay - Y).^2);
Lpb = sqrt((Bx - X).^2 + (By - Y).^2);
Lpc = sqrt((Cx - X).^2 + (Cy - Y).^2);
L = Lpa + Lpb + Lpc

how to interpolate a fluctuated vector in matlab?

I have two arrays
x = [0 9.8312 77.1256 117.9810 99.9979];
y = [0 2.7545 4.0433 5.3763 5.0504];
figure; plot(x, y)
I want to make more samples of x and y then I interpolated both arrays. I tried this code
xi =min(x):.1:max(x);
yi = interp1(x,y,xi);
figure; plot(xi, yi)
but the trajectory is not same as previous plot. Its because the xi is not fluctuating same as x. How should I interpolate both arrays with same trajectory as original one?
This is an issue because when interpolating, MATLAB is going to ignore the order that you feed in the points and instead just sort them based upon their x location.
Rather than interpolating in x/y coordinates, you can instead use a parameter which represents the cumulative arc length of the line segments and use that to interpolate both the x and y coordinates. This will provide you with an interpolant that respects the order and guarantees monotonicity even for multiple values at the same x coordinate.
% Compute the distance between all points.
distances = sqrt(diff(x).^2 + diff(y).^2);
% Compute the cumulative arclength
t = cumsum([0 distances]);
% Determine the arclengths to interpolate at
tt = linspace(t(1), t(end), 1000);
% Now interpolate x and y at these locations
xi = interp1(t, x, tt);
yi = interp1(t, y, tt);

' vectors must be the same length' error

I've got a 250 x 250 image, I want to have a scatter plot of the intensity of every pixel and its nearest neighborhood. This is my code:
I = imread(image);
i = [1,249];
j = [1,250];
X = I(i,j);
Y = I(i+1,j);
scatter(X,Y);
why do I get the " X and Y vectors must be the same length" error? They are the same length !
Because scatter(X, Y) is only used for vectors, not matrix. In your example, both X and Y are 2x2 matrices, not vectors.
From its documentation:
scatter(X,Y) displays circles at the locations specified by the vectors X and Y. This type of graph is also known as a bubble plot.
Edit: if you want to plot matrix, use plotmatrix() instead:
plotmatrix(X,Y)
Scatter(X,Y) is used only for vectors as herohuyongtao correctly mentioned. You could try to do the following:
m = 250;
X = I(m+1:end);
Y = I(1:end-m);
scatter(X,Y);
You convert your image matrix I into a vector X while ignoring the first column and in a vector Y while ignoring the last column. X(n) is thus the neighbour of Y(n) on the right side.
I hope this helps!

Set surf minimum for matlab

I have a function which takes a voxel representation of a 3D landscape and can plot a X-Y section to show the middle of the landscape. The voxel representation is stored in a 3 dimensional matrix with a number that represents something important. Obviously the matrix is
1,1,1
2,2,2
in terms of accessing the elements but the actual 3D locations are found in the following method:
(index-1)*resolution+0.5*resolution+minPos;
where resolution is the grid size :
resolution
<-->
__ __ __
|__|__|__|
<- Min pos
and minPos is where the grid starts.
Now in terms of the actual question, i would like to extract a single X-Y section of this voxel representation and display it as a surf. This can be done by just doing this:
surf(voxel(:, :, section))
however then you get this:
The obvious problem is that the grid will start at 0 because that is how the matrix representation is. How can i set the minimum and cell size for surf, ie so that the grid will start at the minimum (shown above) and will have the grid spacing of resolution (shown above).
Read the documentation of surf, you can also provide x and y coordinates corresponding to your data points.
surf(X,Y,Z)
X and Y can be either vectors or matrices:
surf(X,Y,Z) uses Z for the color data and surface height. X and Y are vectors or matrices defining the x and y components of a surface. If X and Y are vectors, length(X) = n and length(Y) = m, where [m,n] = size(Z). In this case, the vertices of the surface faces are (X(j), Y(i), Z(i,j)) triples. To create X and Y matrices for arbitrary domains, use the meshgrid function
Example
Z=[ 0 1 2 3;
7 6 5 4;
8 9 10 11];
x=[-1 0 1 2];
y=[-2 0 2];
surf(x,y,Z);
Of course you have to match Z, x and y matrices/vectors as clearly described in the doc^^
Just remember that elements in columns of Z are surf'ed as values along the y-axis, elements in rows of Z are surf'ed as values along the x-axis. This is clearly to be seen in the example picture.
Solution
I think you switched the x and y-axis around, which you can fix by just transposing z:
s = size(voxel);
xi = (minPosX:resolution:(minPosX+resolution*s(1)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(2)-1));
z = (voxel(:,:,section));
surf(xi, yi, z');
or that you're picking the wrong numbers for constructing xi and yi and it should be this instead:
xi = (minPosX:resolution:(minPosX+resolution*s(2)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(1)-1));
z = (voxel(:,:,section));
surf(xi, yi, z);
So it was easy enough to do:
lets say we have a 3D matrix "voxel";
s = size(voxel);
xi = (minPosX:resolution:(minPosX+resolution*s(1)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(2)-1));
z = (voxel(:,:,section));
[x y] = meshgrid(xi, yi);
x = x';
y = y';
surf(x, y, z);
Provides the following plot:
This is rotated which is annoying, I cant seem to get it to rotate back (I could just visualise around the other way but that's ok)