18 typedef struct U_POINT {
19 unsigned short x,y;} U_POINT;
20 typedef U_POINT *LINEBUF;
21 typedef struct INODE {
22 unsigned short int count;
24 unsigned short int limit;
28 typedef struct LINE_END { LINE_INODE buf;
31 /* ðÁÒÁÍÅÔÒÙ ËÏÎÆÉÇÕÒÁÃÉÉ */
34 /* ïÓÎÏ×ÎÙÅ ÒÁÂÏÞÉÅ ÓÔÒÕËÔÕÒÙ ÄÁÎÎÙÈ */
36 unsigned short *rp1,*rp2;
39 /* ïÓÎÏ×ÎÙÅ ÐÒÏÃÅÄÕÒÙ */
40 int epp2dgtX(int col);
41 int epp2dgtY(int row);
43 void add_segment(LINE_END line,int col,int row);
44 /* ÄÏÂÁ×ÌÑÅÔ ÓÅÇÍÅÎÔ × ÎÁÞÁÌÏ ÉÌÉ × ËÏÎÅÃ, × ÚÁ×ÉÓÉÍÏÓÔÉ ÏÔ
45 ÐÏÌÑ line->tail, ËÏÎÞÁÀÝÉÊÓÑ × ÔÏÞËÅ col,row */
46 void put_line(LINE_INODE buf);
47 /* çÅÎÅÒÁÌÉÚÕÅÔ ÌÉÎÉÀ É ÚÁÐÉÓÙ×ÁÅÔ ÅÅ. ðÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ÒÅÖÅÔ
48 ðÏ ÚÁ×ÅÒÛÅÎÉÉ ÏÐÅÒÁÃÉÉ ÏÓ×ÏÂÏÖÄÁÅÔ ×ÓÀ ÐÁÍÑÔØ, ÚÁÎÑÔÕÀ ÌÉÎÉÅÊ
50 int create_header(EPP *epp,char *dgtname);
51 /* óÏÚÄÁÅÔ ×ÙÈÏÄÎÏÊ ÆÁÊÌ */
52 void write_labels(EPP *epp,DGT *dgt);
54 void end_line(LINE_END line);
55 /* úÁ×ÅÒÛÁÅÔ ÐÏÐÏÌÎÅÎÉÅ ÌÉÎÉÉ Ó ÕËÁÚÁÎÎÏÇÏ ËÏÎÃÁ. åÓÌÉ Ó ÄÒÕÇÏÇÏ ËÏÎÃÁ
56 ÏÎÁ ÕÖÅ ÎÅ ÍÏÖÅÔ ÐÏÐÏÌÎÑÔØÓÑ, ÄÅÌÁÅÔ ÅÊ put_line */
57 LINEBUF enlarge(LINE_INODE buf);
58 /* õ×ÅÌÉÞÉ×ÁÅÔ ÄÌÉÎÕ ÌÉÎÉÉ ÎÁ 1. ðÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ÄÏ×ÙÄÅÌÑÅÔ ÐÁÍÑÔØ */
59 int smooth(LINE_INODE line,LINEBUF *buf);
61 ×ÏÚ×ÒÁÝÁÅÔ ËÏÌÉÞÅÓÔ×Ï ÕÚÌÏ×, ÏÓÔÁ×ÛÉÈÓÑ ÐÏÓÌÅ ÇÅÎÅÒÁÌÉÚÁÃÉÉ*/
62 LINE_INODE new_line(int both,int col1,int row1,int col2,int row2);
63 /* óÏÚÄÁÅÔ ÎÏ×ÕÀ ÌÉÎÉÀ, ÐÏÍÅÝÁÑ × ÎÅÅ ÅÄÉÎÓÔ×ÅÎÎÙÊ ÓÅÇÍÅÎÔ Ó ÚÁÄÁÎÎÙÍÉ
65 void join_lines(LINE_END line1,LINE_END line2);
66 /* ïÂßÅÄÉÎÑÅÔ Ä×Å ÌÉÎÉÉ × ÏÄÎÕ. */
67 int border_dgt(EPP *epp,char *dgtname,int offs_opt,int tol,int do_labels)
68 {int nrows=epp->lr-epp->fr+1;
69 int ncols=epp->lc-epp->fc+2;
70 unsigned short *left,*right,*up;
71 int this_node,next_node;
72 LINE_END hor_line,*vert_line;
74 offsite_option=offs_opt;
76 if ((i=create_header(epp,dgtname))) return i;
77 rp1=calloc(ncols,sizeof(short int));
78 rp2=calloc(ncols,sizeof(short int));
79 lines=calloc(ncols,sizeof(struct LINE_END));
83 if (EndLineProc) if ((*EndLineProc)(i,i,nrows)) return 1;
90 for(j=0;j<ncols-1;j++,left++,right++,up++,vert_line++)
91 { /* çÏÒÉÚÏÎÔÁÌØÎÙÊ ÓÅÇÍÅÎÔ*/
101 if ((this_node&SEG_LEFT)&&(!hor_line.buf))
102 fprintf(stderr,"Hor_line exists, where shouldn't x=%d y=%d\n",j,i);
103 if (!(this_node&SEG_LEFT)&&(hor_line.buf))
104 fprintf(stderr,"Hor_line doesn't exist x=%d y=%d\n",j,i);
105 if (this_node&SEG_UP)
106 if ((vert_line->tail?vert_line->buf->x_tail:vert_line->buf->x_head)!=j)
107 fprintf(stderr,"Invalid vertical segment at x=%d y=%d\n",j,i);
110 {/* ìÉÎÉÉ ÐÒÏÄÏÌÖÁÀÔÓÑ ÐÒÑÍÏ*/
111 case 0:/* äÅÌÁÔØ ÚÄÅÓØ ÎÅÞÅÇÏ */ break;
112 case SEG_UP|SEG_VERT:add_segment(*vert_line,j,i+1);
114 case SEG_LEFT|SEG_RIGHT:add_segment(hor_line,j+1,i);
116 /* ìÉÎÉÉ ÐÒÏÄÏÌÖÁÀÔÓÑ Ó ÉÚÇÉÂÏÍ */
117 case SEG_LEFT|SEG_VERT:*vert_line=hor_line;hor_line.buf=NULL;
118 add_segment(*vert_line,j,i+1);
120 case SEG_UP|SEG_RIGHT:hor_line=*vert_line;vert_line->buf=NULL;
121 add_segment(hor_line,j+1,i);
123 /* ìÉÎÉÉ ÓÌÉ×ÁÀÔÓÑ */
124 case SEG_UP|SEG_LEFT:join_lines(hor_line,*vert_line);
128 /* ìÉÎÉÑ ÓÁÍÏÚÁÒÏÖÄÁÅÔÓÑ ÎÁ ÐÕÓÔÏÍ ÍÅÓÔÅ */
129 case SEG_VERT|SEG_RIGHT:hor_line.buf=new_line(TRUE,j,i,j+1,i);
131 vert_line->buf=hor_line.buf;
132 vert_line->tail=FALSE;
133 add_segment(*vert_line,j,i+1);
136 /* ìÉÎÉÉ ÒÁÓÓÅËÁÀÔÓÑ - 5 ÓÌÕÞÁÅ× ËÏÇÄÁ × ÔÏÞËÅ 3 É ÂÏÌÅÅ ÌÉÎÉÊ */
137 case SEG_VERT|SEG_LEFT|SEG_RIGHT:
140 hor_line.buf=new_line(FALSE,j,i,j+1,i);
142 vert_line->buf=new_line(FALSE,j,i,j,i+1);
143 vert_line->tail=TRUE;
146 case SEG_UP|SEG_LEFT|SEG_RIGHT:
150 end_line(*vert_line);
151 hor_line.buf=new_line(FALSE,j,i,j+1,i);
155 case SEG_UP|SEG_LEFT|SEG_VERT:
156 /* ô È×ÏÓÔÏÍ ×ÌÅ×Ï */
157 /* ×ÙÂÒÏÓÉÔØ ÔÏÞËÕ */
159 end_line(*vert_line);
160 vert_line->buf=new_line(FALSE,j,i,j,i+1);
161 vert_line->tail=TRUE;
164 case SEG_UP|SEG_RIGHT|SEG_VERT:
165 /* ô È×ÏÓÔÏÍ ×ÐÒÁ×Ï */
166 /* ×ÙÂÒÏÓÉÔØ ÔÏÞËÕ */
167 end_line(*vert_line);
168 hor_line.buf=new_line(FALSE,j,i,j+1,i);
170 vert_line->buf=new_line(FALSE,j,i,j,i+1);
171 vert_line->tail=TRUE;
174 case SEG_UP|SEG_RIGHT|SEG_LEFT|SEG_VERT:
176 end_line(*vert_line);
178 hor_line.buf=new_line(FALSE,j,i,j+1,i);
180 vert_line->buf=new_line(FALSE,j,i,j,i+1);
181 vert_line->tail=TRUE;
185 /* ÷ÉÓÑÞÉÅ ÕÚÌÙ, ËÏÔÏÒÙÈ îå âù÷áåô */
186 fprintf(stderr,"Dangling node at x=%d,y=%d\n",j,i);
191 if (do_labels) write_labels(source,dest);
197 void add_segment(LINE_END line,int col,int row)
199 LINE_INODE l=line.buf;
203 {points=l->points+l->count-2;
204 if (points->x==col&&points[1].x==col) {points[1].y=row;return;}
205 if (points->y==row&&points[1].y==row) {points[1].x=col;l->x_tail=col;return;}
213 {LINEBUF tmp;int i=l->count;
215 if (points->x==col&&points[1].x==col) {points->y=row;return;}
216 if (points->y==row&&points[1].y==row) {points->x=col;l->x_head=col;return;}
220 for(;i>0;i--,*(points--)=*(tmp--));
227 LINEBUF enlarge(LINE_INODE buf)
228 { if (buf->count++==buf->limit)
229 buf->points=realloc(buf->points,(buf->limit+=DELTA)*sizeof(U_POINT));
232 void end_line(LINE_END line)
233 { if (line.buf->both_ends)
234 line.buf->both_ends=FALSE;
239 #define DEBUG_CHECK(x1,x2) if (line1.buf->x1!=line2.buf->x2) fprintf(stderr,"Joining lines with separate ends %d %d\n",line1.buf->x1,line2.buf->x2)
241 #define DEBUG_CHECK(x1,x2)
243 #define COPY_DIRECT(l) for(i=l.buf->count,source=l.buf->points;i>0;i--,*(dest++)=*(source++))
244 #define COPY_REVERSE(l) for(i=l.buf->count,source=l.buf->points+l.buf->count-1;i>0; i--,*(dest++)=*(source--))
245 void join_lines(LINE_END line1,LINE_END line2)
249 if (line1.buf==line2.buf)
250 { put_line(line1.buf);
253 new=malloc(sizeof(struct INODE));
254 new->count=line1.buf->count+line2.buf->count-1;
255 new->limit=(new->count+DELTA-1)/DELTA*DELTA;
256 new->points=malloc(new->limit*sizeof(U_POINT));
261 new->x_head=line1.buf->x_head;
267 DEBUG_CHECK(x_tail,x_tail);
268 new->x_tail=line2.buf->x_head;
272 { DEBUG_CHECK(x_tail,x_head);
273 new->x_tail=line2.buf->x_tail;
279 new->x_head=line1.buf->x_tail;
283 { DEBUG_CHECK(x_head,x_tail);
284 new->x_tail=line2.buf->x_head;
288 { DEBUG_CHECK(x_head,x_head);
289 new->x_tail=line2.buf->x_tail;
294 if (line1.buf->both_ends)
296 lines[new->x_head].buf=new;
297 lines[new->x_head].tail=FALSE;
299 if (line2.buf->both_ends)
301 lines[new->x_tail].buf=new;
302 lines[new->x_tail].tail=TRUE;
304 if (new->both_ends<0)
306 free(line1.buf->points);
307 free(line2.buf->points);
311 LINE_INODE new_line(int both,int col1,int row1,int col2,int row2)
312 {LINE_INODE tmp=malloc(sizeof(struct INODE));
316 tmp->points=malloc(DELTA*sizeof(U_POINT));
317 tmp->points[0].x=col1;
318 tmp->points[0].y=row1;
319 tmp->points[1].x=col2;
320 tmp->points[1].y=row2;
326 { unsigned short int *tmp,*tmp2;
331 if(row+source->fr<source->lr)
333 epp_get(source,source->fc,source->fr+row);
334 memcpy(rp1+1,source->row,(source->lc-source->fc)*sizeof(short));
336 { rp1[0]=source->offsite;
337 rp1[source->lc-source->fc+1]=source->offsite;
341 tmp=rp1+source->lc-source->fc;
347 for(i=source->lc-source->fc,tmp=rp1;i>=0;*(tmp++)=source->offsite,i--);
349 for(i=source->lc-source->fc,tmp=rp1,tmp2=rp2;i>=0;*(tmp++)=*(tmp2++),i--);
352 for(i=source->lc-source->fc+1,tmp=rp2;i>=0;*(tmp++)=source->offsite,i--);
354 for(i=source->lc-source->fc,tmp=rp2,tmp2=rp1;i>=0;*(tmp++)=*(tmp2++),i--);
356 void put_line(LINE_INODE line)
357 {static int lineno=1;
358 int c,n;LINEBUF p;LINEBUF buf;POINT *s;
359 if (tolerance) c=smooth(line,&buf);
360 else {c=line->count;buf=line->points;}
363 { if (c>500) {n=500;c-=499;} else {n=c;c=0;}
365 dest->buffer->npoints=n;
367 for(;n>0;p++,n--,s++)
368 {s->x=epp2dgtX(p->x);
380 int create_header(EPP *epp,char *dgtname)
382 get_epp_header(epp,&h);
383 dest=creat_dgt(dgtname,epp->XLeft,epp->YBottom,epp->XRight,epp->YTop,h.coord_sys);
384 if (dest==NULL) return errno;
386 rowfact=epp->lr-epp->fr;
387 colfact=epp->lc-epp->fc;
388 if (tolerance) {rowfact*=2;colfact*=2;}
391 int epp2dgtX(int col)
392 { return (col*(unsigned long)65535/colfact-32768);
394 int epp2dgtY(int row)
395 { return (32767-row*(unsigned long)65535/rowfact);
399 #define seg_len(a) abs(a->x-a[1].x?:a->y-a[1].y)
401 #define seg_len(a) abs(a->x-a[1].x?a->x-a[1].x:a->y-a[1].y)
403 U_POINT make_middle_point(LINEBUF src1,LINEBUF src2)
405 tmp.x=src1->x+src2->x;
406 tmp.y=src1->y+src2->y;
409 int smooth(LINE_INODE line,LINEBUF *buf)
411 LINEBUF dest,src1,src2;
412 int i,prev_kept=TRUE;
415 line->points->x=2*line->points->x;
416 line->points->y=2*line->points->y;
417 line->points[1].x=2*line->points[1].x;
418 line->points[1].y=2*line->points[1].y;
422 tmp=malloc(((4*line->count)/3+1)*sizeof(U_POINT));
427 for(i=line->count-2,src2=src1+1;i>=0;i--,src1++,src2++)
430 { if (seg_len(src1)<tolerance)
431 {*(dest++)=make_middle_point(src1,src2);prev_kept=FALSE;}
434 if (i&&seg_len(src2)<tolerance)
435 {*(dest++)= make_middle_point(src1,src2);prev_kept=FALSE;}
438 dest->y=src2->y*2;dest++;
443 { U_POINT tmp=make_middle_point(src1,src2);
445 if (((dest-1)->x-dest->x)*(dest->y-tmp.y)==
446 ((dest-1)->y-dest->y)*(dest->x-tmp.x)) *dest=tmp; else *(++dest)=tmp;
448 if(seg_len(src1)>tolerance)
450 if(i&&seg_len(src2)>tolerance)
463 if(seg_len(dest)<tolerance) *dest=dest[1]; else dest++;
464 if(seg_len(tmp)<tolerance) *(++tmp)=**buf;
467 line->count=dest-tmp+1;
471 void write_labels(EPP *epp,DGT *dgt)
475 int main(int argc,char **argv)
476 { struct option longoptions[]={
477 {"tolerance",1,0,'t'},
479 {"output-file",1,0,'o'},
488 int tolerance=0,draw_frame=1,do_labels=0;
489 char *endptr,outname[1024]="";
491 while ((c=getopt_long(argc,argv,"t:mo:l%",longoptions,&index))!=-1)
494 case 't':tolerance=strtol(optarg,&endptr,0);
495 if (*endptr||tolerance<0||tolerance>100)
496 { fprintf(stderr,"Invalalid tolerance value %s\n",optarg);
500 case 'f':draw_frame=0;break;
501 case 'l':do_labels=1;break;
502 case 'm':draw_frame=0;break;
504 case '%':verbose=1;break;
505 case 'o':strcpy(outname,default_ext(optarg,".dgt"));
507 case 2:show_version("border","$Revision: 1.1 $");
510 printf ("Usage:border [-%%][-f][-l][-t value][-o file] file.epp\n");
513 if (optind==argc) { fprintf(stderr,"No input file given\n");
516 if (!*outname) strcpy(outname,force_ext(argv[optind],".dgt"));
517 epp=open_epp(default_ext(argv[optind],".epp"));
518 if (!epp) {fprintf(stderr,"Cannot open input file %s\n",argv[optind]);
521 install_progress_indicator(verbose?show_percent:check_int);
522 if ((c=clear_progress(
523 border_dgt(epp,outname,draw_frame,tolerance,do_labels))))