/***************************************************************/ /* gsurf.c : generate surface grid from random point data */ /* after Smith and Wessel (1990) */ /*-------------------------------------------------------------*/ /* Smith, W.H.F. and P. Wessel (1990) Gridding with continuous */ /* curvature splines in tension. Geophysics, vol.55, 293-305. */ /***************************************************************/ /* Usage (FORTRAN calling sequence): */ /* call gsurf0(xorg, yorg, smx, smy, mx, my) */ /* xorg,yorg : float : coordinates of SW corner of grid */ /* smx, smy : float : mesh size in NS and EW */ /* mx, my : int : number of grid to N and to E */ /* Start and preset fundamental parameters */ /* call gsurf1(tens, eps, prelax, maxit) */ /* tens : float : tension parameter (default: 0.25) */ /* eps : float : convergence limit (default: 0.) */ /* prelax : float : over-relaxation parm (default: 1.4) */ /* maxit : int : max iteration (default: 250) */ /* Preset optional parameters, if necessary */ /* call gsurf2(n, xm, ym, zm) */ /* n : int : number of data in the arrays */ /* xm, ym : float array : random point coordinates */ /* zm : float array : random point data value */ /* Give random data (may be repeated) */ /* Calling with n=0 indicates end of random data. */ /* call gsurf3(radius, vnul) */ /* radius : float : search radius for trimming */ /* vnul : float : no data value for trimmed-off area */ /* Calculate grid value, and trim data */ /* If radius <= 0., no trim operation. */ /* call gsurf4(fname) */ /* fname : char string : filename of grid-data output */ /* Output grid data to the file (append) */ /* Format is fixed to '((f7.1,9(1x,f7.1)))' */ /* call gsurf4m(array, n, m) */ /* array : float array : area to store grid-data */ /* n, m : int : adjustable size of array */ /* Transfer generated grid data */ /* call gsurf5() */ /* Close process */ /***************************************************************/ #include #include #include #include static double xorg, yorg, smx, smy, xs, ys; static double ar, ar2, ar4, tens, tensb, eps, prelax; static int kseq=0, imx, jmx, imx4, maxit, ntgrd, *kc; static char *kv; static float *w, *u, *u2, *v, *c; static double ssr=0., vnul, cts0, cts1, cts2; int gsurf0(double axo, double ayo, double asmx, double asmy, int mx, int my) { int ngrd, n; if (kseq != 0) { fprintf(stderr, "gsurf0: illegal call sequence\n"); return(-1); } /* preset fundamental parameters, and prepare work area A (random data) */ if ((asmx==0.) || (asmy==0.)) { fprintf(stderr, "gsurf0: mesh size invalid\n"); return(-1); } if ((mx<1) || (my<1)) { fprintf(stderr, "gsurf0: array size rejected\n"); return(-1); } xorg = axo; yorg = ayo; imx = mx; jmx = my; imx4 = imx+4; smx = asmx; smy = asmy; xs = fabs(smx); ys = fabs(smy); ntgrd = imx4*(jmx+4); ngrd = imx*jmx; if (ngrd > 10006501) { fprintf(stderr, "gsurf0: too huge array\n"); return(-1); } if ((w=malloc(ngrd*4*sizeof(float))) == NULL) { fprintf(stderr, "gsurf0: memory (w) alloc fail\n"); return(-1); } for (n=0; n<(ngrd*4); n+=4) *(w+n) = 1.; ar = 1. / (xs/ys); ar2 = ar*ar; ar4 = ar2*ar2; tens = 0.25; tensb = tens; eps = 0.; prelax = 1.4; maxit = 250; fprintf(stderr, "gsurf0: process start\n"); kseq = 1; return(0); } int gsurf1(double atens, double aeps, double aprelx, int itmax) { if (kseq != 1) { fprintf(stderr, "gsurf1: illegal call sequence\n"); return(-1); } /* preset optional parameters */ if ((atens<0.) || (atens>1.)) { fprintf(stderr, "gsurf1: tension invalid\n"); return(-1); } if (aeps <= 0.) { fprintf(stderr, "gsurf1: converge limit invalid\n"); return(-1); } if ((aprelx<1.) || (aprelx>=2.)) { fprintf(stderr, "gsurf1: over-relax parm invalid\n"); return(-1); } if (itmax < 1) { fprintf(stderr, "gsurf1: max iteration invalid\n"); return(-1); } tens = atens; tensb = atens; eps = aeps; prelax = aprelx; maxit = itmax; fprintf(stderr, "gsurf1: option paremeters were set\n"); return(0); } int gsurf2(int np, float xp[], float yp[], float zp[]) { double sx, sy, sxx, sxy, syy, sz, szx, szy, det; double fx, fy, zv, dx, dy, rr, xy, xy1, b1, b2, b3, b4, b5; float *up, *cp; int i, ip, jp, kij, n, ma, mc, m, *kup, *kcp; int key; if (kseq == 1) kseq = 2; if (kseq != 2) { fprintf(stderr, "gsurf2: illegal call sequence\n"); return(-1); } /* read random data, store if usable. (to be repeated) */ if (np < 0) { fprintf(stderr, "gsurf2: data points n < 0\n"); return(-1); } if (np > 0) { for (i=0; i=imx) || (jp>=jmx)) continue; dx = fx - (double)ip; dy = fy - (double)jp; rr = dx*dx + dy*dy; kij = (jp*imx + ip) * 4; if (rr < *(w+kij)) { *(w+kij) = rr; *(w+kij+1) = dx; *(w+kij+2) = dy; *(w+kij+3) = zp[i]; } } return(0); } fprintf(stderr, "gsurf2: end of random data, now processing..."); fflush(stderr); /* calculate linear trend */ sx = sy = sxx = sxy = syy = sz = szx = szy = 0.; n = 0; for (kij=0,jp=0; jp 0) { key = 0; m = 0; for (m=0,jp=0; jp<(jmx+4); jp++) for (ip=0; ip= 0) { zv += *(v+m-imx4-1) / 2.; rr += 0.5; } if (jp != 0) if (*(kv+m-imx4) >= 0) { zv += *(v+m-imx4); rr += 1.; } if ((jp!=0) && (ip!=(imx+3))) if (*(kv+m-imx4+1) >= 0) { zv += *(v+m-imx4+1) / 2.; rr += 0.5; } if (ip != 0) if (*(kv+m-1) >= 0) { zv += *(v+m-1); rr += 1.; } if (ip != (imx+3)) if (*(kv+m+1) >= 0) { zv += *(v+m+1); rr += 1.; } if ((jp!=(jmx+3)) && (ip!=0)) if (*(kv+m+imx4-1) >= 0) { zv += *(v+m+imx4-1) / 2.; rr += 0.5; } if (jp != (jmx+3)) if (*(kv+m+imx4) >= 0) { zv += *(v+m+imx4); rr += 1.; } if ((jp!=(jmx+3)) && (ip!=(imx+3))) if (*(kv+m+imx4+1) >= 0) { zv += *(v+m+imx4+1) / 2.; rr += 0.5; } if (rr == 0.) key++; else { *(kv+m) = -2; *(v+m) = zv / rr; } } } for (m=0,jp=0; jp<(jmx+4); jp++) for (ip=0; ipeps) && (nit dmax) dmax = fabs(vst); } nit++; mit = nit*50 / maxit; while (lit < mit) { fputc('#', stderr); fflush(stderr); lit++; } } fprintf(stderr, " done\n"); kseq = 4; if (sr <= 0.) return(0); vnul = avnul; ssr = sr*sr; mj = (int)(sr/ys); fprintf(stderr, "gsurf3: trimming..."); fflush(stderr); for (k=mx2+2,j=0; j=jmx)) continue; t1 = js*ys; t2 = sqrt(ssr-t1*t1); mi = (int)(t2/xs); for (is=-1; is<=+mi; is++) { if (((i+is)<0) || ((i+is)>=imx)) continue; if (*(kv+k+ks+is) != 0) { n = 1; break; } } } for (ks=+mx1,js=+1; (n==1)&&(js>=-mj); js--,ks-=mx1) { if (((j+js)<0) || ((j+js)>=jmx)) continue; t1 = js*ys; t2 = sqrt(ssr-t1*t1); mi = (int)(t2/xs); for (is=-1; is<=+mi; is++) { if (((i+is)<0) || ((i+is)>=imx)) continue; if (*(kv+k+ks+is) != 0) { n = 2; break; } } } for (ks=+mx1,js=+1; (n==2)&&(js>=-mj); js--,ks-=mx1) { if (((j+js)<0) || ((j+js)>=jmx)) continue; t1 = js*ys; t2 = sqrt(ssr-t1*t1); mi = (int)(t2/xs); for (is=+1; is>=-mi; is--) { if (((i+is)<0) || ((i+is)>=imx)) continue; if (*(kv+k+ks+is) != 0) { n = 3; break; } } } for (ks=-mx1,js=-1; (n==3)&&(js<=+mj); js++,ks+=mx1) { if (((j+js)<0) || ((j+js)>=jmx)) continue; t1 = js*ys; t2 = sqrt(ssr-t1*t1); mi = (int)(t2/xs); for (is=+1; is>=-mi; is--) { if (((i+is)<0) || ((i+is)>=imx)) continue; if (*(kv+k+ks+is) != 0) { n = 4; break; } } } if (n != 4) *(v+k) = vnul; } fprintf(stderr, " done\n"); return(0); } int gsurf4(char *fnam) { int i, j, k, n; double t; FILE *fp; if ((kseq!=4) && (kseq!=5)) { fprintf(stderr, "gsurf4: illegal call sequence\n"); return(-1); } /* output generated grid data */ if (*fnam == '\0') fp = stdout; else if ((fp=fopen(fnam,"a")) == NULL) { fprintf(stderr, "gsurf4: unable to open file (%s)\n", fnam); return (-1); } k = imx4+imx4+2; n = 0; for (j=0; j0.) && (*(v+k)==vnul)) t = vnul; else t = *(v+k) + cts0 + cts1*(double)i + cts2*(double)j; if (n != 0) fputc(' ', fp); fprintf(fp, "%7.1lf", t); if (++n == 10) { fputc('\n',fp); n = 0; } } if (n > 0) { fputc('\n',fp); n = 0; } } if (fp != stdout) fclose(fp); fprintf(stderr, "gsurf4: grid data were output\n"); kseq = 5; return(0); } int gsurf4m(float *av, int ni, int nj) { int i, j, k; if ((kseq!=4) && (kseq!=5)) { fprintf(stderr, "gsurf4m: illegal call sequence\n"); return(-1); } /* transfer generated grid data */ k = imx4+imx4+2; for (j=0; j0.) && (*(v+k)==vnul)) *av = vnul; else *av = *(v+k) + cts0 + cts1*(double)i + cts2*(double)j; } while (i < ni) { av++; i++; } } fprintf(stderr, "gsurf4m: grid data were tranferred\n"); kseq = 5; return(0); } int gsurf5() { if (kseq != 5) { fprintf(stderr, "gsurf5: illegal call sequence\n"); fprintf(stderr, " forced to set initial state\n"); kseq = 0; return(1); } free(u2); free(v); free(kv); free(u); fprintf(stderr, "gsurf5: process end\n"); kseq = 0; return(0); } /*******************************************/ /* FORTRAN Language Interface Routines */ /*******************************************/ void gsurf0_(float *axo, float *ayo, float *asmx, float *asmy, int *mx, int *my) { if (gsurf0((double)*axo, (double)*ayo, (double)*asmx, (double)*asmy, *mx, *my) < 0) exit(1); } void gsurf1_(float *atens, float *aeps, float *aprelx, int *itmax) { if (gsurf1((double)*atens, (double)*aeps, (double)*aprelx, *itmax) < 0) exit(1); } void gsurf2_(int *n, float *xp, float *yp, float *zp) { if (gsurf2(*n, xp, yp, zp) < 0) exit(1); } void gsurf3_(float *sr, float *avnul) { if (gsurf3((double)*sr, (double)*avnul) < 0) exit(1); } void gsurf4_(char *name, size_t lf) { char fnam[256]; if (lf > 255) lf=255; while ((lf>0) && (*(name+lf-1)==' ')) lf--; fnam[0]='\0'; if (lf > 0) strncat(fnam,name,lf); if (gsurf4(fnam) < 0) exit(1); } void gsurf4m_(float *av, int *n, int *m) { if (gsurf4m(av, *n, *m) < 0) exit(1); } void gsurf5_() { gsurf5(); }