3D Spline Interpolation Matlab - matlab

I have two 3D arrays:
A=[
12751 4616 15915
15864 4622 15667
12877 4683 21050
15816 4668 21253
11374 5006 18495
16995 5466 18493
11638 4880 20023
17078 4938 20006
11576 4886 17011
];
and
B=[
12402 2138 15743
10285 3175 15851
10237 3084 21052
12130 2129 21299
8074 3802 18505
14515 1623 18497
8415 3713 19856
14462 1120 20061
8340 3711 17145
14483 1157 16990];
and I want to do spline or 3D interpolation between them using Interp3 in Matlab.How should I define V in VI = interp3(X,Y,Z,V,XI,YI,ZI)?
Or Y in yy = spline(x,Y,xx).

I don't quite understand your data, is B a function of A (or visa versa)? Also, those arrays appear to be 1D, not 3D. Can you clarify this?
In your function call
yy = spline(x, Y, xx)
Y is the dependent variable which you are interpolating: Y is a function of x and the result of the above function call is to return the value of Y at xx. As an example in one dimension, try
x = linspace(0., 2.*pi, 100);
Y = sin(x);
% What is the value of Y (or sin(x)) at pi/2?
xx = pi/2.;
yy = spline(x, Y, xx); % This should result in yy = 1.000
Check out the spline documentation for more information and examples of using this function.
Now this function is only for 1D fitting, and is (I presume) equivalent to yy = interp1(x, Y, xx, 'spline'). If you want to do a three dimensional lookup, you'll have to use interp3, which generalises the above example to 3D. So rather than just one independent coordinate x, we have two more, y, and z and three coordinates for the point at which we want to perform the look up: xx, yy and zz. The function you are interpolating must be a 3D function of the coordinates (x, y, z). Try, as an example:
x = linspace(-1., 1., 100); y = x; z = x;
[X, Y, Z] = meshgrid(x, y, z);
s = exp(-sqrt(X.^2 + Y.^2 + Z.^2));
sinterp = interp3(x, y, z, s, 0., 0., 0.) % Should give sinterp = 0.9827

Related

Plotting four variables u = f(x, y, z) with ranges of x, y, z in Matlab

I'm trying to plot four variables (x, y, z, u) in a 3D space.
Below I defined u = f(x,y,z) = (x-y)/z and ranges for x, y and z.
Then I used the scatter3 function for plotting.
But the linspace command only returned
u1 = f(x1, y1, z1)
u2 = f(x2, y2, z2)
...
I wanted to plot my variables so that I would get values of u for all x, y and z, so as well as u_i = f(x_i, y_i, z_i), I want:
u112 = f(x1, y1, z2)
u121 = f(x1, y2, z1)
...
Which function do I need to use for this?
Full code:
z = linspace(1,2,50);
y = linspace(0,0.5,50);
x = linspace(-1,1,50);
f = (x-y)./z;
scatter3(x,y,z,5,f,'filled')
for i=1:50
if f(i)<0
scatter3(x,y,z,5,f,'r','filled');
else
scatter3(x,y,z,5,f,'b','filled');
end
end
You need to pass your x, y, and z vectors to meshgrid to have it generate points to fill the whole 3-D volume:
z = linspace(1, 2, 50);
y = linspace(0, 0.5, 50);
x = linspace(-1, 1, 50);
[X, Y, Z] = meshgrid(x, y, z);
f = (X-Y)./Z;
These will be 50-by-50-by-50 matrices. To plot them with scatter3 you will need to reshape them into column vectors using the colon operator:
scatter3(X(:), Y(:), Z(:), 5, f(:), 'filled');
If you'd like to plot negative values of f as red and positive values as blue, you can call scatter3 like so and add a jet colormap (no loops necessary):
scatter3(X(:), Y(:), Z(:), 5, (f(:) < 0), 'filled');
colormap(jet);

Error in mesh(X,Y,Z) in matlab

This is my code:
load mwe16_2.dat;
x = mwe16_2(:,1); % x contains the 1st column(500 values) of ‘mwe16_2’
y = mwe16_2(:,2); % y contains the 2nd column (500 values)of ‘mwe16_2’
z = mwe16_2(:,3); % z contains the 3rd column(500 values) of ‘mwe16_2’
[X, Y, Z] = meshgrid (x, y, z);
mesh (X, Y, Z)
While running the code it is showing the error:
*Error in plot3_d (line 13) mesh(X,Y,Z) in Matlab*
Can someone say the reason for the error and how to correct it?
[X,Y,Z] = meshgrid(x,y,z) produces three 3D arrays from x, y and z vectors. Now if you take a look at mesh you will see that you are not providing this function with proper input.
If you want to illustrate the set of points defined by three vectors of x, y and z, you can consider using scatter3:
figure; scatter3(x, y, z)

