#include #include #include #include #include #include "local_proto.h" #define DOT "." /* for determining data type -tw */ #define INT "int" #define FLOAT "float" #define DOUBLE "double" #define TMPBUFSIZE 8192 static int error(char *); static int missing(int,char *); static int extract(int,char *,char *,void *,int,int (*)()); static int scan_int(char *,int *,int); const char gs_ascii_flag[5]={"DSAA"}; int getgrdhead ( FILE *fd, struct Cell_head *cellhd) { char grd_flag[6]; int nc,nr; float xmin,xmax,ymin,ymax,zmin,zmax; /* make sure the input file is positioned at the beginning */ rewind(fd); /* read and check the flag on the first line */ fgets(grd_flag,sizeof(grd_flag),fd); if(strncmp(gs_ascii_flag,grd_flag,strlen(gs_ascii_flag))) { G_warning(_("input file is not a Surfer ascii grid file")); return 0; } /* read the row and column dimensions */ if(fscanf(fd,"%d %d \n",&nc,&nr) != 2 ) { G_warning(_("error reading the column and row dimension from the Surfer grid file")); return 0; } /* read the range of x values */ if(fscanf(fd,"%f %f \n", &xmin, &xmax) != 2 ) { G_warning(_("error reading the X range from the Surfer grid file")); return 0; } /* read the range of y values */ if(fscanf(fd,"%f %f \n", &ymin, &ymax) != 2 ) { G_warning(_("error reading the Y range from the Surfer grid file")); return 0; } /* read the range of z values (not used) */ if(fscanf(fd,"%f %f \n", &zmin, &zmax) != 2 ) { G_warning(_("error reading the Z range from the Surfer grid file")); return 0; } /* initialize the cell header */ cellhd->zone = G_zone(); cellhd->proj = G_projection(); cellhd->rows=nr; cellhd->cols=nc; cellhd->ew_res=(double)(xmax-xmin)/(nc-1); cellhd->ns_res=(double)(ymax-ymin)/(nr-1); /* the Surfer grid specifies x,y locations of gridded points. The GRASS raster specifies an area covered by rectangular cells centerd at gridded points. That difference requires an adjustment */ cellhd->north = ymax+cellhd->ns_res/2.; cellhd->south = ymin-cellhd->ns_res/2.; cellhd->east = xmax+cellhd->ew_res/2.; cellhd->west = xmin-cellhd->ew_res/2.; return 1; } int gethead ( FILE *fd, struct Cell_head *cellhd, RASTER_MAP_TYPE *d_type, DCELL *mult, char **nval) { int n,s,e,w,r,c; char label[100], value[100]; char buf[1024]; char *err; int ret, len; /* rsb fix */ fpos_t p; n = s = e = w = r = c = 0; cellhd->zone = G_zone(); cellhd->proj = G_projection(); /* while (n == 0 || s== 0 || e == 0 || w == 0 || r == 0 || c == 0)*/ while(1) { /* rsb fix */ if (fgetpos(fd, &p) != 0) G_fatal_error(_("error getting file position")); if (!G_getl2(buf, sizeof(buf), fd)) break; len = strlen(buf); *label = *value = '\0'; if(NULL == G_strstr(buf, ":")) break; if(sscanf (buf, "%[^:]:%s", label, value)!=2) break; if (*label == '\0') continue; /* ignore blank lines */ if (strcmp (label, "north") == 0) { extract (n++, label, value, &cellhd->north, cellhd->proj, G_scan_northing); continue; } if (strcmp (label, "south") == 0) { extract (s++, label, value, &cellhd->south, cellhd->proj, G_scan_northing); continue; } if (strcmp (label, "east") == 0) { extract (e++, label, value, &cellhd->east, cellhd->proj, G_scan_easting); continue; } if (strcmp (label, "west") == 0) { extract (w++, label, value, &cellhd->west, cellhd->proj, G_scan_easting); continue; } if (strcmp (label, "rows") == 0) { extract (r++, label, value, &cellhd->rows, cellhd->proj, scan_int); continue; } if (strcmp (label, "cols") == 0) { extract (c++, label, value, &cellhd->cols, cellhd->proj, scan_int); continue; } /* try to read optional header fields */ if (strcmp (label, "type") == 0) /* if not exist then the file scan */ { if (*d_type < 0) { /* if data type not set on command line */ if (!strncmp(value, INT, strlen(INT))) *d_type = CELL_TYPE; else if (!strncmp(value, FLOAT, strlen(FLOAT))) *d_type = FCELL_TYPE; else if (!strncmp(value, DOUBLE, strlen(DOUBLE))) *d_type = DCELL_TYPE; else { G_warning(_("illegal type field: using type int")); *d_type= CELL_TYPE; } } else G_warning(_("ignoring type filed in header, type is set on command line")); continue; } if (strcmp (label, "multiplier") == 0) { if(G_is_d_null_value(mult)) /* if mult not set on commant line */ { if(sscanf(value, "%lf", mult) != 1) { G_warning(_("illegal multiplier field: using 1.0")); *mult = 1.0; } } else G_warning(_("ignoring multiplier filed in header, multiplier is set on command line")); continue; } if (strcmp (label, "null") == 0) { if(!(*nval)) /* if null val string not set on command line */ *nval = G_store(value); else G_warning(_("ignoring null filed in header, null string is set on command line")); continue; } } /* while */ /* the line read was not a header line, but actually the first data line, so put it back on the stack and break */ /* rsb fix */ fsetpos(fd, &p); missing(n,"north") ; missing(s,"south") ; missing(e,"east") ; missing(w,"west") ; missing(r,"rows") ; missing(c,"cols") ; if(!(*nval)) *nval = G_store("*"); if(G_is_d_null_value(mult)) *mult = 1.0; /* if data type is not set, then scan data to find out data type */ if(*d_type<0) { ret = file_scan(fd); if (!ret) *d_type = DCELL_TYPE; else if (ret == 1) *d_type = CELL_TYPE; else { error("ERROR: in ascii data format"); return 0; } } if ((err = G_adjust_Cell_head (cellhd, 1, 1))) { error (err); return 0; } return 1; } static int scan_int ( char *s, int *i,int proj) { char dummy[3]; *dummy = 0; if (sscanf (s, "%d%1s", i, dummy) != 1) return 0; if (*dummy) return 0; if (*i <= 0) return 0; return 1; } static int extract ( int count, char *label, char *value, void *data, int proj, int (*scanner)()) { char msg[1024]; if (count) { sprintf (msg, "duplicate \"%s\" field in header", label); error (msg); return 0; } if (scanner (value, data, proj)) return 1; sprintf (msg, "illegal \"%s\" value in header", label); error (msg); sprintf (msg, " %s: %s", label, value); error (msg); return 0; } static int missing (int count, char *label) { char msg[200]; if (count) return 0; sprintf (msg, "\"%s\" field missing from header", label); error(msg); return 1; } static int error( char *msg) { static int first = 1; if (first) { G_message(_("** errors detected in header section **\n")); first = 0; } fprintf (stderr, " %s\n", msg); return 0; } /* file_scan(): determine data type in ascii format */ int file_scan (FILE *fd) { long curpos; char tmpbuf[TMPBUFSIZE]; size_t size = TMPBUFSIZE; if ((curpos = ftell(fd)) == -1) return -1; while (!feof(fd)) { if (size != fread(tmpbuf, sizeof(char), size, fd)) { if (!feof(fd)) return -1; } if (strstr(tmpbuf, DOT) != NULL) { fseek(fd, curpos-1L, SEEK_SET); return 0; } } fseek(fd, curpos-1L, SEEK_SET); return 1; }