Annotation of OpenXM_contrib2/asir2000/plot/smoothing.c, Revision 1.2
1.2 ! takayama 1: /* $OpenXM: OpenXM_contrib2/asir2000/plot/smoothing.c,v 1.1 2000/10/15 06:56:53 takayama Exp $ */
1.1 takayama 2: #include "ca.h"
3: #include "parse.h"
4: #include "ox.h"
5: #include "ifplot.h"
6: #include "cursor.h"
7:
8: #define MAG 1
9: #define PRINT_XOFFSET 100
10: #define PRINT_YOFFSET 100
11:
12: struct polyLine {
13: int numberOfSegments;
14: int limit;
15: int *x;
16: int *y;
17: };
18:
19: static FILE *Fp = NULL;
20:
21: static void *gcmalloc(int a);
22: static struct polyLine *polyLine_new(void);
23: static struct polyLine *polyLine_addNewSegment(struct polyLine *pl,
24: int x,int y);
25: static int polyLine_lastY(struct polyLine *pl);
26: static void polyLine_outputPS(struct polyLine *pl);
27: static void polyLine_outputProlog(int xmin, int ymin, int xmax, int ymax);
28: static void polyLine_outputEpilog(void);
29: static void polyLine_error(char *s);
30: #define translateX(x) (x*MAG+PRINT_XOFFSET)
31: #define translateY(y) (y*MAG+PRINT_YOFFSET)
32: /* #define translateY(y) ((Ysize-y)*MAG+PRINT_YOFFSET) */
33: #define IS_DOT != 0
34: #define IS_POLYLINE > -1
35: #define YES 1
36: #define NO 0
37:
38:
39: static int Xsize = 0;
40: static int Ysize = 0;
41: static int updatePolyLine(struct polyLine *pl[], int plSize,
42: int prev[], int Curr[], int x);
43:
1.2 ! takayama 44: static void polyLine_outputPS_dashed_line(int x0,int y0,int x1,int y1);
! 45: static int polyLine_pline(struct canvas *can);
! 46:
! 47:
1.1 takayama 48: static void *gcmalloc(a) {
49: void *m;
50: /* BUG: interruption must be locked. */
51: m = (void *) GC_malloc(a);
52: if (m == NULL) polyLine_error("no memory");
53: return(m);
54: }
55:
56: #define MINIMAL_POLYLINE_SIZE 10
57: static struct polyLine *polyLine_new_with_size(int size) {
58: struct polyLine *pl;
59: pl = (struct polyLine *)gcmalloc(sizeof(struct polyLine));
60: pl-> limit = (size > 0? size: 1);
61: pl-> numberOfSegments = 0;
62: pl->x = (int *)gcmalloc(sizeof(int)*(pl->limit));
63: pl->y = (int *)gcmalloc(sizeof(int)*(pl->limit));
64: return(pl);
65: }
66:
67: static struct polyLine *polyLine_new(void) {
68: return( polyLine_new_with_size(MINIMAL_POLYLINE_SIZE));
69: }
70:
71: static struct polyLine *polyLine_addNewSegment(struct polyLine *pl,
72: int x,int y) {
73: int n,limit,i;
74: struct polyLine *new_pl;
75: limit = pl->limit;
76: n = pl->numberOfSegments;
77: if (n >= limit) {
78: new_pl = polyLine_new_with_size( 2*limit );
79: new_pl -> numberOfSegments = pl->numberOfSegments;
80: for (i=0; i<pl->numberOfSegments; i++) {
81: new_pl->x[i] = pl->x[i];
82: new_pl->y[i] = pl->y[i];
83: }
84: pl = new_pl;
85: }
86: pl->numberOfSegments++;
87: pl->x[n] = x;
88: pl->y[n] = y;
89: return(pl);
90: }
91:
92: static int polyLine_lastY(struct polyLine *pl) {
93: int n;
94: n = pl->numberOfSegments;
95: if (n == 0) {
96: polyLine_error("polyLine_lastY: empty polyLine.");
97: }
98: return(pl->y[n-1]);
99: }
100:
101:
102: static void polyLine_outputPS(struct polyLine *pl) {
103: int n,i;
104: n = pl->numberOfSegments;
105: if (n == 1) {
106: fprintf(Fp," %d %d ifplot_putpixel\n",translateX(pl->x[0]),translateY(pl->y[0]));
107: }else if (n > 1) {
108: fprintf(Fp," newpath ");
109: for (i=0; i<n; i++) {
110: fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i]));
111: if (i==0) fprintf(Fp," moveto ");
112: else fprintf(Fp," lineto ");
113: }
114: fprintf(Fp," stroke\n");
115: }
116: fflush(Fp);
117: }
118: static void polyLine_outputProlog(int xmin, int ymin,int xmax, int ymax) {
119: fprintf(Fp,"%%!PS-Adobe-1.0\n");
120: fprintf(Fp,"%%%%BoundingBox: %d %d %d %d \n",
121: PRINT_XOFFSET+xmin*MAG,PRINT_YOFFSET+ymin*MAG,
122: PRINT_XOFFSET+xmax*MAG, PRINT_YOFFSET+ymax*MAG);
123: fprintf(Fp,"%%%%Creator: This is generated by ifplot\n");
124: fprintf(Fp,"%%%%Title: ifplot\n");
125: fprintf(Fp,"%%%%EndComments: \n");
126: fprintf(Fp,"/ifplot_putpixel { \n");
127: fprintf(Fp," /yyy 2 1 roll def /xxx 2 1 roll def \n");
128: fprintf(Fp," gsave newpath xxx yyy .5 0 360 arc \n");
129: fprintf(Fp," fill grestore \n");
130: fprintf(Fp,"} def \n");
131: fflush(Fp);
132: }
133: static void polyLine_outputEpilog(void) {
134: fprintf(Fp,"showpage \n"); fflush(Fp);
135: }
136: static void polyLine_error(char *s) {
137: fprintf(stderr,"Error in smoothing: %s\n",s);
138: exit(-1);
139: }
140: static int updatePolyLine(struct polyLine *pl[], int plSize,
141: int prev[], int curr[],int x) {
142: /* 1 <= y <= Ysize , curr[0], curr[Ysize+1] = 0 , i=y .
143: prev = {-1, -1, -1, 0, 1, -1, 2, -1} -1: no polyLine. 0:pl[0], 1:pl[1],
144: curr = {0, 1, 0, 1, 1, 1, 0, 0} 0: no dot, 1: dot.
145: */
146: /* Return Value: plSize, pl, prev */
147: int i;
148: static int *prevHasNext = NULL;
149: static struct polyLine **tmpPl = NULL;
150: static struct polyLine **newPl = NULL;
151: int tmpPlSize = 0;
152: static int *tmpPrev = NULL;
153: int newPlSize = 0;
154: extern int Ysize;
155: if (prevHasNext == NULL) prevHasNext = (int *)gcmalloc(sizeof(int)*(Ysize+2));
156: if (tmpPl == NULL)
157: tmpPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
158: if (newPl == NULL)
159: newPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
160: if (tmpPrev == NULL) tmpPrev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
161: for (i=0; i<Ysize+2; i++) {
162: prevHasNext[i] = NO; newPl[i] = NULL; tmpPl[i] = NULL;
163: tmpPrev[i] = -1;
164: }
165: prev[0] = prev[Ysize+1] = -1;
166: for (i=1; i <= Ysize; i++) {
167: if (curr[i] IS_DOT) {
168: if (prev[i-1] IS_POLYLINE && !prevHasNext[i-1]) {
169: pl[prev[i-1]] = polyLine_addNewSegment(pl[prev[i-1]],x,i);
170: prevHasNext[i-1] = YES;
171: }else if (prev[i] IS_POLYLINE && !prevHasNext[i]) {
172: pl[prev[i]] = polyLine_addNewSegment(pl[prev[i]],x,i);
173: prevHasNext[i] = YES;
174: }else if (prev[i+1] IS_POLYLINE && !prevHasNext[i+1]) {
175: pl[prev[i+1]] = polyLine_addNewSegment(pl[prev[i+1]],x,i);
176: prevHasNext[i+1] = YES;
177: }else{
178: newPl[newPlSize] = polyLine_new();
179: newPl[newPlSize] = polyLine_addNewSegment(newPl[newPlSize],x,i);
180: newPlSize++;
181: }
182: }
183: }
184: for (i=1; i<=Ysize; i++) {
185: if (prevHasNext[i] == NO && prev[i] IS_POLYLINE) {
186: polyLine_outputPS(pl[prev[i]]);
187: }
188: }
189:
190: /* generate new pl and new prev */
191: tmpPlSize = 0; tmpPrev[0] = tmpPrev[Ysize+1] = -1;
192: for (i = 1; i<=Ysize; i++) {
193: if (prevHasNext[i] == YES) {
194: tmpPl[tmpPlSize] = pl[prev[i]];
195: tmpPrev[polyLine_lastY(pl[prev[i]])] = tmpPlSize;
196: tmpPlSize++;
197: }
198: }
199: for (i=0; i<newPlSize; i++) {
200: tmpPl[tmpPlSize] = newPl[i];
201: tmpPrev[polyLine_lastY(newPl[i])] = tmpPlSize;
202: tmpPlSize++;
203: }
204:
205: /* copy and update for the next step. */
206: for (i=0; i< Ysize+2; i++) {
207: prev[i] = tmpPrev[i];
208: }
209: for (i=0; i<tmpPlSize; i++) {
210: pl[i] = tmpPl[i];
211: }
212: return(tmpPlSize);
213: }
214:
215: /*
216: #define TEST_YSIZE 12
217: #define TEST_XSIZE 5
218: generatePS_from_image(FILE *fp) {
219: int image_test[TEST_XSIZE][TEST_YSIZE] =
220: {{0,0,1,0,0,0,0,0,0,0,0,0},
221: {0,1,0,1,0,0,0,0,0,1,0,0},
222: {0,1,0,1,1,0,0,0,1,0,1,0},
223: {0,0,1,0,0,0,0,0,0,1,0,1},
224: {0,0,0,0,0,0,1,0,0,1,0,0}};
225: struct polyLine **pl;
226: int plSize = 0;
227: int *prev;
228: int *curr;
229: int i,x,y;
230:
231: Xsize = TEST_XSIZE;
232: Ysize = TEST_YSIZE;
233: pl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
234: prev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
235: curr = (int *)gcmalloc(sizeof(int)*(Ysize+2));
236: Fp = fp;
237: polyLine_outputProlog(0,0,Xsize,Ysize);
238: for (i=0; i<= Ysize+1; i++) {
239: prev[i] = -1;
240: }
241: for (x=0; x<Xsize; x++) {
242: curr[0] = curr[Ysize+1] = 0;
243: for (y=0; y<Ysize; y++) {
244: if (image_test[x][y]) curr[y+1]=1;
245: else curr[y+1] = 0;
246: }
247: plSize = updatePolyLine(pl,plSize,prev,curr,x);
248: }
249: for (y=0; y<Ysize+2; y++) {
250: curr[y] = 0;
251: }
252: plSize = updatePolyLine(pl,plSize,prev,curr,Xsize);
253: polyLine_outputEpilog();
254: }
255: main() {
256: generatePS_from_image(stdout);
257: }
258:
259: */
1.2 ! takayama 260: static void polyLine_outputPS_dashed_line(int x0,int y0,int x1,int y1) {
! 261: extern FILE *Fp;
! 262: fprintf(Fp," gsave [3] 0 setdash newpath \n");
! 263: fprintf(Fp," %d %d moveto %d %d lineto stroke \n",x0,y0,x1,y1);
! 264: fprintf(Fp," stroke grestore \n");
! 265: }
! 266:
! 267: #define D 5
! 268: static int polyLine_pline(can)
! 269: struct canvas *can;
! 270: {
! 271: double w,w1,k,e,n;
! 272: int x0,y0,x,y,xadj,yadj;
! 273: char buf[BUFSIZ];
! 274: double adjust_scale();
! 275:
! 276: if ( can->noaxis )
! 277: return;
! 278:
! 279: xadj = yadj = 0;
! 280: if ( (can->xmin < 0) && (can->xmax > 0) ) {
! 281: x0 = (int)((can->width-1)*(-can->xmin/(can->xmax-can->xmin)));
! 282: polyLine_outputPS_dashed_line(translateX(x0),translateY(0),
! 283: translateX(x0),translateY(can->height));
! 284: } else if ( can->xmin >= 0 )
! 285: x0 = 0;
! 286: else
! 287: x0 = can->width-1-D;
! 288: if ( (can->ymin < 0) && (can->ymax > 0) ) {
! 289: y0 = (int)((can->height-1)*(can->ymax/(can->ymax-can->ymin)));
! 290: polyLine_outputPS_dashed_line(translateX(0),translateY(y0),
! 291: translateX(can->width),translateY(y0));
! 292: } else if ( can->ymin >= 0 )
! 293: y0 = can->height-1;
! 294: else
! 295: y0 = D;
! 296: /* BUG: not written yet a code for PS.
! 297: w = can->xmax-can->xmin;
! 298: w1 = w * DEFAULTWIDTH/can->width;
! 299: e = adjust_scale(EXP10(floor(log10(w1))),w1);
! 300: for ( n = ceil(can->xmin/e); n*e<= can->xmax; n++ ) {
! 301: x = (int)can->width*(n*e-can->xmin)/w;
! 302: DRAWLINE(display,d,drawGC,x,y0,x,y0-D);
! 303: sprintf(buf,"%g",n*e);
! 304: DRAWSTRING(display,d,scaleGC,x+2,y0,buf,strlen(buf));
! 305: }
! 306: w = can->ymax-can->ymin;
! 307: w1 = w * DEFAULTHEIGHT/can->height;
! 308: e = adjust_scale(EXP10(floor(log10(w1))),w1);
! 309: for ( n = ceil(can->ymin/e); n*e<= can->ymax; n++ ) {
! 310: y = (int)can->height*(1-(n*e-can->ymin)/w);
! 311: DRAWLINE(display,d,drawGC,x0,y,x0+D,y);
! 312: sprintf(buf,"%g",n*e);
! 313: if ( can->xmax <= 0 )
! 314: xadj = TEXTWIDTH(sffs,buf,strlen(buf));
! 315: DRAWSTRING(display,d,scaleGC,x0-xadj,y,buf,strlen(buf));
! 316: }
! 317: */
! 318: }
1.1 takayama 319:
320: generatePS_from_image(FILE *fp,XImage *image,int xsize, int ysize,
1.2 ! takayama 321: int color[],int colorSize,
! 322: struct canvas *can) {
1.1 takayama 323: struct polyLine **pl;
324: int plSize = 0;
325: int *prev;
326: int *curr;
327: int i,x,y,c;
328:
329: Xsize = xsize;
330: Ysize = ysize;
331: pl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2));
332: prev = (int *)gcmalloc(sizeof(int)*(Ysize+2));
333: curr = (int *)gcmalloc(sizeof(int)*(Ysize+2));
334: Fp = fp;
335: polyLine_outputProlog(0,0,Xsize,Ysize);
336: for (c=0; c<colorSize; c++) {
337: /* Set color if necessary */
338: for (i=0; i<= Ysize+1; i++) {
339: prev[i] = -1;
340: }
341: for (x=0; x<Xsize; x++) {
342: curr[0] = curr[Ysize+1] = 0;
343: for (y=0; y<Ysize; y++) {
344: if ((int) XGetPixel(image,x,y) == color[c]) curr[y+1]=1;
345: else curr[y+1] = 0;
346: }
347: plSize = updatePolyLine(pl,plSize,prev,curr,x);
348: }
349: for (y=0; y<Ysize+2; y++) {
350: curr[y] = 0;
351: }
352: plSize = updatePolyLine(pl,plSize,prev,curr,Xsize);
353: }
1.2 ! takayama 354: polyLine_pline(can);
1.1 takayama 355: polyLine_outputEpilog();
356: }
1.2 ! takayama 357:
1.1 takayama 358:
359:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>