Search code examples
matlab3dmatlab-figureparticles

Create 3D streamtube (or streamline) from particle trajectory data


I have a set of particle trajectories in a 3D space and I want to represent them using 3D streamlines. I can easily get the trajectory using plot3, and I can represent the velocity vector using quiver3. As an example, one can consider the following sample script

zz = 0:pi/50:10*pi;
yy = zz.*sin(zz);
xx = zz.*cos(zz);
px=[0,diff(xx)];
py=[0,diff(yy)];
pz=[0,diff(zz)];

plot3(xx,yy,zz);
hold all;
quiver3(xx(1:5:end),yy(1:5:end),zz(1:5:end),px(1:5:end),py(1:5:end),pz(1:5:end),3);
hold off;

which produces the following plot

plot3+quiver3

I want to have the same plot, but with a 3D streamtube replacing the trajectory line. What is the most efficient way to deal with this situation?


Solution

  • Usually streamtube and streamline works on vector fields, in particular in MATLAB they works only for structured meshes (i.e. those generated by meshgrid).
    What you have is an unstructured vector field, but since you have a set of trajectories you actually have already the streamlines computed, indeed the trajectory are streamlines (you defined the vector field as the derivative of the trajectory).
    So basically you can plot the streamlines using `plot3'.
    If I understood your problem properly then a solution is the following:

    clear all
    close all
    
    x = [];
    y = [];
    z = [];
    Px = [];
    Py = [];
    Pz = [];
    
    figure(1)
    for i=1:10
        a= rand;
        b= rand; 
        zz{i} = 0:pi/50:10*pi;
        yy{i} = a*zz{i}.*sin(zz{i});
        xx{i} = b*zz{i}.*cos(zz{i});
        px{i}=[0,diff(xx{i})];
        py{i}=[0,diff(yy{i})];
        pz{i}=[0,diff(zz{i})];
    
    
        plot3(xx{i},yy{i},zz{i});
        hold all;
    
        XYZ{i} = [xx{i}',yy{i}',zz{i}'];
    
        x = [x, xx{i}];
        y = [y, yy{i}];
        z = [z, zz{i}];
        Px = [Px, px{i}];
        Py = [Py, py{i}];
        Pz = [Pz, pz{i}];
    end
    figure(2)
    streamtube(XYZ)
    
    [X,Y,Z] = meshgrid(linspace(min(x),max(x),10),linspace(min(y),max(y),10),linspace(min(z),max(z),10));
    PX = griddata(x,y,z,Px,X,Y,Z);
    PX(isnan(PX)) = 0;
    PY = griddata(x,y,z,Py,X,Y,Z);
    PY(isnan(PY)) = 0;
    PZ = griddata(x,y,z,Pz,X,Y,Z);
    PZ(isnan(PZ)) = 0;
    
    figure(3)
    streamtube(X,Y,Z,PX,PY,PZ,zeros(1,10),zeros(1,10),linspace(min(z),max(z),10))
    

    this scripts generates a set of ten trajectories and then plot the streamlines with plot3 but also with streamtube. However streamtube does exactly the same job replacing the line with a tube. If you wish you can also set the width of each tube.

    There is also the possibility to translate your unstructured vector field into a structured one, using the function griddata, however the result in this case will depend on how and how many the trajectory are. I would prefer the former two methods, the third could be used if you have an huge amount of trajectories and you wants to envelope all of them into a single tube.
    Please let me know if this answer your question.
    Alessandro