Create 4D surface plot from x, y, z and c column vectors

I have 4 columns in a table named A. The 3 columns x,y,z are the initial conditions and c is the result of a specific function I use c = f(x,y,z). I want to show the result c[i] for every case x[i],y[i],z[i] as a surface where the colour will stand for how high/low the value of c is.
I use the code below:
xx = A.x
yy = A.y
zz = A.z
cc = A.c
but the following error appears:
Z must be a matrix, not a scalar or vector.
Any ideas?

 Accepted Answer

scatteredInterpolant or TriScatteredInterp. Then evaluate at a regular grid. Then you can isosurface() or slice()

13 Comments

I am not sure how you can use scatteredInterpolant or TriScatteredInterp on my cases. Can I have some more details on those?
F = scatteredInterpolant(xx, yy, zz, cc)
Now meshgrid or ndgrid up 3d arrays of query points. Call F passing in those arrays. The result will be a cuboid of projected c values. From there use isosurface or slice depending on how you want to display the results.
Thank you for your answer! I used some other functions, but your answer helped me find them. :)
This is what I used.
scatHand = scatter3(xx, yy, zz);
set(scatHand, 'CData', cc);
i do not understand the answer. Can you please send me your code or more details at least because i have exactly the same issue.
The original question had been about building a 4D surface plot; the technique for that is
xx = A.x;
yy = A.y;
zz = A.z;
cc = A.c;
F = scatteredInterpolant(xx, yy, zz, cc);
Nx = 10; Ny = 10; Nz = 10;
xv = linspace(min(xx),max(xx),Nx);
yv = linspace(min(yy),max(yy),Ny);
zv = linspace(min(zz),max(zz),Nz);
[xq, yq, zq] = ndgrid(xv, yv, zv);
cc_cuboid = F(xq, yq, zq);
Nprobe = 5;
probe_cc = linspace(min(cc), max(cc), Nprobe); %5 isosurfaces
for K = 1 : Nprobe
patch(isosurface(xq, yq, zq, cc_cuboid, probe_cc(K)));
end
legend( sprintf('cc = %g', probe_cc) );
I applied this code to my table variable with four collumns to build a 4d surface plot but the following picture shows the output. It gives me black polygons in xy plane which shows 3rd diemension value by placing the mouse on the points and does not show the 4th diemension at all. Could you please let me know if I am doing something wrong here?
Thank you.
You might need to
view(3)
to see the 3D surface.
The datatips will not reflect the additional coordinate -- not unless you customize the datatips. You could, for example,
for K = 1 : Nprobe
patch(isosurface(xq, yq, zq, cc_cuboid, probe_cc(K)), 'DisplayName', probe_cc(K), 'UserData', probe_cc(K));
end
legend
colorbar
which would create a legend relating color to value of the 4th coordinate. It would also set up UserData for each patch() object so that customized datatips could retrieve that value to display.
Thanks so much Walter for your feedback.
I updated code to customize the datatips but getting this error:
Error using patch
Value must be a character vector or a string scalar.
Attached you will find my table variable A.
Your input is very much appreciated.
for K = 1 : Nprobe
patch(isosurface(xq, yq, zq, cc_cuboid, probe_cc(K)), 'DisplayName', string(probe_cc(K)), 'UserData', probe_cc(K));
end
legend
colorbar
Thank you for your reply. Here is what I get:
Here is the code (table variable A is shared in my previous comments):
figure
xx = A.x;
yy = A.y;
zz = A.z;
cc = A.c;
F = scatteredInterpolant(xx, yy, zz, cc);
Nx = 11; Ny = 11; Nz = 11;
xv = linspace(min(xx),max(xx),Nx);
yv = linspace(min(yy),max(yy),Ny);
zv = linspace(min(zz),max(zz),Nz);
[xq, yq, zq] = ndgrid(xv, yv, zv);
cc_cuboid = F(xq, yq, zq);
Nprobe = 10;
probe_cc = linspace(min(cc), max(cc), Nprobe); %5 isosurfaces
for K = 1 : Nprobe
patch(isosurface(xq, yq, zq, cc_cuboid, probe_cc(K)), 'DisplayName', string(probe_cc(K)), 'UserData', probe_cc(K));
end
legend
colorbar
view(3)
Tested.
load A.mat
figure
xx = A.x;
yy = A.y;
zz = A.z;
cc = A.c;
F = scatteredInterpolant(xx, yy, zz, cc);
Nx = 11; Ny = 11; Nz = 11;
xv = linspace(min(xx),max(xx),Nx);
yv = linspace(min(yy),max(yy),Ny);
zv = linspace(min(zz),max(zz),Nz);
[xq, yq, zq] = ndgrid(xv, yv, zv);
cc_cuboid = F(xq, yq, zq);
Nprobe = 10;
mincc = min(cc_cuboid(:)); maxcc = max(cc_cuboid(:));
probe_cc = linspace(mincc, maxcc, Nprobe); %5 isosurfaces
cmap = colormap();
ncol = size(cmap,1);
cidx = floor(rescale(probe_cc, 1, ncol));
for K = 1 : Nprobe
patch(isosurface(xq, yq, zq, cc_cuboid, probe_cc(K)), 'FaceColor', cmap(cidx(K),:), 'FaceAlpha', .3, 'DisplayName', string(probe_cc(K)), 'UserData', probe_cc(K));
end
legend('Location', 'best')
colorbar
view(3)
Note that the UserData part is only there for potential future code extension with customizing datatips; if you are not planning to customize the datatips then you can leave out the 'UserData' part.
Also, the code to get a color from the color map to pass to FaceColor, uses interpolation of the current level compared to the potential range of the levels. If your levels are dense or if you choose the levels non-linearly, then you could end up with two surfaces the same color. The code does not use "next color" each time -- does not use the standard color order

Sign in to comment.

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!