/* **************************************************************************** * * MODULE: s.vol.rst: program for 3D(volume) interpolation and geometry * analysis from scattered point data using regularized spline * with tension * * AUTHOR(S): Original program (1989) and various modifications: * Lubos Mitas * * GRASS 4.2, GRASS 5.0 version and modifications: * H. Mitasova, I. Kosinovsky, D. Gerdes, J. Hofierka * * PURPOSE: s.vol.rst interpolates the values to 3-dimensional grid from * point data (climatic stations, drill holes etc.) given in a * sites file named input. Output grid3 file is elev. * Regularized spline with tension is used for the * interpolation. * * COPYRIGHT: (C) 1989, 1993, 2000 L. Mitas, H. Mitasova, * I. Kosinovsky, D. Gerdes, J. Hofierka * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include #include #include #include "dataoct.h" #include "externs.h" #include "user.h" struct quadruple *point_new(double x, double y, double z, double w, double sm) { struct quadruple *point; if(!(point = (struct quadruple *)G_malloc (sizeof(struct quadruple)))) { return NULL; } point->x = x; point->y = y; point->z = z; point->w = w; point->sm = sm; return point; } struct octdata *data_new (double x_orig, double y_orig, double z_orig, int n_rows, int n_cols, int n_levs, int n_points) { struct octdata *data; int i; if (!(data = (struct octdata*)G_malloc (sizeof(struct octdata)))) { return NULL; } data->x_orig=x_orig; data->y_orig=y_orig; data->z_orig=z_orig; data->n_rows=n_rows; data->n_cols=n_cols; data->n_levs=n_levs; data->n_points=n_points; data->points = (struct quadruple *)G_malloc (sizeof(struct quadruple)*(KMAX+1)); for (i=0;i<=KMAX;i++) { data->points[i].x=0; data->points[i].y=0; data->points[i].z=0; data->points[i].w=0; data->points[i].sm=0; } return data; } int oct_compare(struct quadruple *point, struct octdata *data) /* returns the quadrant the point should be inserted in */ /* called by divide() */ {int cond1,cond2,cond3,cond4,cond5,cond6,rows,cols,levs; if (data==NULL) return -1; if(data->n_rows % 2==0) { rows=data->n_rows/2; } else { rows=(int)(data->n_rows/2)+1; } if(data->n_cols % 2==0) { cols=data->n_cols/2; } else { cols=(int)(data->n_cols/2)+1; } if(data->n_levs % 2==0) { levs=data->n_levs/2; } else { levs=(int)(data->n_levs/2)+1; } cond1=(point->x>=data->x_orig); cond2=(point->x>=data->x_orig+cols*ew_res); cond3=(point->y>=data->y_orig); cond4=(point->y>=data->y_orig+rows*ns_res); cond5=(point->z>=data->z_orig); cond6=(point->z>=data->z_orig+levs*tb_res); if(cond1&&cond3&&cond5) { if(cond6) { if(cond2&&cond4) return NET; if(cond2) return SET; if(cond4) return NWT; return SWT; } else { if(cond2&&cond4) return NEB; if(cond2) return SEB; if(cond4) return NWB; return SWB; } } else return 0; } int oct_add_data(struct quadruple *point, struct octdata *data) { int n,i,cond; double xx,yy,zz,r; cond=1; for(i=0;in_points;i++) { xx=data->points[i].x - point->x; yy=data->points[i].y - point->y; zz=data->points[i].z - point->z; r=xx*xx+yy*yy+zz*zz; if (r<=dmin) { cond=0; } } if (cond) { n=(data->n_points)++; data->points[n].x=point->x; data->points[n].y=point->y; data->points[n].z=point->z; data->points[n].w=point->w; data->points[n].sm=point->sm; } return cond; } int oct_division_check(struct octdata *data) { if (data->points == NULL) return -1; if (data->n_points < KMAX) return 0; else return 1; } struct octdata ** oct_divide_data(struct octdata *data) { struct octdata **datas; int cols1, cols2, rows1, rows2, levs1, levs2; int comp, i; double dx, dy, dz, x_or, y_or, z_or; if ((data->n_cols <= 1) || (data->n_rows <= 1)) { clean_fatal_error("Points are too concentrated -- please increase DMIN"); } if (data->n_cols % 2 == 0) { cols1 = data->n_cols / 2; cols2 = cols1; } else { cols2 = (int) (data->n_cols / 2); cols1 = cols2 + 1; } if (data->n_rows % 2 == 0) { rows1 = data->n_rows / 2; rows2 = rows1; } else { rows2 = (int) (data->n_rows / 2); rows1 = rows2 + 1; } if(data->n_levs % 2==0) { levs1=data->n_levs/2; levs2=levs1; } else { levs2=(int)(data->n_levs/2); levs1=levs2+1; } dx=cols1*ew_res; dy=rows1*ns_res; dz=levs1*tb_res; x_or=data->x_orig; y_or=data->y_orig; z_or=data->z_orig; if (!(datas=(struct octdata **) G_malloc (sizeof(struct octdata *) * 9))) { return NULL; } datas[SWB]=data_new(x_or,y_or,z_or,rows1,cols1,levs1,0); datas[SEB]=data_new(x_or+dx,y_or,z_or,rows1,cols2,levs1,0); datas[NWB]=data_new(x_or,y_or+dy,z_or,rows2,cols1,levs1,0); datas[NEB]=data_new(x_or+dx,y_or+dy,z_or,rows2,cols2,levs1,0); datas[SWT]=data_new(x_or,y_or,z_or+dz,rows1,cols1,levs2,0); datas[SET]=data_new(x_or+dx,y_or,z_or+dz,rows1,cols2,levs2,0); datas[NWT]=data_new(x_or,y_or+dy,z_or+dz,rows2,cols1,levs2,0); datas[NET]=data_new(x_or+dx,y_or+dy,z_or+dz,rows2,cols2,levs2,0); for (i=0;in_points;i++) { comp = oct_compare (data->points+i, data); if ((comp<1)||(comp>NUMLEAFS)) { clean_fatal_error("Point out of range"); } oct_add_data (data->points+i, datas[comp]); } data->n_points=0; data->points = NULL; return datas; } int oct_intersect(double xmin, double xmax, double ymin, double ymax, double zmin, double zmax, struct octdata *data) { int ix, ix0, iy, iy0, iz, iz0, izor, iyzoror; ix0 = ((data->x_orig>=xmin)&&(data->x_orig<=xmax)); iy0 = ((data->y_orig>=ymin)&&(data->y_orig<=ymax)); iz0 = ((data->z_orig>=zmin)&&(data->z_orig<=zmax)); iz = ((zmin>=data->z_orig)&&(zmin<=data->z_orig+data->n_levs*tb_res)); iy = ((ymin>=data->y_orig)&&(ymin<=data->y_orig+data->n_rows*ns_res)); ix = ((xmin>=data->x_orig)&&(xmin<=data->x_orig+data->n_cols*ew_res)); /*printf("\n%f %f %f",zmin,data->z_orig,data->z_orig+data->n_levs*tb_res);*/ izor = (iz || iz0); iyzoror = ((iy0 && izor) || (iy && izor)); if ( (ix0 && iyzoror) || (ix && iyzoror) ) { return 1; } else return 0; } int oct_get_points(struct quadruple *points, struct octdata *data, double xmin, double xmax, double ymin, double ymax, double zmin, double zmax, int MAX) { int i; int n=0; int l=0; struct quadruple *point; for(i=0;in_points;i++) { point=data->points+i; if(l>=MAX) return MAX+1; if ((point->x>=xmin)&&(point->x<=xmax) &&(point->y>=ymin)&&(point->y<=ymax) &&(point->z>=zmin)&&(point->z<=zmax)) { points[l].x = point->x; points[l].y = point->y; points[l].z = point->z; points[l].w = point->w; points[l].sm = point->sm; l++; } } n = l; return n; }