Fit polynomial to the maximums of a function

I want to fit a polynomial to noisy data so that the approximated polynomial is always >= the original data. For example:
x = linspace (-2, 6);
y = (x-2).^2 + 1 + 2 * randn (size (x));
function ret = delta (P, x, y)
yP = polyval (P, x);
d = yP - y;
d (d < 0) *= 1000;
ret = sumsq (d);
endfunction
P0 = polyfit (x, y, 2);
f = #(P) delta (P, x, y);
[P, FVAL] = sqp (P0, f)
xi = linspace (min(x), max(x), 100);
yi = polyval (P, xi);
plot(x, y, xi, yi);
grid on
Is there a better way/method which also works with higher order polynomials?
The easies way would be to just use polyfit and then calculate max(y-yi) and add this as offset but this wouldn't be optimal...
EDIT: I want to use GNU OCtave but added "matlab" as tag because the language and functions are similiar.
EDIT: based on tvo's answer and real data:
x = [10 20 30 40 50 60 80 100];
y = [0.2372, 0.1312, 0.0936, 0.0805, 0.0614, 0.0512, 0.0554, 0.1407];
function ret = delta (P, x, y)
ret = sumsq (polyval (P, x) - y);
endfunction
f = #(P) delta (P, x, y);
h = #(P) polyval(P, x) - y;
P0 = polyfit (x, y, 3);
[P] = sqp (P0, f, [], h)
xi = linspace (min(x), max(x));
yi = polyval (P0, xi);
yio = polyval (P, xi);
plot(x, y, xi, yi, ";initial guess;", xi, yio, ";optimized;");
grid on
but as you can see, the optimized and evaluated poly has points < the orginal point which isn't allowed.
your method seems fine, and I see no reason it can't be used for higher-order polynomials actually. Please explain why if you think it can't be used.
You are using Octave's 'sqp' solver. Documentation is here: http://www.gnu.org/software/octave/doc/v4.0.1/Nonlinear-Programming.html
You may want to avoid multiplying the error by an arbitrary number (1000 in your example) when it is negative. This may fail for different data sets, especially if they are larger, i.e. more data points.
You could try to use the non-linear inequality constraint options that Octave's 'sqp' offers, i.e. the h(x)>=0 (see doc).
As objective function phi you could use a square norm error, as in your example, and add constraints of the form h(x)>=0 for every data point. Note that 'x' would be the polynomial coefficients you want to fit and h(x) is the polynomial evaluated at a specific data point.
For example:
phi = #(P) delta_mod (P, x, y); % mod: Don't increase the importance of negative residuals!!
h = #(P) polyval(P, x1) - y1;
Psol = sqp(P0, phi, [], h);
Notice that the constraint function 'h' ensures that the polynomial will lie above (x1,y1), and the objective function 'phi' will try to keep it as close as possible. You can extend 'h' to contain one constraint for every data point in your set (see doc).

Plot 3D plane given equations in matlab

I want to plot 2 3D planes for the equations given below :
x + y + z = 1
2x - y = 0
For 1st equation, I plotted it using meshgrid as :
[x y] = meshgrid(-5:0.5:5);
z = 1 - x - y
mesh(x,y,z)
But for 2nd equation, z is not given i.e. z can be anything, then how do I plot plane for this ?
The comments are correct. It is more of a math problem. You draw a line 2x - y = 0 and translate it for any z value to create a plane.
[x, y] = meshgrid(-5:0.5:5);
Zv = #(x,y) 1 - x - y;
mesh(x,y,Zv(x,y));
hold on
[x, z] = meshgrid(-5:0.5:5);
Yv = #(x) 2*x;
mesh(x,Yv(x),z);
hold off

Matlab Plotting x=a?

How can I draw i.e. x = 5 line in plot at Matlab?
I plot like that:
x = (-10:.1:10);
f= 10;
plot(x, f, 'r');
of course it doesn't work. For every variable of x, y is equal to 0 except for x=10. When x = 10 y equals to everything. How to plot this?
In MATLAB, plot(X, Y) simply draws points on the graph (and connects them with lines). Note that in this form of syntax, X and Y must have the same dimensions. Therefore, to plot the line x = 5 create a vector of your desired y-coordinates, and then create matching x-coordinates, which are all equal to 5:
Y = -10:0.1:10;
X = 5 * ones(size(Y));
plot(X, Y);
A useful function from the FileExchange in hline and vline.
You could also achieve this by plotting only 2 points:
f = 5;
plot([-10 10] , [1 1]*f);
I think using line is more straightforward here than plot.
x = [-10, 10];
f = ones(size(x));
f = 5 .* f;
line(x, f);