Search code examples
matlaboctavegeometry-surface

Isosurface from X,Y,Z,V ordered data in Matlab/Octave


I have a set of 3d data points for each of which the value V of a certain quantity is associated. The data are organized in ordered columns X Y Z V, where the spatial coordinates are distributed on a grid. I have 21 points in every direction, so that the lengths of the several columns is 21x21x21=9261. How can I transform the data into a meshgrid that can be used by isosurface in Octave/Matlab? My code is the following

a=load("data.txt");
X=reshape(a(:,1), 21,21,21);
Y=reshape(a(:,2), 21,21,21);
Z=reshape(a(:,3), 21,21,21);
V=reshape(a(:,2), 21,21,21);
fv=isosurface (X,Y,Z,V,0.9);
patch(fv)

But the result is not meaningful (i get two flat surfaces located at x=0.9 and 1.). The data can be downloaded here.


Solution

  • Here's a way to create a proper meshgrid of your data:

    a = load('data.txt');
    [X, Y, Z] = meshgrid(unique(a(:, 1)), unique(a(:, 2)), unique(a(:, 3)));
    V = zeros(21, 21, 21);
    for i = 1:numel(V)
      idx = find(a(:, 1) == X(i) & a(:, 2) == Y(i) & a(:, 3) == Z(i));
      V(i) = a(idx, 4);
    end
    fv = isosurface (X,Y,Z,V,0.9);
    p = patch(fv);
    set(p,'FaceColor','red','EdgeColor','none');
    camlight;
    lighting gouraud;
    xlabel('x');
    ylabel('y');
    zlabel('z');
    

    enter image description here

    If you have much larger data and this is too slow, I can probably come up with a way of reshaping the original data to avoid the for-loop I've used above.