#include #include #include #include #include "cmconst.h" #define NOFCMDS 17 int ox, oy, CANVAS_WIDTH, CANVAS_HEIGHT; double scale, red, green, blue; char *grcmds[]={"color","point","line","ellipse","polygon","curve","circle","stop", "connect", "disk", "gray", "lwidth", "cwidth", "clip", "Text", "text", "rgb", 0}; double c[MNN], x[(MAXD + 1) * MAXD], z[MAXD]; int sle(int n, double c[], double d[]); int cut(char s[], int a[]); void trimming(char *s) { char *t; int f = 0; for(t = s; *t != '\0'; t++) if(*t == '.') f = 1; if(f == 0) return; for(t-- ; *t == '0'; t--) *t = '\0'; } void dtos(char *s, double x) { sprintf(s, "%f", x); trimming(s); } int cmpword(s1,s2) char *s1, *s2; { for(;;){ if(*s1>*s2) return(1); else if(*s1<*s2) return(-1); if(*(s1++)=='\0') break; s2++; } return(0); } int getl(s) char *s; { static int f = 0; int l = 0; if(f == 1) return -1; for(; l < MXSTRLH; s++, l++) { if(read(0, s, 1)>0) { if(*s == '\n') { *s = '\0'; return l; } } else { if(l==0) return(-1); f=1; *s='\0'; return(l); } } return MXSTRLH; } int getpoly(int md, double c[], char *s) { int i, x, y, d, dd = 0; char *s0, cs, xoy; double f, w = 0; for(i = 0; i < MNN; i++) c[i] = 0.; for(; *s != 0; ) { x = y = 0; f = 1.; if(*s == '+') s++; if(*s == '-') { f = -1.; s++; } for(s0 = s; ; s++) if((*s > '9' || *s < '0') && *s != '.') break; if((*s != 'x') && (*s != 'y') && (*s != 0) && (*s != '+') && (*s != '-')) return -1; if(s0 == s) w = 1.; else { cs = *s; *s = 0; w = atof(s0); *s = cs; } if(((xoy = *s) == 'x') || (xoy == 'y')) { s++; if(*s == '^') s++; for(s0 = s; ; s++) if(*s > '9' || *s < '0') break; if(s0 == s) { if(xoy == 'x') x = 1; else y = 1; } else { cs = *s; *s = 0; if(xoy == 'x') x = atoi(s0); else y = atoi(s0); *s = cs; } } if(((xoy = *s) == 'x') || (xoy == 'y')) { s++; if(*s == '^') s++; for(s0 = s; ; s++) if(*s > '9' || *s < '0') break; if(s0 == s) { if(xoy == 'x') x = 1; else y = 1; } else { cs = *s; *s = 0; if(xoy == 'x') x = atoi(s0); else y = atoi(s0); *s = cs; } } if((d = x + y) > md) return 0; if(d > dd) dd = d; c[d * (d + 1) / 2 + x] += f * w; } return dd; } void mlpoly(int md1, double c1[], int md2, double c2[]) { int i, j, k, x1, x2, d1, d2, d, md; double c3[MNN]; d = md1 + md2; md = (d + 1) * (d + 2) / 2; for(i = 0; i < md; i++) c3[i] = 0.; for(d1 = x1 = i = 0; ; x1++, i++) { if(x1 > d1) { d1++; if(d1 > md1) break; x1 = 0; } k = i; for(d2 = x2 = j = 0; ; x2++, j++) { if(x2 > d2) { d2++; if(d2 > md2) break; x2 = 0; k += d1; } c3[k++] += c1[i] * c2[j]; } } for(i = 0; i < md; i++) c1[i] = c3[i]; } void pwofpoly(int d, double c[], int n) { int i, md, d2 = d; double c2[MNN]; md = (d + 1) * (d + 2) / 2; for(i = 0; i < md; i++) c2[i] = c[i]; for(i = 1; i < n; i++, d2 += d) mlpoly(d2, c, d, c2); } void addpoly(int md1, double c1[], int md2, double c2[]) { int i, md; md = (md2 + 1) * (md2 + 2) / 2; for(i = 0; i < md; i++) c1[i] += c2[i]; } int expand(char *s, double c[]) { int i, j, ocn, f = 0, d = 0, d1, d2; char str[MXSTRLH], *ps, *ps0, *ps2; double c1[MNN], c2[MNN]; for(i = 0; i < MNN; i++) c[i] = 0.; for(ps = ps0 = str; *s != '\0'; ) { if(*s == '(') { if(f == 0) { if(ps > ps0) { for(ps2 = ps - 1; ps2 >= ps0; ps2--) if((*ps2 == '+') || (*ps2 == '-')) break; if(ps2 > ps0) { *ps2 = '\0'; d1 = getpoly(MAXD, c1, str); addpoly(d, c, d1, c1); if(d1 > d) d = d1; ps0 = ps2; } if(ps > ps2 + 1) { if(ps2 < ps0) ps2 = ps0; for(j = ps - ps2, i = 0; j > 0; j--) str[i++] = *(s - j); // for(ps2 = ps0, i = 0; ps2 < ps; ps2++) str[i++] = *(s + ps2 - ps); str[i] = '\0'; d1 = getpoly(MAXD, c1, str); } else { d1 = 0; if(*(s - 1) == '-') c1[0] = -1.; else c1[0] = 1.; } } else { d1 = 0; c1[0] = 1.; } f = 1; } for(s++, i = ocn = 0; *s != '\0'; s++) { if(*s == '(') ocn++; else if(*s == ')') { ocn--; if(ocn < 0) break; } str[i++] = *s; } str[i] = '\0'; d2 = expand(str, c2); ps = str; if(*s == '\0') break; s++; if(*s == '^') s++; for(s; (*s >= '0') && (*s <= '9'); s++) *(ps++) = *s; if(ps > str) { int n; *ps = '\0'; n = atoi(str); pwofpoly(d2, c2, n); d2 *= n; } mlpoly(d1, c1, d2, c2); d1 += d2; ps0 = ps = str; } else { if(f == 1) { addpoly(d, c, d1, c1); if(d1 > d) d = d1; f = 0; } *(ps++) = *(s++); } } if(f == 1) { addpoly(d, c, d1, c1); if(d1 > d) d = d1; } else if(ps > str) { *ps = '\0'; d1 = getpoly(MAXD, c1, str); addpoly(d, c, d1, c1); if(d1 > d) d = d1; } return d; } int checkeq(char *s) { int ocb = 0; for(; *s != '\0'; s++) { if((*s >= '0') && (*s <= '9')) continue; if((*s == 'x') || (*s == 'y') || (*s == '.') || (*s == '+') || (*s == '-') || (*s == '^')) continue; if(*s == '(') ocb++; else if(*s == ')') { ocb--; if(ocb < 0) return -1; } else return -1; } if(ocb > 0) return -1; else return 1; } int main(int argc, char *argv[]) { char s[MXSTRLH], *ps, sx[20], sy[20], sx2[20], sy2[20]; int i, j, h, l, a[MXNOFWD], dox = 0, doy = 0; double x, y, x2, y2, angle1, angle2, t, dt = 0.02; CANVAS_WIDTH = 640, CANVAS_HEIGHT = 480; scale = SCALE; for(i = 1; i < argc; i++) { if(*(ps = argv[i]) != '-') continue; ps++; if(*ps == 'W' | *ps == 'w') { if(*(++ps) == '=') ps++; if((CANVAS_WIDTH = atoi(ps)) > MAX_CANVAS_WIDTH) CANVAS_WIDTH = MAX_CANVAS_WIDTH; continue; } if(*ps == 'H' | *ps == 'h') { if(*(++ps) == '=') ps++; if((CANVAS_HEIGHT = atoi(ps)) > MAX_CANVAS_HEIGHT) CANVAS_HEIGHT = MAX_CANVAS_HEIGHT; continue; } if(*ps == 'X' | *ps == 'x') { if(*(++ps) == '=') ps++; dox = atoi(ps); continue; } if(*ps == 'Y' | *ps == 'y') { if(*(++ps) == '=') ps++; doy = atoi(ps); continue; } if(*ps == 'S' | *ps == 's') { if(*(++ps) == '=') ps++; scale = atof(ps); continue; } } ox = CANVAS_WIDTH/2 + dox; oy = CANVAS_HEIGHT - CANVAS_HEIGHT/2 + doy; printf("\%\%!PS-Adobe-3.0 EPSF-1.2\n\%\%\%\%BoundingBox: 0 0 %d %d\n", CANVAS_WIDTH, CANVAS_HEIGHT); printf("/Times-Roman findfont 24 scalefont setfont\n"); printf("/rad .5 def\n1. setlinewidth \n0. 0. 0. setrgbcolor\n"); printf("/Circ {\nnewpath\n0 360 arc\nstroke\n} def\n"); printf("/Crcl {\nnewpath\narc\nstroke\n} def\n"); printf("/Disc {\nnewpath\n0 360 arc\nfill\n} def\n"); while(getl(s) >= 2) { l=cut(s, a); for(i = 0; i < NOFCMDS; i++) if(cmpword(s,grcmds[i])==0) break; if(i == 7) break; switch(i) { case 0: if(l < 4) break; for(j = 1; j < 4; j++) { h = atoi(s + a[j]); if(h == 0) printf("0 "); else if(h == 1) printf("0.33 "); else if(h == 2) printf("0.66 "); else printf("1 "); } printf("setrgbcolor\n"); // printf("%f %f %f setrgbcolor\n", red = .33 * atoi(s + a[1]), green = .33 * atoi(s + a[2]), blue = .33 * atoi(s + a[3])); break; case 1: if(l > 2){ int count = l/2, j; if(count > MNP) count = MNP; for(j = 0; j < count; j++) { x = ox + (int)(scale * atof(s+a[2 * j + 1])); y = oy + (int)(scale * atof(s+a[2 * j + 2])); dtos(sx, (double)x); dtos(sy, (double)y); printf("%s %s 1. Disc\n", sx, sy); } } break; case 2: if(l > 3){ double lx = - (double) ox / scale, ux = (double) (CANVAS_WIDTH - ox) / scale, uy = (double) (CANVAS_HEIGHT - oy) / scale, ly = - (double) oy / scale, t, t2, cx = atof(s+a[1]), cy = atof(s+a[2]), c0 = atof(s+a[3]); if(cx == .0) { if(cy == .0) break; if((t = -c0/cy) < uy && t > ly) { x = ox + (scale * lx); y = y2 = oy + (scale * t); x2 = ox + (int)(scale * ux); dtos(sx, x); dtos(sy, y); dtos(sx2, x2); dtos(sy2, y2); printf("newpath\n%s %s moveto\n%s %s lineto\nstroke\n", sx, sy, sx2, sy2); break; } } if(cy == .0) { if((t = -c0/cx) < ux && t > lx) { x = x2 = ox + (int)(scale * t); y = oy + (scale * ly); y2 = oy + (scale * uy); dtos(sx, x); dtos(sy, y); dtos(sx2, x2); dtos(sy2, y2); printf("newpath\n%s %s moveto\n%s %s lineto\nstroke\n", sx, sy, sx2, sy2); break; } } if((t = -(cx * lx + c0)/cy) < ly) { if(cy/cx >= .0) break; if((t2 = -(cy * ly + c0)/cx) > ux) break; x = ox + (scale * t2); y = oy + (scale * ly); } else if(t <= uy) { x = ox + (scale * lx); y = oy + (scale * t); } else { if(cy/cx <= .0) break; if((t2 = -(cy * uy + c0)/cx) > ux) break; x = ox + (scale * t2); y = oy + (scale * uy); } if((t = -(cx * ux + c0)/cy) < ly) { x2 = ox + (-scale * (cy * ly + c0)/cx); y2 = oy + (scale * ly); } else if(t <= uy) { x2 = ox + (scale * ux); y2 = oy + (scale * t); } else { x2 = ox + (-scale * (cy * uy + c0)/cx); y2 = oy + (scale * uy); } dtos(sx, x); dtos(sy, y); dtos(sx2, x2); dtos(sy2, y2); printf("newpath\n%s %s moveto\n%s %s lineto\nstroke\n", sx, sy, sx2, sy2); } break; case 3: if(l > 3) { x = ox + scale * atof(s + a[1]); y = oy + scale * atof(s + a[2]); x2 = scale * atof(s + a[3]); if(l > 4) y2 = scale * atof(s + a[4]); else y2 = x2; if(l > 6) { angle1 = atof(s + a[5]); angle2 = atof(s + a[6]); } printf("newpath\n%f %f moveto\n", x + x2 * cos(angle1), y + y2 * sin(angle1)); for(t = dt; t < angle2; t += dt) { printf("%f %f lineto\n", x + x2 * cos(angle1 + t), y + y2 * sin(angle1 + t)); } printf("stroke\n"); } break; case 4: if(l > 6) { x = ox + (scale * atof(s+a[1])); y = oy + (scale * atof(s+a[2])); dtos(sx, x); dtos(sy, y); printf("newpath\n%s %s moveto\n", sx, sy); for(i = 3; i < l; ) { x = ox + (scale * atof(s+a[i++])); y = oy + (scale * atof(s+a[i++])); dtos(sx, x); dtos(sy, y); printf("%s %s lineto\n", sx, sy); } printf("closepath\nfill\n"); } break; case 5: if(l > 1) { int dd; if((checkeq(s + a[1]) > 0) && ((dd = expand(s + a[1], c)) > 1)) grdt(dd, c); } break; case 6: if(l>3) { x = ox + (scale * atof(s+a[1])); y = oy + (scale * atof(s+a[2])); x2 = (int)(scale * atof(s+a[3])); dtos(sx, x); dtos(sy, y); dtos(sx2, x2); if(l > 5) { angle1 = atof(s + a[4]) / 64; angle2 = atof(s + a[5]) / 64; if(angle2 >= 0) printf("%s %s %s %f %f Crcl\n", sx, sy, sx2, angle1, angle1 + angle2); else printf("newpath\n%s %s %s %f %f arcn\nstroke\n", sx, sy, sx2, angle1, angle1 + angle2); } else printf("%s %s %s Circ\n", sx, sy, sx2); } break; case 8: if(l > 4) { int count = l/2, j; if(count > MNP) count = MNP; x = ox + (scale * atof(s+a[1])); y = oy + (scale * atof(s+a[2])); dtos(sx, x); dtos(sy, y); printf("newpath\n%s %s moveto\n", sx, sy); for(j = 1 ;j < count; j++) { x2 = ox + (scale * atof(s + a[2 * j + 1])); y2 = oy + (scale * atof(s + a[2 * j + 2])); dtos(sx2, x2); dtos(sy2, y2); printf("%s %s lineto\n", sx2, sy2); } printf("stroke\n"); } break; case 9 : if(l > 3) { x = ox + (scale * atof(s+a[1])); y = oy + (scale * atof(s+a[2])); x2 = scale * atof(s + a[3]); dtos(sx, x); dtos(sy, y); dtos(sx2, x2); printf("%s %s %s Disc\n", sx, sy, sx2); } break; case 10 : if(l > 1) { printf("%s setgray\n", s + a[1]); } break; case 11 : if(l > 1) { printf("%f setlinewidth\n", atof(s + a[1])); } break; case 12 : if(l > 1) { printf("/rad %f def\n", atof(s + a[1])); } break; case 13: if(l > 6) { x = ox + (scale * atof(s+a[1])); y = oy + (scale * atof(s+a[2])); dtos(sx, x); dtos(sy, y); printf("newpath\n%s %s moveto\n", sx, sy); for(i = 3; i < l; ) { x = ox + (scale * atof(s+a[i++])); y = oy + (scale * atof(s+a[i++])); dtos(sx, x); dtos(sy, y); printf("%s %s lineto\n", sx, sy); } printf("closepath\nclip\n"); } break; case 14: if(l > 3) { for(i = 4; i < l; i++) *(s + a[i] - 1) = ' '; printf("%d %d moveto\n(%s) show\n", atoi(s + a[1]), CANVAS_HEIGHT - atoi(s + a[2]), s + a[3]); } break; case 15: if(l > 3) { for(i = 4; i < l; i++) *(s + a[i] - 1) = ' '; printf("%d %d moveto\n(%s) show\n", ox + (int)(scale * atof(s + a[1])), oy + (int)(scale * atof(s + a[2])), s + a[3]); } break; case 16: if(l > 3) { printf("%1.2f %1.2f %1.2f setrgbcolor\n", red = atof(s + a[1]), green = atof(s + a[2]), blue = atof(s + a[3])); } break; default: break; } } printf("showpage\n"); } #define gosa .0000000000001 void grdt(int dg, double a[]) { int ix, iy, i, j, k, n, top; double z0, c[MAXD]; top = (dg + 1) * (dg + 2) / 2 - 1; for(ix = -ox; ix < CANVAS_WIDTH - ox; ix++) { for(x[0] = 1., x[1] = (double)ix * 1./scale, i = 2; i <= dg; i++) x[i] = x[i - 1] * x[1]; for(i = 0; i <= dg; i++) { for(c[dg - i] = 0., j = i, k = dg + 1; k > i; j += k--) c[dg - i] += a[top - j] * x[k - i - 1]; } n = fdallsol(dg, c, z); for(i = 0; i < n; i++) { if((z0 = oy + z[i] * scale) >= 0. && z0 <= CANVAS_HEIGHT) printf("%f %f rad Disc\n", (double) (ox + ix), z0); } } for(iy = -oy ; iy < CANVAS_HEIGHT - oy; iy++) { for(x[0] = 1., x[1] = (double)iy * 1./scale, i = 2; i <= dg; i++) x[i] = x[i - 1] * x[1]; for(i = 0; i <= dg; i++) { for(c[dg - i] = 0., j = dg - i, k = dg; k >= i; j += k--) c[dg - i] += a[top - j] * x[k - i]; } n = fdallsol(dg, c, z); for(i = 0; i < n; i++) { if((z0 = ox + z[i] * scale) >= 0. && z0 < CANVAS_WIDTH) printf("%f %f rad Disc\n", z0 , (double) (oy + iy)); } } }