2 /* This program edits header of EPP file */
4 /*#define LSB_FIRST 1*/
6 /* portability issues when reading binary files */
7 /* define LSB_FIRST, when your processor uses Intel byte order */
8 # define COPY_DOUBLE(x) x
9 # define COPY_LONG(x) x
10 # define COPY_SHORT(x) x
12 # define COPY_DOUBLE(x) swapdouble(x)
13 # define COPY_LONG(x) swaplong(x)
14 # define COPY_SHORT(x) swapshort(x)
25 #define SET_X_LEFT 0x10
26 #define SET_X_RIGHT 0x20
27 #define SET_Y_BOTTOM 0x40
28 #define SET_Y_TOP 0x80
31 #define EXPLICIT_COORDS 0xF0
34 #define EXPLICIT_ROW_COL 0x300
35 #define DO_ALIGN 0x400
36 #define SET_AREA 0x800
37 #define SET_COMMENT 0x1000
38 #define SET_UNIT 0x2000
39 #define SET_OFFSITE 0x4000
40 #define VERBOSE_MODE 0x8000
41 #define MAX_PROJECTION 3
44 long operations=0;/* Bit mask of operations to apply */
45 void usage(int return_code)
47 "Usage eheader options files\n\
48 where options may be:\n\
49 These are applicable to both EPP and DGT files:\n\
50 -x n - shifts alternative x by n\n\
51 -y n - same with alternative y\n\
52 -s factor - multiplies all coordinates by factor\n\
53 -Xl n - sets alternative x of left border to specified value\n\
54 -Xr n - same with right border\n\
55 -Yb n, Yt - same with bottom and top y\n\
56 -p xxx - set projection type, where projection can be:\n\
57 \tnone - cause EPPL ver 3 to say \"No alternate coordinates\"\n\
58 \tutm - UTM projection\n\
59 \tstplate - state plane\n\
60 \tll - geographic coordinates\n\
61 Following is applicable to EPP files only:\n\
62 -o n - set offsite value\n\
63 -fr n - set first row to n\n\
64 -fc n - set first column to n\n\
65 -A filename - align to specified file\n\
66 -a n - set cell area\n\
67 -c \"string\" - set description\n\
68 -u xxx - set area unit type, where unit type may be:\n\
69 \tnone - cause EPPL ver 3 to say \"No alternate coordinates\"\n\
71 \tm - square meters\n\
72 \tkm - square kilometers\n\
73 \tmile - square miles\n\
79 int get_epp_header(FILE *f,EPPHEADER *hdr);
80 int put_epp_header(FILE *f,EPPHEADER *hdr);
81 int get_dgt_header(FILE *f,EPPHEADER *hdr,long *maxline,long *maxpt);
82 int put_dgt_header(FILE *f,EPPHEADER *hdr);
83 void main(int argc,char **argv)
86 int option(int *num,char **argv);
87 void process_file(const char *filename);
88 void read_align_values(const char *filename);
89 if (argc==1) usage(0);
90 progname=strrchr(argv[0],'/');
91 if (progname==NULL) progname=argv[0];
93 if (!strcmp(progname,"maplist"))
94 operations|=VERBOSE_MODE;
96 if (!strcmp(progname,"mapalign"))
97 { operations|=DO_ALIGN;
98 if (!strcmp(argv[1],"-v")) {operations|=VERBOSE_MODE;i++;}
99 read_align_values(argv[i++]);
100 if (!strcmp(argv[i],"-v")) {operations|=VERBOSE_MODE;i++;}
103 while (argv[i]&&(argv[i][0]=='-'))
104 { if (!option(&i,argv))
105 { fprintf(stderr,"Unknown option :%s\n",argv[i]);
110 { process_file(argv[i]);
113 /* global variables - parameters of transformation */
115 double x_shift,y_shift,scale_fact,area_val,XLeft,XRight,YTop,YBottom;
116 long fr,fc,proj,unit,offsite;
118 { double XLeft,YBottom,XRight,YTop;
121 double double_value(const char *s)
123 { char *errcheck=NULL;
125 tmp=strtod(s,&errcheck);
126 if (errcheck&& *errcheck )
127 { fprintf(stderr,"Invalid number : %s\n",s);
132 void check_key(char *keytext,int this_key,int incompatible_keys)
133 { if (operations & incompatible_keys)
134 { fprintf(stderr,"Option %s is incompatible with prevoius\n",keytext);
137 operations|=this_key;
139 long int_value(const char *s)
141 if (!sscanf(s,"%ld",&tmp))
142 { fprintf(stderr,"Invalid integer %s\n",s);
147 void read_align_values(const char *filename)
148 { FILE *f;EPPHEADER hdr;
149 f=fopen(filename,"rb");
151 { fprintf(stderr,"Error open file %s\n",filename);
154 if (!get_epp_header(f,&hdr))
155 { fprintf(stderr,"%s is invalid EPP file\n",filename);
160 align_val.XLeft=hdr.fcx;
161 align_val.XRight=hdr.lcx;
162 align_val.YTop=hdr.fry;
163 align_val.YBottom=hdr.lry;
169 int option(int *num,char **argv)
170 { if (argv[*num][0]!='-') return 0;
171 switch (argv[*num][1])
172 { case 'x': { check_key(argv[*num],DO_XSHIFT,EXPLICIT_COORDS);
173 x_shift=double_value(argv[++(*num)]);
177 check_key(argv[(*num)],DO_YSHIFT,EXPLICIT_COORDS);
178 y_shift=double_value(argv[++(*num)]);
181 case 'X': { switch ((argv[(*num)])[2])
183 case 'L': { check_key(argv[(*num)],SET_X_LEFT,RESCALING);
184 XLeft=double_value(argv[++(*num)]);
188 case 'R': { check_key(argv[(*num)],SET_X_RIGHT,RESCALING);
189 XRight=double_value(argv[++(*num)]);
193 { fprintf(stderr,"Invalid option %s\n",argv[(*num)]);
199 case 'Y': { switch ((argv[(*num)])[2])
201 case 'B': { check_key(argv[(*num)],SET_Y_BOTTOM,RESCALING);
202 YBottom=double_value(argv[++(*num)]);
206 case 'T': { check_key(argv[(*num)],SET_Y_TOP,RESCALING);
207 YTop=double_value(argv[++(*num)]);
217 case 'p': { check_key(argv[(*num)],SET_PRJ,0);
219 if (!strcmp(argv[(*num)],"none"))
222 if (!strcmp(argv[(*num)],"utm"))
225 if (!strcmp(argv[(*num)],"UTM"))
228 if (!strcmp(argv[(*num)],"stplane"))
231 if (!strcmp(argv[(*num)],"ll"))
234 { fprintf(stderr,"Invalid projection name %s\n",argv[(*num)]);
239 case 'o': { check_key(argv[(*num)],SET_OFFSITE,0);
240 offsite=int_value(argv[++(*num)]);
241 if (offsite>32767) offsite=65536-offsite;
243 { fprintf(stderr,"Invalid offsite value %s\n",argv[*num]);
248 case 's' : { check_key(argv[(*num)],DO_SCALE,EXPLICIT_COORDS);
249 scale_fact=double_value(argv[++(*num)]);
252 case 'f': { switch((argv[(*num)])[2])
253 { case 'r':{ check_key(argv[(*num)],SET_FR,DO_ALIGN);
254 fr=int_value(argv[++(*num)]);
257 case 'c':{ check_key(argv[(*num)],SET_FC,DO_ALIGN);
258 fc=int_value(argv[++(*num)]);
261 default: { fprintf(stderr,"Invalid option %s\n",argv[(*num)]);
268 case 'a':{ check_key(argv[(*num)],SET_AREA,RESCALING|EXPLICIT_COORDS);
269 area_val=double_value(argv[++(*num)]);
272 case 'A':{ check_key(argv[(*num)],DO_ALIGN,EXPLICIT_ROW_COL);
273 read_align_values(argv[++(*num)]);
276 case 'c':{check_key(argv[(*num)],SET_COMMENT,0);
277 strncpy(header,argv[++(*num)],32);
280 case 'u':{check_key(argv[(*num)],SET_UNIT,0);
282 if (!strcmp(argv[(*num)],"none"))
285 if (!strcmp(argv[(*num)],"ft"))
288 if (!strcmp(argv[(*num)],"m"))
291 if (!strcmp(argv[(*num)],"km"))
294 if (!strcmp(argv[(*num)],"mile"))
297 if (!strcmp(argv[(*num)],"ha"))
300 if (!strcmp(argv[(*num)],"acre"))
303 { fprintf(stderr,"Invalid area unit %s\n",argv[(*num)]);
308 case 'v': { operations|=VERBOSE_MODE;
319 int get_epp_header(FILE *f,EPPHEADER *hdr)
321 if (fseek(f,0,SEEK_SET)) return 0;
322 if (!fread(&buf,sizeof(buf),1,f)) return 0;
323 hdr->kind=COPY_SHORT(buf.kind);
324 if ((hdr->kind!=8)&&(hdr->kind!=16)) return 0;
325 hdr->fr = COPY_SHORT(buf.fr);
326 hdr->lr = COPY_SHORT(buf.lr);
327 hdr->fc = COPY_SHORT(buf.fc);
328 hdr->lc = COPY_SHORT(buf.lc);
329 hdr->fry = COPY_DOUBLE(buf.fry);
330 hdr->lry = COPY_DOUBLE(buf.lry);
331 hdr->fcx = COPY_DOUBLE(buf.fcx);
332 hdr->lcx = COPY_DOUBLE(buf.lcx);
333 hdr->kind = COPY_SHORT(buf.kind);
334 hdr->base = COPY_SHORT(buf.base);
335 hdr->scale = COPY_SHORT(buf.scale);
336 hdr->offsite = COPY_SHORT(buf.offsite);
337 hdr->sfact = COPY_DOUBLE(buf.sfact);
338 hdr->access_ptr = COPY_LONG(buf.access_ptr);
339 hdr->minclass = COPY_SHORT(buf.minclass);
340 hdr->maxclass = COPY_SHORT(buf.maxclass);
341 hdr->area_unit =(buf.area_unit);
342 hdr->coord_sys =(buf.coord_sys);
343 memcpy(&(hdr->date),&(buf.date),16+8+32);
346 int put_epp_header(FILE *f,EPPHEADER *hdr)
348 if (fseek(f,0,SEEK_SET)) return 0;
349 memset(&buf,0x20,128);
350 buf.kind=COPY_SHORT(hdr->kind);
351 buf.fr = COPY_SHORT(hdr->fr);
352 buf.lr = COPY_SHORT(hdr->lr);
353 buf.fc = COPY_SHORT(hdr->fc);
354 buf.lc = COPY_SHORT(hdr->lc);
355 buf.fry = COPY_DOUBLE(hdr->fry);
356 buf.lry = COPY_DOUBLE(hdr->lry);
357 buf.fcx = COPY_DOUBLE(hdr->fcx);
358 buf.lcx = COPY_DOUBLE(hdr->lcx);
359 buf.kind = COPY_SHORT(hdr->kind);
360 buf.base = COPY_SHORT(hdr->base);
361 buf.scale = COPY_SHORT(hdr->scale);
362 buf.offsite = COPY_SHORT(hdr->offsite);
363 buf.sfact = COPY_DOUBLE(hdr->sfact);
364 buf.access_ptr = COPY_LONG(hdr->access_ptr);
365 buf.minclass = COPY_SHORT(hdr->minclass);
366 buf.maxclass = COPY_SHORT(hdr->maxclass);
367 buf.area_unit =(hdr->area_unit);
368 buf.coord_sys =(hdr->coord_sys);
369 memcpy(&(buf.date),&(hdr->date),16+8+32);
371 for(i=strlen(buf.date);i<16;buf.date[i++]=' ');
372 for(i=strlen(buf.time);i<8;buf.time[i++]=' ');
373 for(i=strlen(buf.comment);i<32;buf.comment[i++]=' ');
375 return fwrite(&buf,sizeof(buf),1,f);
377 int get_dgt_header(FILE *f,EPPHEADER *hdr,long *maxline,long *maxpt)
379 if (fseek(f,0,SEEK_SET)) return 0;
380 if (!fread(&buf,sizeof(buf),1,f)) return 0;
381 hdr->fry = COPY_DOUBLE(buf.ytop);
382 hdr->lry = COPY_DOUBLE(buf.ybottom);
383 hdr->fcx = COPY_DOUBLE(buf.xleft);
384 hdr->lcx = COPY_DOUBLE(buf.xright);
385 hdr->coord_sys =(buf.coord_sys);
386 *maxline=COPY_LONG(buf.maxline);
387 *maxpt=COPY_LONG(buf.maxpt);
390 int put_dgt_header(FILE *f,EPPHEADER *hdr)
392 if (fseek(f,0,SEEK_SET)) return 0;
393 fread(&buf,sizeof(buf),1,f);
394 if (fseek(f,0,SEEK_SET)) return 0;
395 buf.ytop = COPY_DOUBLE(hdr->fry);
396 buf.ybottom = COPY_DOUBLE(hdr->lry);
397 buf.xleft = COPY_DOUBLE(hdr->fcx);
398 buf.xright = COPY_DOUBLE(hdr->lcx);
399 buf.coord_sys =(hdr->coord_sys);
400 return fwrite(&buf,sizeof(buf),1,f);
402 char *coord_name[]={"Alternative","UTM","State plane","Geographic"};
403 char *unit_name[]={"unknown units","sq.feet","sq.m","sq.km","sq.miles","ha","acres"};
404 void print_epp_header(const char *filename,EPPHEADER hdr)
405 { char commentstr[33],datestr[17],timestr[9];
406 commentstr[32]=datestr[16]=timestr[8]='\0';
407 strncpy(datestr,hdr.date,16);
408 strncpy(timestr,hdr.time,8);
409 if ((unsigned char)hdr.area_unit>6) hdr.area_unit=0;
410 if ((unsigned char)hdr.coord_sys>3) hdr.coord_sys=0;
413 First row = %6d Last row = %6d\n\
414 First column = %6d Last column = %6d\n\
415 %s coordinates:\nFirst row = %12g Last row = %12g\n\
416 First column = %12g Last column = %12g\n\
417 Cell area: %12g %s\n\
420 Minimum class = %d, Maximum class = %d, Offsite class = %d\n",
421 filename,strncpy(commentstr,hdr.comment,32),
422 hdr.fr,hdr.lr,hdr.fc,hdr.lc,coord_name[(int)hdr.coord_sys],
423 hdr.fry,hdr.lry,hdr.fcx,hdr.lcx,hdr.sfact,unit_name[(int)hdr.area_unit],
424 datestr,timestr,hdr.kind,
425 hdr.minclass,hdr.maxclass,hdr.offsite);
427 void print_dgt_header(const char*filename,EPPHEADER hdr,long maxline,long maxpt)
428 { printf("File: %s\n\
430 Xleft = %12g, XRight = %12g\n\
431 Ytop = %12g, YBottom = %12g\n\
432 Maximum point id = %ld, Maximum line id = %ld\n",
433 filename,coord_name[(int)hdr.coord_sys],hdr.fcx,hdr.lcx,hdr.fry,hdr.lry,
436 void set_row( EPPHEADER *hdr,int row)
438 hdr->lr=hdr->lr-hdr->fr+row;
441 void set_column( EPPHEADER *hdr,int column)
443 hdr->lc=hdr->lc-hdr->fc+column;
446 int align(EPPHEADER *hdr,const char *name)
449 cw=(align_val.XRight-align_val.XLeft)/(align_val.lc-align_val.fc+1);
450 sfx=cw/((hdr->lcx-hdr->fcx)/(hdr->lc-hdr->fc+1));
451 cw=(align_val.YBottom-align_val.YTop)/(align_val.lr-align_val.fr+1);
452 sfy=cw/((hdr->lry-hdr->fry)/(hdr->lr-hdr->fr+1));
453 if (fabs(sfx-1)>(1.0/(hdr->lc-hdr->fc+1))||fabs(sfy-1)>(1.0/(hdr->lr-hdr->fr+1)))
454 { fprintf(stderr,"Unable to align file %s.\nRescale it with X factor %7.4f and Y factor %7.4f\n",
458 new_col=(hdr->fcx-align_val.XLeft)/(align_val.XRight-align_val.XLeft)*
459 (align_val.lc-align_val.fc+1);
460 new_col+=align_val.fc;
461 new_row=(hdr->fry-align_val.YTop)/(align_val.YBottom-align_val.YTop)*
462 (align_val.lr-align_val.fr+1);
463 new_row+=align_val.fr;
464 set_row(hdr,new_row);
465 set_column(hdr,new_col);
468 void process_file(const char *filename)
475 strncpy(ext,filename+(strlen(filename)-3),4);
477 strlwr(ext);/* dos filenames are not case-sensitive */
480 if (!strcmp(ext,"dgt")||!strcmp(ext,"DGT"))
481 { if (!(operations&(DGT_OPS|VERBOSE_MODE)))
482 { fprintf(stderr,"No operations to apply to %s\n",filename);
488 if (strcmp(ext,"epp")&&strcmp(ext,"EPP"))
489 { fprintf(stderr,"File %s has unknown extension\n",filename);
492 f=fopen(filename,"r+b");
494 if (NULL==(f=fopen(filename,"rb")))
496 fprintf(stderr,"Cannot open file %s\n",filename);
499 if (!(isdgt?get_dgt_header(f,&hdr,&maxline,&maxpt):get_epp_header(f,&hdr)))
500 { fprintf(stderr,"invalid %s file %s\n",ext,filename);
503 if (hdr.coord_sys>MAX_PROJECTION)
506 { if (hdr.area_unit>MAX_UNIT)
509 { if (hdr.maxclass>255) hdr.maxclass=255;
510 if (hdr.minclass>hdr.maxclass) hdr.minclass=0;
513 /****************** Applying requested operations *****************/
514 if (operations & DO_XSHIFT)
518 if (operations & DO_YSHIFT)
522 if (operations & DO_SCALE)
523 { hdr.fcx*=scale_fact;
528 if (operations & SET_X_LEFT) hdr.fcx=XLeft;
529 if (operations & SET_X_RIGHT) hdr.lcx=XRight;
530 if (operations & SET_Y_BOTTOM) hdr.lry=YBottom;
531 if (operations & SET_Y_TOP) hdr.fry=YTop;
532 if (operations & SET_PRJ) hdr.coord_sys=proj;
533 if (!isdgt &&(operations & SET_FR)) set_row(&hdr,fr);
534 if (!isdgt &&(operations & SET_FC)) set_column(&hdr,fc);
535 if (!isdgt &&(operations & DO_ALIGN)) align(&hdr,filename);
536 if (!isdgt &&(operations & SET_AREA)) hdr.sfact=area_val;
537 if (!isdgt &&(operations & SET_COMMENT))
539 char *dest=hdr.comment;
541 memset(&(hdr.comment),' ',32);
542 while (*src!='\0'&&count++<32) *(dest++)=*(src++);
544 if (!isdgt &&(operations & SET_UNIT )) hdr.area_unit=unit;
545 if (!isdgt &&(operations & SET_OFFSITE ))
547 if (hdr.kind==16||(offsite<=255&&offsite>=-1))hdr.offsite=offsite;
550 /******************** End of operations ***************************/
551 if (operations & VERBOSE_MODE )
552 { if (readonly) printf("Read-only ");
554 print_dgt_header(filename,hdr,maxline,maxpt);
556 print_epp_header(filename,hdr);
558 if ((operations& ~VERBOSE_MODE)&& !readonly)
559 if (!(isdgt?put_dgt_header(f,&hdr):put_epp_header(f,&hdr)))
560 { fprintf(stderr,"Cannot modify file %s\n",filename);