]> www.wagner.pp.ru Git - oss/fgis.git/blob - epu/eheader.c
First checked in version
[oss/fgis.git] / epu / eheader.c
1
2 /* This program edits header of EPP file */
3 #include <eppl.h>
4 /*#define LSB_FIRST 1*/
5 #ifdef LSB_FIRST
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
11 #else
12 # define COPY_DOUBLE(x) swapdouble(x)
13 # define COPY_LONG(x)  swaplong(x)
14 # define COPY_SHORT(x) swapshort(x)
15 #endif
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <math.h>
20
21 #define DO_XSHIFT 1
22 #define DO_YSHIFT 2
23 #define DO_SCALE 4
24 #define RESCALING 7
25 #define SET_X_LEFT 0x10
26 #define SET_X_RIGHT 0x20
27 #define SET_Y_BOTTOM 0x40
28 #define SET_Y_TOP 0x80
29 #define SET_PRJ 8
30 #define DGT_OPS 0xFF
31 #define EXPLICIT_COORDS 0xF0
32 #define SET_FR 0x100
33 #define SET_FC 0x200
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
42 #define MAX_UNIT 5
43
44 long operations=0;/* Bit mask of operations to apply */
45 void usage(int return_code)
46 { printf(
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\
70 \tft  - square feet\n\
71 \tm - square meters\n\
72 \tkm - square kilometers\n\
73 \tmile - square miles\n\
74 \tha - hectares\n\
75 \tacre - acres\n");
76    exit(return_code);
77 }
78
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)
84 { int i=1;
85   char *progname;
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];
92 else progname++;
93   if (!strcmp(progname,"maplist"))
94     operations|=VERBOSE_MODE;
95   else
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++;}
101   }
102  else
103      while (argv[i]&&(argv[i][0]=='-'))
104         { if (!option(&i,argv))
105                 { fprintf(stderr,"Unknown option :%s\n",argv[i]);
106                         exit(1);
107                 }
108         }
109         for(;i<argc;i++)
110         { process_file(argv[i]);
111         }
112 }
113 /* global variables - parameters of transformation */
114 char header[33];
115 double x_shift,y_shift,scale_fact,area_val,XLeft,XRight,YTop,YBottom;
116 long fr,fc,proj,unit,offsite;
117 struct ALIGN_VALUES
118    { double XLeft,YBottom,XRight,YTop;
119      int fr,fc,lr,lc;
120    } align_val;
121 double double_value(const char *s)
122
123 { char *errcheck=NULL;
124   double tmp;
125   tmp=strtod(s,&errcheck);
126   if (errcheck&& *errcheck )
127   { fprintf(stderr,"Invalid number : %s\n",s);
128     exit(1);
129   }
130   return tmp;
131 }
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);
135    exit(1);
136   }
137   operations|=this_key;
138 }
139 long int_value(const char *s)
140 { long tmp;
141   if (!sscanf(s,"%ld",&tmp))
142    { fprintf(stderr,"Invalid integer %s\n",s);
143       exit(1);
144     }
145  return tmp;
146 }
147 void read_align_values(const char *filename)
148 { FILE *f;EPPHEADER hdr;
149   f=fopen(filename,"rb");
150   if (NULL==f)
151   { fprintf(stderr,"Error open file %s\n",filename);
152     exit(1);
153   }
154  if (!get_epp_header(f,&hdr))
155  { fprintf(stderr,"%s is invalid EPP file\n",filename);
156    fclose(f);
157    exit(1);
158  }
159  fclose(f);
160  align_val.XLeft=hdr.fcx;
161  align_val.XRight=hdr.lcx;
162  align_val.YTop=hdr.fry;
163  align_val.YBottom=hdr.lry;
164  align_val.fc=hdr.fc;
165  align_val.fr=hdr.fr;
166  align_val.lc=hdr.lc;
167  align_val.lr=hdr.lr;
168 }
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)]);
174                       break;
175                     }
176          case 'y':  {
177                       check_key(argv[(*num)],DO_YSHIFT,EXPLICIT_COORDS);
178                       y_shift=double_value(argv[++(*num)]);
179                       break;
180                     }
181         case 'X': { switch ((argv[(*num)])[2])
182                     { case 'l':
183                       case 'L': { check_key(argv[(*num)],SET_X_LEFT,RESCALING);
184                                   XLeft=double_value(argv[++(*num)]);
185                                   break;
186                                 }
187                       case 'r':
188                       case 'R': { check_key(argv[(*num)],SET_X_RIGHT,RESCALING);
189                                   XRight=double_value(argv[++(*num)]);
190                                   break;
191                                 }
192                       default:
193                           { fprintf(stderr,"Invalid option %s\n",argv[(*num)]);
194                             exit(1);
195                           }
196                     }
197                     break;
198                   }
199         case 'Y': { switch ((argv[(*num)])[2])
200                     { case 'b':
201                       case 'B': { check_key(argv[(*num)],SET_Y_BOTTOM,RESCALING);
202                                   YBottom=double_value(argv[++(*num)]);
203                                   break;
204                                 }
205                       case 't':
206                       case 'T': { check_key(argv[(*num)],SET_Y_TOP,RESCALING);
207                                   YTop=double_value(argv[++(*num)]);
208                                   break;
209                                 }
210                       default:
211                           { return 0;
212                           }
213                     }
214                     break;
215                   }
216
217         case 'p': { check_key(argv[(*num)],SET_PRJ,0);
218                     (*num)++;
219                     if (!strcmp(argv[(*num)],"none"))
220                      { proj=0; }
221                     else
222                     if (!strcmp(argv[(*num)],"utm"))
223                      { proj=1; }
224                     else
225                     if (!strcmp(argv[(*num)],"UTM"))
226                      { proj=1; }
227                     else
228                     if (!strcmp(argv[(*num)],"stplane"))
229                      { proj=2; }
230                     else
231                     if (!strcmp(argv[(*num)],"ll"))
232                      { proj=3; }
233                     else
234                     { fprintf(stderr,"Invalid projection name %s\n",argv[(*num)]);
235                       exit(1);
236                     }
237                     break;
238                   }
239         case 'o': { check_key(argv[(*num)],SET_OFFSITE,0);
240                     offsite=int_value(argv[++(*num)]);
241                     if (offsite>32767) offsite=65536-offsite;
242                     if (offsite<-32768)
243                     { fprintf(stderr,"Invalid offsite value %s\n",argv[*num]);
244                       exit(1);
245                     }
246                     break;
247                   }
248   case 's' : { check_key(argv[(*num)],DO_SCALE,EXPLICIT_COORDS);
249                scale_fact=double_value(argv[++(*num)]);
250                break;
251              }
252   case 'f': {  switch((argv[(*num)])[2])
253                     { case 'r':{ check_key(argv[(*num)],SET_FR,DO_ALIGN);
254                                  fr=int_value(argv[++(*num)]);
255                                  break;
256                                }
257                       case 'c':{ check_key(argv[(*num)],SET_FC,DO_ALIGN);
258                                  fc=int_value(argv[++(*num)]);
259                                  break;
260                                }
261                       default: { fprintf(stderr,"Invalid option %s\n",argv[(*num)]);
262                             exit(1);
263                               }
264                      break;
265                   }
266                   break;
267                 }
268    case 'a':{ check_key(argv[(*num)],SET_AREA,RESCALING|EXPLICIT_COORDS);
269               area_val=double_value(argv[++(*num)]);
270               break;
271             }
272         case 'A':{ check_key(argv[(*num)],DO_ALIGN,EXPLICIT_ROW_COL);
273                                                  read_align_values(argv[++(*num)]);
274                                                  break;
275                   }
276         case 'c':{check_key(argv[(*num)],SET_COMMENT,0);
277                                                 strncpy(header,argv[++(*num)],32);
278                                                 break;
279                  }
280         case 'u':{check_key(argv[(*num)],SET_UNIT,0);
281                                                 (*num)++;
282                     if (!strcmp(argv[(*num)],"none"))
283                      { unit=0; }
284                     else
285                     if (!strcmp(argv[(*num)],"ft"))
286                      { unit=1; }
287                     else
288                     if (!strcmp(argv[(*num)],"m"))
289                      { unit=2; }
290                     else
291                     if (!strcmp(argv[(*num)],"km"))
292                      { unit=3; }
293                                 else
294                     if (!strcmp(argv[(*num)],"mile"))
295                      { unit=4; }
296                     else
297                     if (!strcmp(argv[(*num)],"ha"))
298                      { unit=5; }
299                     else
300                     if (!strcmp(argv[(*num)],"acre"))
301                      { unit=6; }
302                     else
303                     { fprintf(stderr,"Invalid area unit %s\n",argv[(*num)]);
304                       exit(1);
305                     }
306                                 break;
307         }
308 case 'v': { operations|=VERBOSE_MODE;
309             break;
310           }
311 default: { return 0;
312           }
313 }
314
315 (*num)++;
316 return 1;
317 }
318
319 int get_epp_header(FILE *f,EPPHEADER *hdr)
320 { EPPHEADER buf;
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);
344 return 1;
345 }
346 int put_epp_header(FILE *f,EPPHEADER *hdr)
347 { EPPHEADER buf;
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);
370 {int i;
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++]=' ');
374 }
375 return  fwrite(&buf,sizeof(buf),1,f);
376 }
377 int get_dgt_header(FILE *f,EPPHEADER *hdr,long *maxline,long *maxpt)
378 { DGTHEADER buf;
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);
388   return 1;
389 }
390 int put_dgt_header(FILE *f,EPPHEADER *hdr)
391 { DGTHEADER buf;
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);
401 }
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;
411         printf("File:%s\n\
412 Description:%s\n\
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\
418 Created: %s %s\n\
419 Data size = %d\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);
426 }
427 void print_dgt_header(const char*filename,EPPHEADER hdr,long maxline,long maxpt)
428 { printf("File: %s\n\
429 %s coordinates:\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,
434 maxline,maxpt);
435 }
436 void set_row( EPPHEADER *hdr,int row)
437 {
438   hdr->lr=hdr->lr-hdr->fr+row;
439   hdr->fr=row;
440 }
441 void set_column( EPPHEADER *hdr,int column)
442
443   hdr->lc=hdr->lc-hdr->fc+column;
444   hdr->fc=column;
445 }
446 int align(EPPHEADER *hdr,const char *name)
447 { double cw,sfx,sfy;
448   int new_row,new_col;
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",
455      name,sfx,sfy);
456      return 0;}
457
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);
466  return 1;
467 }
468 void process_file(const char *filename)
469 { FILE *f;
470   EPPHEADER hdr;
471   long maxline,maxpt;
472   int isdgt;
473   char ext[8];
474   int readonly=0;
475   strncpy(ext,filename+(strlen(filename)-3),4);
476   #ifdef __MSDOS__
477    strlwr(ext);/* dos filenames are not case-sensitive */
478   #endif
479   isdgt=0;
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);
483        return;
484       }
485      isdgt=1;
486    }
487   else
488    if (strcmp(ext,"epp")&&strcmp(ext,"EPP"))
489    { fprintf(stderr,"File %s has unknown extension\n",filename);
490      return;
491    }
492   f=fopen(filename,"r+b");
493   if (NULL==f) 
494   if (NULL==(f=fopen(filename,"rb")))
495   { 
496     fprintf(stderr,"Cannot open file %s\n",filename);
497     return;
498   } else readonly=1;
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);
501    return;
502  }
503  if (hdr.coord_sys>MAX_PROJECTION)
504    hdr.coord_sys=0;
505  if (!isdgt)
506  { if  (hdr.area_unit>MAX_UNIT)
507     hdr.area_unit=0;
508    if (hdr.kind==8)
509    { if (hdr.maxclass>255) hdr.maxclass=255;
510      if (hdr.minclass>hdr.maxclass) hdr.minclass=0;
511    }
512  }
513  /****************** Applying requested operations *****************/
514   if (operations & DO_XSHIFT)
515    { hdr.fcx+=x_shift;
516      hdr.lcx+=x_shift;
517    }
518   if (operations & DO_YSHIFT)
519   { hdr.fry+=y_shift;
520     hdr.lry+=y_shift;
521   }
522   if (operations & DO_SCALE)
523   { hdr.fcx*=scale_fact;
524     hdr.fry*=scale_fact;
525     hdr.lcx*=scale_fact;
526     hdr.lry*=scale_fact;
527    }
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))
538   { char *src=header;
539     char *dest=hdr.comment;
540     int count=0;
541     memset(&(hdr.comment),' ',32);
542     while (*src!='\0'&&count++<32) *(dest++)=*(src++);
543   }
544   if (!isdgt &&(operations & SET_UNIT )) hdr.area_unit=unit;
545   if (!isdgt &&(operations & SET_OFFSITE )) 
546    
547 if (hdr.kind==16||(offsite<=255&&offsite>=-1))hdr.offsite=offsite;
548  else
549   hdr.offsite=-1;
550  /******************** End of operations ***************************/
551  if (operations & VERBOSE_MODE )
552  { if (readonly) printf("Read-only ");
553    if (isdgt)
554     print_dgt_header(filename,hdr,maxline,maxpt);
555   else
556    print_epp_header(filename,hdr);
557  }
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);
561    clearerr(f);
562  }
563  fclose(f);
564 }