]> www.wagner.pp.ru Git - oss/fgis.git/blob - epu/cluster.c
First checked in version
[oss/fgis.git] / epu / cluster.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "epp.h"
4 #include "dgt.h"
5 #include <math.h>
6 #include <unistd.h>
7 #include "eppl_ut.h"
8 #include <getopt.h>
9 #include <stdlib.h>
10
11
12 # ifdef __unix 
13 #   define EARLY_UNLINK 1
14 # endif
15
16 #define LABEL_DELTA 16384
17 /* step to increase size of labels array */
18 #define LABEL_INIT_SIZE 65536
19 /* initial size of label array */
20 int *labels, last, limit;
21 int megabytes=4;
22 int line_color=0;
23 EPP *epp;/*global pointer to input file for coordinate info access*/
24 int new_label()
25 { int tmp;
26   tmp=last;
27   labels[last]=0;
28   if (++last>=limit)
29    { labels=realloc(labels,(limit+=LABEL_DELTA)*sizeof(int));
30      if (!labels)
31      { fprintf(stderr,"Cannot perform realloc()\n");
32       exit(1); 
33      }
34    }
35  return tmp;
36 }
37 void *check_alloc(size_t size)
38 {void *tmp;
39  if (!(tmp=malloc(size)))
40  { fprintf(stderr,"Cannot perform malloc()\n");
41    exit(1);
42  }
43  return tmp;
44 }
45 unsigned short *alloc_buffer(int width,int *height)
46 {int i=0,l=0,h=megabytes*524288/width;
47  unsigned short *buffer;
48  buffer=malloc(h*width*sizeof(short));
49  if (!buffer)
50  { while (l<h)
51    { i=(l+h)>>1;
52      buffer=malloc(i*width*sizeof(short));
53      if (buffer)
54      { free(buffer);
55        l=i+1;
56      }
57     else
58      { h=i-1; }
59    }
60    i--;
61    i=i*3/4;
62    buffer=malloc(i*width*sizeof(short));
63    *height=i;
64  }
65  else
66   *height=h;
67  return buffer;
68 }
69 void alloc_labels()
70 { labels=check_alloc(LABEL_INIT_SIZE*sizeof(int));
71   limit=LABEL_INIT_SIZE;
72   labels[0]=1;
73   last=1;
74
75 int check_line(int this,int other)
76
77   return other==line_color;
78 }
79 int check_border(int this,int other)
80
81   return other!=this;
82 }
83
84 int base_color(int color)
85 { while (labels[color]<0) color=-labels[color];
86   return color;
87 }
88 void report_dup(int row,int col,int class1,int class2)
89 { static int dup_count=0;
90   fprintf(stderr,"\r Duplicate label %d:",++dup_count);
91   fflush(stderr);
92   printf("%10g %10g %6d %6d\n",
93   alt_xc(epp,col),alt_yc(epp,row),class1,class2); 
94
95 }
96 int merge_colors(int color1,int color2,int row,int col)
97 { color1=base_color(color1);
98   color2=base_color(color2);
99   if (labels[color1]&&labels[color2]&&labels[color1]!=labels[color2])
100      report_dup(row,col,labels[color1],labels[color2]);
101   if (color1==color2) 
102     return color1;
103   if (color1<color2) 
104      {labels[color2]=-color1;return color1;}
105   else 
106      {labels[color1]=-color2;return color2;}
107 }
108
109 int (*is_border)(int this,int other)=check_line;
110
111 int first_pass(EPP *fin,EPP *temp1,EPP *temp2, int eight_way,int do_labels)
112 { int nrows,ncol,seqrow,row,col;
113   unsigned short int *in_rp1,*in_rp2;
114   long int *out_rp1,*out_rp2;
115   int i,j,color;
116   unsigned short int *inp1,*inp2;
117   long int *cc; 
118   alloc_labels();
119  /* set up global pointer */
120   epp=fin;
121 /* calculate file sizes */
122   ncol=fin->lc-fin->fc;
123   nrows=fin->lr-fin->fr;
124 /* Allocating row buffers */
125   in_rp1=check_alloc((ncol+2)*sizeof(short int));
126   in_rp2=check_alloc((ncol+2)*sizeof(short int));
127   out_rp1=check_alloc((ncol+2)*sizeof(long int));
128   out_rp2=check_alloc((ncol+2)*sizeof(long int));
129 /* initiliazing row buffers */
130   for(i=0,cc=out_rp2,inp2=in_rp2;i<ncol+2;*(cc++)=0,*(inp2++)=line_color,i++); 
131   out_rp1[0]=0;out_rp1[ncol+1]=0;
132   *in_rp1=in_rp1[ncol+1]=line_color; 
133 /* row loop */
134   for (seqrow=1,row=fin->fr;row<fin->lr;seqrow++,row++)
135   {  /*swap output row buffers*/
136     cc=out_rp1;out_rp1=out_rp2;out_rp2=cc;    
137      /* swap input row buffers*/
138     inp1=in_rp1; in_rp1=in_rp2; in_rp2=inp1;
139      /*get input file row */
140     memcpy(in_rp2+1,epp_getline(fin,fin->fc,row),ncol*sizeof(short int));
141     /* position output files */
142     epp_put(temp1,fin->fc,row,1);
143     epp_put(temp2,fin->fc,row,1);
144     /* handle progress indicator */
145     if (*EndLineProc)
146     {int exitcode;
147      if ((exitcode=EndLineProc(row,seqrow,nrows)))
148       { return exitcode; }
149     }
150     /*scan row */
151     for(j=epp->fc,col=1,inp1=in_rp1+1,inp2=in_rp2+1,cc=out_rp2+1;
152          col<=ncol;col++,inp1++,inp2++,cc++,j++)
153      { if (*inp2==line_color) *cc=0;
154        else 
155         /*check for labels with id!=0&&id!=line_color */
156         { if (do_labels&&*inp2) 
157            { int* lptr=labels+base_color(*inp2);
158                 if (*lptr) report_dup(row,col,*inp2,*lptr);
159                    else *lptr=*inp2;
160            } 
161           if (is_border(*inp2,*inp1)) color=0; else color= out_rp1[col];  
162           if (!is_border(*inp2,*(inp2-1))) 
163             if (color) 
164               {if(*(cc-1))  
165                color=merge_colors(*(cc-1),color,row,j);
166               }
167            else color=*(cc-1);
168           if (eight_way)
169           { if (!is_border(*inp2,*(inp1-1)))
170              if (color) color=merge_colors(out_rp1[col-1],color,row,j);
171                else color=out_rp1[col-1];
172             if (!is_border(*inp2,*(inp1+1)))
173              if (color) color=merge_colors(out_rp1[col+1],color,row,j);
174               else color=out_rp1[col+1]; 
175           }
176           if (!color)
177           { int j;
178             unsigned short int *this,*next; 
179             /* no color found. Trying to get it from some right cell*/
180             for (this=inp2,next=this+1,j=col;j<=ncol&&
181                    is_border(*this,in_rp1[j]) 
182                  &&!is_border(*this,*next);this++,next++,j++);
183             if (j<=ncol&&!is_border(*this,in_rp1[j])) color=out_rp1[j];
184               else
185               { color=new_label();}
186            } else color=base_color(color);
187          *cc=color;
188         }
189     } /* end of inner loop */
190   /* save out_rp2 */
191   for (i=0,inp1=temp1->row,inp2=temp2->row,cc=out_rp2+1;
192        i<ncol;i++,cc++,inp1++,inp2++)
193   { *inp1=*cc & 0xFFFF;
194     *inp2=*cc >> 16;
195   }     
196  }
197  reset_epp(temp1);
198  reset_epp(temp2);
199  close_epp(fin);
200  free(in_rp1);
201  free(in_rp2);
202  free(out_rp1);
203  free(out_rp2);
204  last--;
205  labels[0]=0;
206  return 0;
207 }    
208  
209  
210 int remap_labels()
211 /* search array of labels to actual numer of clusters */
212 /* case where there are no label points */
213 { long int i,j,c=1;
214  
215   for (i=1;i<=last;i++)
216   { j=base_color(i);
217     if (!labels[j])
218      labels[i]=labels[j]=c++;
219     else
220      labels[i]=labels[j];   
221   }   
222   c--;
223   if (c>65535)
224   { fprintf(stderr,"Count of contours exceedes EPPL limit of 65535\n");
225     exit(2);
226   }
227   Create16bit=c>255;
228   printf("Temporary numbers used %d\nContours found %ld\n Output file will be %d-bit\n",
229           last,
230           c,
231           c>255?16:8);
232   return c;        
233 }
234 int remap_hard_labels()
235 /* link temporary numbers with actual labels .
236    mark each temporary contour with no labels by unique number greater than
237    65535 
238  
239    returns count of classes in resulting file.
240    Side effects: label[i] contain value to fill temporary contour i;
241    Create16bit is set appropriate.
242 */
243 { long int i,j,c=65536,unlabelled=0,max=0;
244   for (i=1;i<last;i++)
245   { j=base_color(i);
246     if (!labels[j])
247      { labels[j]=labels[i]=c++;unlabelled++;
248      }
249     else 
250    {
251     labels[i]=labels[j];
252     if (labels[j]>max) max=labels[j];
253    } 
254   }
255   Create16bit=max>255;
256   printf("Temporary numbers used %d\nMaximal class is %ld\nUnlabelled polygons found %ld\n",
257         last,max,unlabelled);
258   return max;    
259 }
260 int second_pass(EPP *temp1,EPP *temp2,EPP *fout)
261 /* creates final clusterized file in case, if no fill rules given
262    file is not from rasterize */
263 {int i,row,col,nrows,fc,secondc,exitcode;
264  unsigned short *src1,*src2,*dest;
265  nrows=fout->lr-fout->fr;
266  secondc=(fc=fout->fc)+1;
267  for (i=1,row=fout->fr;row<fout->lr;i++,row++)
268  { if (EndLineProc)
269     if ((exitcode=EndLineProc(row,i,nrows))) return exitcode;
270    epp_put(fout,fc,row,
271       labels[epp_get(temp1,fc,row)|(epp_get(temp2,fc,row)<<16)]);
272    for (col=secondc,src1=epp_getline(temp1,secondc,row),
273                     src2=epp_getline(temp2,secondc,row),
274                     dest=fout->row+1;
275         col<fout->lc;
276         *(dest++)=labels[*(src1++)|(*(src2++)<<16)],col++);   
277  }      
278  close_epp(temp1);
279  close_epp(temp2);
280  return 0;
281 }
282 void report_unlabelled(int row,int col,int class,int offsite)
283 { int i,*lbl;
284   printf("%g %g unlabelled\n",alt_xc(epp,col),alt_yc(epp,row));
285   for (i=1,lbl=labels+1;i<=last;i++,lbl++)
286    if (*lbl==class) *lbl=offsite;
287 }
288 void fill_and_save(EPP *fout,EPP *fill, unsigned short *rp1,
289         unsigned short *rp2, unsigned short *rp3, int row)
290 {int col=fout->fc,value;
291  for (rp1++,rp2++,rp3++;col<fout->lc;rp1++,rp2++,rp3++,col++)
292   { value=*rp2; 
293     if (!value)
294     switch (epp_get(fill,row,col))
295     { case 1:value=*rp1;break;
296       case 2:value=*(rp2+1);break;
297       case 3:value=*(rp1+1);break;
298       case 4:value=*(rp3);break;
299       case 6:value=*(rp3+1);break;
300       case 8:value=*(rp2-1);break;
301       case 9:value=*(rp1-1);break;
302       case 12: value=*(rp3-1);break;
303      }
304     epp_put(fout,col,row,value?value:fout->offsite);
305   }  
306 }
307 int second_pass_fill(EPP *temp1,EPP *temp2,EPP *fill,EPP *fout)
308 {unsigned short *rp1,*rp2,*rp3,*rtmp;
309  int i,row,col,ncols,nrows,fc,secondc,exitcode,value;
310  unsigned short *src1,*src2,*dest;
311  nrows=fout->lr-fout->fr;
312  secondc=(fc=fout->fc)+1;
313  ncols=fout->lc-fout->fc+2;
314  /*set global pointer */
315  epp=fout;
316  /* allocate buffers */
317  rp1=check_alloc(ncols*sizeof(short int));
318  rp2=check_alloc(ncols*sizeof(short int));
319  rp3=check_alloc(ncols*sizeof(short int));
320  for(i=0,rtmp=rp2;i<ncols;i++,*(rp1++)=fout->offsite);
321  *rp1=rp1[ncols-1]=*rp3=rp3[ncols-1]=fout->offsite;
322  for (row=fout->fr,i=1;row<fout->lr;i++,row++)
323  {  if (EndLineProc)
324     if ((exitcode=EndLineProc(row,i,nrows))) return exitcode;
325     for (col=fout->fc,
326            dest=rp3+1,
327            src1=epp_getline(temp1,fc,row),
328            src2=epp_getline(temp2,fc,row);
329          col<fout->lc;
330          dest++,src1++,src2++,col++)
331       {value=labels[*src1|(*src2<<16)];
332        if (value>65535)
333          report_unlabelled(row,col,value,*dest=fout->offsite);
334         else *dest=value==65534?0:value;
335       }
336      if (row>fout->fr) fill_and_save(fout,fill,rp1,rp2,rp3,row-1);
337     rtmp=rp1;
338     rp1=rp2; rp2=rp3; rp3=rtmp;
339    }
340   fill_and_save(fout,fill,rp1,rp2,rp3,fout->lc-1);   
341   close_epp(temp1);
342   close_epp(temp2);
343   close_epp(fill);
344   return 0;
345 }
346 /* rasterize should fill this variables near its beginning */
347 int right_border, bottom_border, nrow, ncol,half_vert,half_horiz;
348 int dgt2col(int x)
349 { return (((unsigned long)(x+32767))*ncol)/right_border;
350 }
351 int dgt2absrow(int y)
352 {
353  return (((unsigned long)(32767-y))*nrow)/bottom_border+1;
354 }
355 int absrow2dgt(int row)
356 {
357   return 32767-((long)((unsigned long)(row-1)*bottom_border/nrow));
358 }
359 #define CELL(buf,row,col) *(buf+row*width+col)
360 #define row2dgt(row) (absrow2dgt(row+firstrow))
361 #define dgt2row(y) (dgt2absrow(y)-firstrow)
362
363 int save_buffer(EPP *epp,unsigned short *buf,int firstrow,int lastrow,int width)
364 {unsigned short *b; int row;
365  for (row=firstrow,b=buf;row<lastrow;row++,b+=width)
366  { 
367    epp_put(epp,1,row,epp->offsite);
368    memcpy(epp->row,b,width*sizeof(short));
369    if (EndLineProc)    
370       {
371        if  ((*EndLineProc)(row,row,nrow)) return -1;
372       }
373
374  }
375  return 0;
376 }
377
378
379
380 int rasterize(DGT *dgt,EPP *fout,EPP *fill,int modulo,int divisor)
381 {unsigned short *buf,*fillbuf=NULL;
382  int width,height,firstrow,lastrow,fry,lry;
383  width=fout->lc-fout->fc;
384  ncol=width;
385  nrow=fout->lr-fout->fr;
386  right_border=(fout->XRight-fout->XLeft)/(dgt->XRight-dgt->XLeft)*65535;
387  bottom_border=(fout->YBottom-fout->YTop)/(dgt->YBottom-dgt->YTop)*65535;
388  half_horiz=right_border>>1;
389  half_vert=bottom_border>>1;
390  buf=alloc_buffer(width,&height);
391  if (fill) 
392    { 
393      height>>=1; 
394      fillbuf=buf+height*width;
395    }
396  firstrow=fout->fr;
397  lastrow=fout->fr+height;
398  do {
399  if (lastrow>fout->lc) lastrow=fout->lc;
400  memset(buf,0,width*height*sizeof(short));
401  if (fill) memset(fillbuf,0,width*height*sizeof(short));
402  reset_dgt(dgt);
403  fry=absrow2dgt(firstrow);
404  lry=absrow2dgt(lastrow);
405  while (!dgt_eof(dgt))
406    { if (dgt_is_point(dgt))
407      { int y,id,row,col;
408         if ((y=dgt_pointy(dgt))<lry&&(y>=fry))
409          { if (divisor) id=(dgt_id(dgt)%modulo)/divisor;
410                 else  id=dgt_id(dgt);
411            if (id>65533) 
412              { fprintf(stderr,"Label ID too large. Use -d or -x options\n");
413                return 1;
414              }  
415            if (!id) id=65534;
416            row=dgt2row(dgt_pointx(dgt));
417            col=dgt2col(y);
418            if (CELL(buf,row,col)) 
419             { printf("%g %g more than one object in same cell\n",alt_xc(fout,col),alt_yc(fout,row));
420             }
421            CELL(buf,row,col)=id;
422          }
423      }
424      else
425      { if (dgt_yt(dgt)>lry&&dgt_yb(dgt)<fry)
426         { int i,id,x,y;
427            POINT *start,*end,p1,p2;
428           if (fill) id=line_color;
429            else 
430           {    if (divisor) id=(dgt_id(dgt)%modulo)/divisor;
431                 else  id=dgt_id(dgt);
432               if (id>65533) 
433               { fprintf(stderr,"Line ID too large. Use -d or -x options\n");
434                  return 1;
435               }
436               if (!id) id=65534;
437            }
438           /* Now we can begin an actual drawing */
439           for (i=1,start=dgt->buffer->s,end=dgt->buffer->s+1;
440             i<dgt_line_len(dgt);i++,start++,end++)
441             if((start->y>lry&&end->y<fry)||(start->y<fry&&end->y>lry))
442              { POINT rc1,rc2;
443                 if (start->y>end->y) {p1=*end;p2=*start;}
444                   else 
445                  {p1=*start;p2=*end;}
446                 if (p1.y<lry) 
447                  {int xx=(lry-p1.y)*((int)p2.x-p1.x)/((int)p2.y-p1.y)+p1.x;
448                   p1.x=xx;
449                   p1.y=lry;
450                  }
451                 if (p2.y>fry) 
452                 {int xx=(fry-p1.y)*((int)p2.x-p1.x)/((int)p2.y-p1.y)+p1.x;
453                  p2.x=xx;
454                  p2.y=fry;
455                 }
456                 rc2.x=dgt2col(p1.x);
457                 rc2.y=dgt2row(p1.y);
458                 rc1.x=dgt2col(p2.x);
459                 rc1.y=dgt2row(p2.y);
460                 if(rc2.x==rc1.x&&rc2.y==rc1.y)
461                 { CELL(buf,rc1.y,rc1.x)=id;
462                   if (fill) CELL(buf,rc1.y,rc1.x)|=2;
463                 }
464                 else  
465                  if ((unsigned long)abs((int)p1.x-p2.x)*bottom_border>(unsigned long)abs((int)p1.y-p2.y)*right_border)
466                     { /* ïÔÒÅÚÏË ÛÉÒÅ ÞÅÍ ÄÌÉÎÎÅÅ */
467                       int xn,ndx,dy;
468                       if (rc1.x>rc2.x) 
469                        { POINT tmp=rc1;
470                          rc1=rc2;
471                          rc2=tmp;
472                          tmp=p1;
473                          p1=p2;
474                          p2=tmp;
475                        }
476                       xn=((int)p1.x+32767)*ncol-half_horiz;
477                       ndx=((int)p2.x-p1.x)*ncol;
478                       dy=(int)p2.y-p1.y;
479                       for (x=rc1.x;x<=rc2.x;x++)
480                       { unsigned long ybig=(32767UL-((right_border*x-xn)*dy/ndx+p1.y))*nrow;
481                         y=ybig/bottom_border+1-firstrow;
482                         CELL(buf,y,x)=id;
483                         if (fill)
484                          {
485                            CELL(fillbuf,y,x)|=ybig%bottom_border>half_vert?4:1;
486                          } 
487                       }
488                     }
489                    else
490                   {int yn,ndy,dx;
491                    yn=(32767-(int)p1.y)*nrow-half_vert;
492                    ndy=((int)p2.y-p1.y)*nrow; 
493                    dx=(int)p2.x-p1.x;
494                    for (y=rc1.y;y<=rc2.y;y++)
495                     { unsigned long xbig=(32767UL+((yn-bottom_border*
496                       (y-1+firstrow))*dx /ndy+p1.x))*ncol;
497                      x=xbig/right_border;
498                      CELL(buf,y,x)=id;
499                      if (fill) {
500                       CELL(fillbuf,y,x)|=xbig%right_border>half_horiz?8:2;
501                       }
502                     }
503                   }
504                  }
505                
506               
507         }
508      }
509      dgt_next(dgt); 
510    }
511  if (save_buffer(fout,buf,firstrow,lastrow,width)) {free(buf);return 1;};
512  if (fill)
513    if (save_buffer(fill,fillbuf,firstrow,lastrow,width)) {free(buf);return 1;};
514  firstrow+=height;
515  lastrow+=height;
516  } while(firstrow<fout->lc); 
517  free(buf);
518  return 0;
519 }
520 void extract_digits(int base,char *s,int *divisor,int *modulo)
521 {char *c;
522  *divisor=0;
523  *modulo=0;
524  for (c=s;*c;c++)
525   switch(*c)
526   {case '_':if (*modulo&&!*divisor)*divisor=base; 
527         else
528                *divisor*=base; 
529       *modulo*=base;
530       break;
531   case 'x':if(!*modulo) *modulo=base; 
532             else *modulo*=base;
533       if (*divisor) {fprintf(stderr,"Digits in -d or -x option must form continous range\n");
534       exit(1);
535       }
536       break;
537   default: fprintf(stderr,"Parameter of -d or -x option must consist of ``x''-es\n"
538 "for each digit to use and ``_'' for each digit to ignore\n");
539   exit(1);
540   }
541  if (*divisor==0) *divisor=1;
542  if (*modulo/ *divisor>0x10000)
543  { fprintf(stderr,"EPP file classes cannot contain more than four digits\n");
544    exit(1);
545  } 
546 }   
547
548 # ifndef EARLY_UNLINK
549
550 char __tempnames[4][80];
551 char *tempnames[]={__tempnames[0],__tempnames[1],__tempnames[2],__tempnames[3]};
552 char **tempptr=tempnames;
553 void store_temp_name(char *name)
554 {strcpy(*(tempptr++),name);
555 }
556 void remove_temp_files()
557 {while(--tempptr>=tempnames)
558   { unlink(*tempptr);
559   }
560 }
561
562 # endif
563 char cluster_help[]=
564 "Usage: cluster [--help] [-version] [-%%8lu] [-o file] [-c color] file\n";
565 char rasterize_help[]=
566 "Usage: rasterize [--help] [-version] [-o file] [-c color] [-s size]\n"
567 "\t[-x string] [-d string] [-m megabytes] [-%%pu] file\n";
568
569 int main(int argc,char **argv)
570 {struct option cluster_options[]={
571  {"help",0,0,1},
572  {"version",0,0,2},
573  {"verbose",0,0,'%'},
574  {"output-file",1,0,'o'},
575  {"line-color",1,0,'c'},
576  {"8-way",0,0,'8'},
577  {"rasterize",0,0,'R'},
578  {"labels",0,0,'l'},
579  {"unuque",0,0,'u'},
580  {NULL,0,0,0}},
581  rasterize_options[]={
582  {"help",0,0,1},
583  {"version",0,0,2},
584  {"verbose",0,0,'%'},
585  {"output-file",1,0,'o'},
586  {"cell-size",1,0,'s'},
587  {"line-color",1,0,'c'},
588  {"line-point",0,0,'p'},
589  {"digits",1,0,'d'},
590  {"hex-digits",1,0,'x'},
591  {"unique",0,0,'u'},
592  {"memory",1,0,'m'}, 
593  {NULL,0,0,0}},
594  *options=cluster_options;
595  int c,index,expect_vector=0;
596  char c_opt[]="%o:c:8Rlu",
597       r_opt[]="%o:c:s:pudxm:",
598     *optstring=c_opt;
599  char    *basename;
600  char tempname[1024],outname[1024]="";
601  int verbose=0,eight_way=0,do_labels=0,result,maxclass;
602  EPP *fin,*ffill=NULL,*ftmp1,*ftmp2,*fout;
603  int modulo=0,divisor=0; 
604  int (*remap)(void)=remap_labels;
605  double cell_size=0.0;
606  
607  if ((basename=strrchr(argv[0],'/')))
608   basename++; else basename=argv[0];
609  if (!strcmp(basename,"rasterize"))
610   { optstring=r_opt; options=rasterize_options;
611     expect_vector=1;
612     remap=remap_hard_labels;
613     do_labels=1;
614   }
615  while ((c=getopt_long(argc,argv,optstring,options,&index))!=-1)
616    switch (c)
617    {
618     case '%' :verbose=1;break;
619     case 2  : show_version("cluster","$Revision: 1.1 $");
620     case 'o':strcpy(outname,default_ext(optarg,".epp"));break;
621     case 'R':optstring=r_opt;options=rasterize_options;
622              remap=remap_hard_labels;
623              do_labels=1;
624               expect_vector=1;break;
625     case 'c':{char *endptr;
626               line_color=strtol(optarg,&endptr,0);
627               if (*endptr||line_color<=0||line_color>65535) 
628                { fprintf(stderr,"Invalid line color %s\n",optarg);
629                  exit(1);
630                }
631               break;
632               } 
633     case 'u':if (!expect_vector) is_border=check_border;
634              else {remap=remap_labels;do_labels=0;}
635              break;
636     case '8':if (expect_vector)
637              {fprintf(stderr,"option -8 is valid only in cluster mode\n");
638               exit(1);
639              }
640              eight_way=1;
641              break;
642     case  'l':if (expect_vector)
643              {fprintf(stderr,"option -l is valid only in cluster mode\n");
644               exit(1);
645              }
646              remap=remap_labels;do_labels=1;
647              break;
648     case 's':if (!expect_vector)
649              {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c);
650               exit(1);
651              }else
652              {char *endptr;
653                cell_size=strtod(optarg,&endptr);
654                if (*endptr)
655                 { fprintf(stderr,"Invalid cell size value %s\n",optarg);
656                   exit(1);
657                 }
658               }
659               break; 
660     case 'p': if (!expect_vector)
661              {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c);
662               exit(1);
663              }
664              expect_vector=2;
665              break;    
666     case 'd':if (!expect_vector)
667              {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c);
668               exit(1);
669              }
670              extract_digits(10,optarg,&divisor,&modulo);
671              break;
672     case 'x':if (!expect_vector)
673              {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c);
674               exit(1);
675              }
676              extract_digits(16,optarg,&divisor,&modulo);
677              break; 
678     case 'm':if (!expect_vector)
679              {fprintf(stderr,"option -%c is valid only in rasterize mode\n",c);
680               exit(1);
681              }else
682              {char *endptr;
683               megabytes=strtol(optarg,&endptr,0);
684               if (*endptr)
685               { fprintf(stderr,"Invalid integer value %s\n",optarg);
686               
687               exit(1);
688               }
689               }
690              break;   
691     case 1:
692     case '?':
693     default: printf(expect_vector?rasterize_help:cluster_help);
694              exit(c!=1);
695    }
696  /***********************************************************/
697  if (argc==optind)
698  {fprintf(stderr,"No input file name given\n");
699   exit(1);
700  }
701  strcpy(tempname,default_ext(argv[optind],expect_vector?".dgt":".epp"));
702  if (!*outname)
703   if (expect_vector) strcpy(outname,force_ext(tempname,".epp"));
704    else  
705 # ifdef __unix
706     strcpy(outname,"cluster.out.epp");
707 # else
708     strcpy(outname,"cluster.epp");
709 # endif   
710   install_progress_indicator(verbose?show_percent:check_int);
711  /*** Zero pass,rasterizing **********************************/
712  if (expect_vector)
713  {DGT *dgt=open_dgt(tempname);
714   int rows,cols;
715   double XR,YB;
716   if (!dgt) { fprintf(stderr,"Cannot open file %s\n",tempname);
717               exit(1);
718             }
719   /*calculating file dimensions*/
720   if (cell_size==0.0)
721   { /*no cell size given, defaulting to 1024 cells/line*/
722     cell_size=fabs(dgt->XRight-dgt->XLeft)/1024.0;
723   } 
724   cols=ceil(fabs(dgt->XRight-dgt->XLeft)/cell_size);
725   rows=ceil(fabs(dgt->YTop-dgt->YBottom)/cell_size);
726   XR=cols*cell_size;
727   if (dgt->XRight<dgt->XLeft) XR=dgt->XLeft-XR;
728    else XR+=dgt->XLeft;
729   YB=rows*cell_size;
730   if (dgt->YTop>dgt->YBottom) YB=dgt->YTop-YB;
731    else YB+=dgt->YTop;
732   fprintf(stderr,"EPP file would be %d rows by %d columns\n",rows,cols);
733  
734   /*creating outputfile*/
735   Create16bit=1;
736   if(expect_vector==1)
737   { /*rasterized file would be temporary */
738     line_color=65535;
739     strcpy(tempname,force_ext(tmpnam(NULL),".epp"));  
740   } else
741    strcpy(tempname,outname);    
742   fin=creat_epp(tempname,1,1,cols,rows,dgt->XLeft,dgt->YTop,XR,YB,
743             100,0,0);
744
745   if (!fin) {fprintf(stderr,"Cannot create file %s\n",tempname);
746                exit(1);
747             }
748   if (expect_vector==1)
749    { Create16bit=0;
750 #ifdef EARLY_UNLINK
751      unlink(tempname);
752 #else
753      store_temp_name(tempname);
754 #endif     
755      strcpy(tempname,force_ext(tmpnam(NULL),".epp"));
756      ffill=creat_epp(tempname,1,1,cols,rows,dgt->XLeft,dgt->YTop,XR,YB,
757          100,0,0);
758      if (!ffill) {fprintf(stderr,"Cannot create file %s\n",tempname);
759           exit(1);
760                  }
761 #ifdef EARLY_UNLINK
762      unlink(tempname); 
763 #else
764      store_temp_name(tempname);
765 #endif
766    }  
767   if (verbose) fprintf(stderr,"Rasterizing...\n");
768   if ((result=rasterize(dgt,fin,ffill,modulo,divisor))) 
769         exit(clear_progress(result));
770   close_dgt(dgt);
771   if (expect_vector==2)
772     { /* nothing more to do - close and exit */
773      if (fin->max<=255)
774       {
775         if (verbose) fprintf(stderr,"\rConverting to 8 bit\n");
776 #ifdef EARLY_UNLINK
777         unlink(outname);
778         fast_convert_to_8bit(fin,outname);
779 #else
780         strcpy(tempname,force_ext(outname,".8bi"));
781         fast_convert_to_8bit(fin,tempname);
782         unlink(outname);
783         rename(tempname,outname);
784 #endif  
785        } else close_epp(fin);
786       exit(clear_progress(result));
787     }
788   else
789    { reset_epp(fin);
790      reset_epp(ffill);
791    } 
792  } else
793   if (!(fin=open_epp(tempname)))
794   { fprintf(stderr,"Cannot open file %s",tempname);
795     exit(1);
796   }
797 /*************** First pass -- counting unique contours ***************/
798 if (verbose) fprintf(stderr,"\rAssembling polygons...\n");
799  
800   Create16bit=1;
801       strcpy(tempname,force_ext(tmpnam(NULL),".epp"));
802   if(!(ftmp1=creat_epp_as(tempname,fin)))
803   { fprintf(stderr,"Cannot create file %s\n",tempname);
804     exit(1);
805   }  
806 #ifdef EARLY_UNLINK
807   unlink(tempname);
808 #else
809   store_temp_name(tempname);
810 #endif
811       strcpy(tempname,default_ext(tmpnam(NULL),".epp"));
812   if(!(ftmp2=creat_epp_as(tempname,fin)))
813   { fprintf(stderr,"Cannot create file %s\n",tempname);
814     exit(1);
815   }  
816 #ifdef EARLY_UNLINK
817  unlink(tempname);
818 #else
819   store_temp_name(tempname);
820 #endif
821  if (!expect_vector&&(is_border==check_border))line_color=fin->offsite;
822  if((result=first_pass(fin,ftmp1,ftmp2,eight_way,do_labels)))
823   exit(clear_progress(result));
824 /**** creating correspondence table *************/
825  if (verbose) {fputc('\r',stderr);fflush(stderr);}
826  maxclass=remap();
827 /************* Second pass -- creating final file *****************/
828 fout=creat_epp_as(outname,ftmp1);
829 if (do_labels) fout->offsite=Create16bit?65535:255;
830 if (verbose) fprintf(stderr,"\rWriting final file...\n");
831 if (ffill)
832  result=second_pass_fill(ftmp1,ftmp2,ffill,fout);
833 else
834  result=second_pass(ftmp1,ftmp2,fout);
835  fout->max=maxclass;
836 close_epp(fout);
837 #ifndef EARLY_UNLINK
838  remove_temp_files();
839 #endif
840 return(clear_progress(result));
841