Search code examples
c2dgnuplotsurfacepiping

Surface plot piping to gnuplot from C


I've made a function which successfully pipes data from my C program to gnuplot:

void gnuprintabs(FILE *gp,double **RE,double **IM, double x[], int N)
{     
    int i,j;

    fprintf(gp, "splot '-'\n");

    for (i=0; i<N; i++)
    {
        for(j=0; j<N; j++)
        {
            fprintf(gp, "%g %g %g\n", x[i],x[j],sqrt(RE[i][j]*RE[i][j]+IM[i][j]*IM[i][j]));
        }
    }
    fflush(gp);
    fprintf(gp, "e\n");    
}            

The function itself is in a loop whereby the 2D RE and IM arrays are continuously updated.

My question is how can I make this plot a solid surface rather than single points or lines?

If I tell gnuplot to set pm3d\n, it returns an error:

single isoline < scan > is not enough for pm3d plot

Is there a way round this?

Thanks


Solution

  • To get a surface plot you must separate two blocks with equal x-values, but changing y-value (or vice versa) by a blank line:

    x1 y1 z11
    x1 y2 z12
    ...
    x1 yN z1N
    
    x2 y1 z21
    x2 y2 z22
    ..
    x2 yN z2N
    
    x3 y1 z31
    ...
    

    i.e. print a newline after the inner for-loop

    void gnuprintabs(FILE *gp,double **RE,double **IM, double x[], int N)
    {     
        int i,j;
    
        fprintf(gp, "splot '-'\n");
    
        for (i=0; i<N; i++)
        {
            for(j=0; j<N; j++)
            {
                fprintf(gp, "%g %g %g\n", x[i],x[j],sqrt(RE[i][j]*RE[i][j]+IM[i][j]*IM[i][j]));
            }
            fprintf(gp, "\n");
        }
        fflush(gp);
        fprintf(gp, "e\n");    
    }
    

    If the throughput could be a problem, and your x- and y-steps are equidistant, you can also write your data as matrix format:

    void gnuprintabs(FILE *gp,double **RE,double **IM, double x[], int N)
    {     
        int i,j;
    
        fprintf(gp, "x0 = %e; dx = %e; y0 = %e; dy = %e;\n", x[0], x[1]-x[0], y[0], y[1]-y[0]);
    
        fprintf(gp, "splot '-' matrix using (x0+dx*$1):(y0+dy*$2):3\n");
    
        for (i=0; i<N; i++)
        {
            for(j=0; j<N; j++)
            {
                fprintf(gp, "%g ", sqrt(RE[i][j]*RE[i][j]+IM[i][j]*IM[i][j]));
            }
            fprintf(gp, "\n");
        }
        fflush(gp);
        fprintf(gp, "e\n");    
    }