]> www.wagner.pp.ru Git - oss/fgis.git/blob - epu/outtable.c
First checked in version
[oss/fgis.git] / epu / outtable.c
1 # include <stdio.h>
2 # define __USE_BSD
3 # include <string.h>
4 # include <stdlib.h>
5 # include <epp.h>
6 # include <eppl_ut.h>
7 # include <stdarg.h>
8 # include "outtable.h"
9 int
10       useOffsite=0,
11       areaInCells=0,  
12       verbose=0;
13       int fileCount=0,/* total number of files in record*/
14           funcCount=0,/* Number of functions to use */
15           openCount=0,/* Number of distinct open files */
16           baseFiles=-1;/* number of files which used to find combinations*/
17 double zUnit=1.0,
18        zOffset=0.0,
19        cellArea=0.0;
20 char *baseFile=NULL,
21      delimiter=',';
22 EPP* fileinfo[MAX_OUTTABLE_FILES];
23 EPP_LINK links[MAX_OUTTABLE_FILES];
24 unsigned short int *table;
25 typedef struct record *rec;
26 int tuple_size, limit, delta, count;
27 struct FuncItem funcList[MAX_OUTTABLE_FILES];
28 struct FileInfo openFiles[MAX_OUTTABLE_FILES];
29
30 void error(const char *format,...)
31 { va_list ap;
32   va_start(ap,format);
33   vfprintf(stderr,format,ap);
34   va_end(format);
35   exit(1);
36 }
37 void help(void)
38 { struct FuncInfo *f;
39   char sep=' '; 
40  printf("Usage: outtable [-%%][-u][-c][-d char][-b file][-z value][-Z value] files.."
41   "-function file(s)...\n");
42   printf("Where function are:\n");
43   for(f=funcTable;f->func;f++){
44    printf("%c-%s %s",sep,f->name,f->nargs==1?"file":"file file");
45    sep=',';
46   }
47   printf("\n");
48 }
49 void scanOpt(int *i,int argc, char **argv)
50
51   /* parsing options */
52   for (*i=1;*i<argc;(*i)++) {
53     if (argv[*i][0]=='-') {
54        if (strlen(argv[*i])==2) {
55            /* short options */ 
56            switch(argv[*i][1]) {
57               case 'u' : 
58                  useOffsite=0;
59                  break;
60               case 'c' :
61                   areaInCells=1;
62                   break;
63               case 'b' : 
64                   baseFile=argv[++*i];
65                   break;
66               case 'd':
67                   delimiter=argv[++*i][0];
68                   break;
69               case 'z': {char *errptr;
70                   zUnit=strtod(argv[++(*i)],&errptr);
71                   if (*errptr) 
72                      error("Invalid Z unit %s\n",argv[*i]);
73                }
74               case 'Z': { char *errptr;
75                           zOffset=strtod(argv[++(*i)],&errptr);
76                           if (*errptr)
77                             error("invalid Z offset %s\n",argv[*i]);
78               }
79               case '%':
80                   verbose=1;
81                   break;
82               default: help();
83                        exit (argv[*i][1]=='h');
84            }
85       } else if (strlen(argv[*i])==3&&argv[*i][1]=='d') {
86               delimiter=argv[*i][2];
87       } else if (argv[*i][1]=='-') {
88            /* long options */
89            if (!strcmp(argv[*i],"--help")) {
90               help(); exit(0);
91            } else if (!strcmp(argv[*i],"--version")) {
92               show_version("outtable","$Revision: 1.1 $");
93               
94            } else if (!strcmp(argv[*i],"--cells")) {
95               areaInCells=1;
96            } else if (!strcmp(argv[*i],"--union")) {
97               useOffsite=1;
98            } else if (!strcmp(argv[*i],"--base")) {
99               baseFile=argv[++*i];
100            } else if (!strcmp(argv[*i],"--delimiter")) {
101               delimiter=argv[++*i][0];
102            } else {
103               help();
104               exit(1);
105            }
106         } else {
107           /* Starts with - but not recognized as option - 
108            should be function */
109            return;
110         }
111      } else {
112         /* Doesn't start with - should be filename */ 
113         return;              
114      }
115    }
116 }
117
118
119
120 struct FuncInfo * findFunction(char *name)
121 {struct FuncInfo* f;
122  for(f=funcTable;strcmp(name,f->name)&&f->func;f++);
123  if (f->func) return f;
124     else return NULL;
125 }
126  
127 void openFile(char *name) {
128 int i;
129 struct FileInfo *f;
130 char Name[1024];
131 strcpy(Name,default_ext(name,".epp"));
132 for (i=0,f=openFiles;i<openCount&&strcmp(Name,f->name);i++,f++);
133   if (i<=openCount) {
134     fileinfo[fileCount++]=f->epp;
135   } else {
136
137     f->epp=open_epp(Name);
138     f->name=strdup(Name);
139     openCount++;
140     if (!f->epp) {
141        error("Couldn't open file %s\n",name);
142     }
143   }
144
145     
146
147 void parseArgs(int i, int argc, char **argv) {
148   struct FuncInfo *func;
149   int j;
150   while (i<argc) {
151      if (argv[i][0]=='-') {
152         if (!(func=findFunction(argv[i]+1))) {
153           error("Undefined function %s\n",argv[i]);
154         }
155         /* Make function list entry */
156         funcList[funcCount].func=func->func;
157         funcList[funcCount].index=fileCount;
158         funcList[funcCount].data=malloc(func->datasize);
159         /* Note, that definition of combinations finished */ 
160         if (baseFiles<0) baseFiles=fileCount;
161         for (j=0;j<func->nargs;j++) {
162           if (i==argc) error("Not enough args for function -%s\n",func->name); 
163           openFile(argv[i++]);
164         }
165      } else {
166        if (baseFiles>=0) 
167           error("Files to define combinations should precede functions\n");
168        openFile(argv[i++]);
169      }
170    }
171 }   
172
173 int compare(struct record *r1, struct record *r2)
174 {int i; 
175  for (i=0;i<fileCount;i++)
176  { if (r1->classes[i]>r2->classes[i]) return 1;
177    else
178    if (r1->classes[i]<r2->classes[i]) return -1;
179  }
180  return 0;
181
182 }
183 /* Searches table for record which contains classes, specified
184    in record key. if found, returns non-zero and places index of it
185    into index. If not, returns zero and places index, where to insert
186    record into index */ 
187 int search(struct record *key,int *index)
188 {int l=0,h=count-1,i,c;
189  while(l<=h)
190  { i=(l+h)>>1;
191    c=compare((struct record *)(table+(tuple_size)*i),key);
192    if (c<0) l=i+1;
193    else
194    { h=i-1;
195      if (!c) { *index=i;return 1;}
196    }
197   } 
198  *index=l;
199  return 0;
200 }
201 /* Inserts given record into table at position index.
202    Fills count field of inserted record by 1
203  */
204 void insert(struct record *key,int index)
205 { int i;long int *l;
206   if (count==limit)
207   {  
208      table=realloc(table,(limit+=delta)*(tuple_size)*sizeof(short int));
209      if (!table)
210       error("Couldn't realloc table. Table limit is %d\n",limit);
211      
212    }
213
214  for(i=count;i>index;i--)
215   memcpy(table+(i)*(tuple_size),table+(i-1)*(tuple_size),
216   (tuple_size)*sizeof(short int)); 
217  l=(long int *)(table+index*(tuple_size));
218  *l=1L;
219  memcpy(table+index*tuple_size+2,key->classes,fileCount*sizeof(short int));
220  count++;
221
222 /*
223    adds pixel into table, i.e. if record with such combination of classes
224    already exists, increments its count. Otherwise inserts new record.
225  */
226 void add_pixel(struct record *key)
227 {int index;long int *l; 
228  if (search(key,&index))
229   {
230    l=((long int *)(table+index*(tuple_size)));
231    (*l)++;
232   }
233  else insert(key,index);
234 }
235
236 /*
237    Processes cell - forms record and adds it to table
238  */
239 void do_cell(int x,int y)
240 {    int k;
241      struct record r;
242      unsigned short int *c=r.classes;  
243      for(k=0;k<fileCount;k++,c++) {
244        if (links[k]) 
245          *c=epp_get(fileinfo[k],linked_col(links[k],x),linked_row(links[k],y));
246        else
247          *c=epp_get(fileinfo[k],x,y);
248        if(*c==fileinfo[k]->offsite&&!useOffsite) return;
249      }
250      add_pixel(&r);
251
252 /*
253  * Print combinations along with cell areas
254  *
255  */
256  void print_table(void)
257 {
258  int i,j;
259  unsigned short *t;
260  for(i=0,t=table;i<count;i++,t+=tuple_size) { 
261      for(j=0;j<fileCount;j++)
262          printf("%d%c",((struct record *)t)->classes[j],delimiter);
263      if (areaInCells) 
264          printf("%ld\n",((struct record *)t)->count);
265      else 
266          printf("%0.8g\n",((struct record *)t)->count*cellArea);
267  }   
268 }
269 /*
270  *  Compute functions and print results
271  *
272  *
273  */
274 void init_functions(void)
275 { int i;
276   struct FuncItem *f;
277   for(i=0,f=funcList;i<funcCount;i++,f++) {
278      f->func(FuncInit,f->data,NULL,f->index);
279   }
280 }
281 void print_row(struct record *row)
282 {  int j;
283    struct FuncItem *f;
284   /* first, print away all things defining a combination */
285      for(j=0;j<fileCount;j++)
286          printf("%d%c",row->classes[j],delimiter);
287   /* second, compute all functions and print away results */    
288      for(j=0,f=funcList;j<funcCount;j++,f++)
289          printf("%g%c",f->func(FuncResult,f->data,row,f->index),
290              j==funcCount-1?'\n':delimiter);
291 }
292
293 void process_table(void)
294 { int i,j;
295   unsigned short *t;
296   struct record *prev=NULL;
297   struct FuncItem *f;
298   /* reset all functions persistend data */
299   init_functions();
300   fileCount=baseFiles;/* for compare to compare only files,
301                          defining combinations*/
302   for(i=0,t=table;i<count;i++,t+=tuple_size) {
303     if (prev&&compare(prev,(struct record *)t)) {
304       /* combination changed, print a row */ 
305       print_row(prev);
306       init_functions();  
307     }
308     for (j=0,f=funcList;j<funcCount;j++,f++) {
309       f->func(FuncIterate,f->data,(struct record *)t,f->index);
310     }
311     prev=(struct record *)t;
312   }
313   print_row(prev);       
314 }     
315 /*
316  * main program
317  */
318 int main(int argc, char **argv) 
319 {int i,j,k,rows;
320  EPP *base;
321  scanOpt(&i, argc, argv);
322  parseArgs(i, argc, argv);
323  if (!openCount) {
324     error("No files specified\n");
325  }
326  /* Find out base file */
327  if (!baseFile) {
328    base=fileinfo[0];
329  } else {
330    int saveCount=fileCount;
331    openFile(baseFile);
332    base=fileinfo[saveCount];
333    fileCount=saveCount;
334  }
335
336  /* Determine cell area */
337  if (areaInCells) {
338     cellArea=1.0;
339   } else {
340     cellArea=base->cell_area;
341   }
342   /* establish coordinate links */
343   for (i=0;i<fileCount;i++) {
344     if (is_aligned(base,fileinfo[i])) {
345       links[i]=NULL;
346     } else {
347       links[i]=link_epp(base,fileinfo[i]);   
348     }
349   }
350   /* create table of combinations */ 
351   if (fileCount%2) {
352     tuple_size=2+fileCount;
353   } else {
354     tuple_size=3+fileCount;
355   }
356   limit=65536;
357   delta=1024;
358   table=malloc(limit*tuple_size*sizeof(short int));
359   if (!table) 
360     error("Cannot allocate %d records\n",limit);
361   count=0;
362   /* iterate through base file */
363  rows=base->lr-base->fr;
364  install_progress_indicator(verbose?show_percent:check_int);
365  for(i=base->fr,k=1;base->lr;i++,k++)
366  { for(j=base->fc;j<base->lc;j++)
367     do_cell(j,i);
368     if (EndLineProc) if ((*EndLineProc)(j,k,rows)) {
369       clear_progress(1);  
370       exit(1);
371     }
372  
373  }
374  clear_progress(0);
375  if (funcCount) {
376     /* there are some functions. Process them */
377     process_table();
378  } else {
379     print_table();
380  }
381  free(table);
382  for(i=0;i<openCount;i++) {
383    close_epp(openFiles[i].epp);
384  }    
385  return 0;
386 }