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