/* * Eukleides version 1.0.3 * Copyright (c) Christian Obrecht 2000-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "types.h" #include "geometry.h" #include "parser.tab.h" extern symrec *tracevar; extern double tracebegin; extern int strokes; double X1, Y1, X2, Y2, Unit; int undefined = 1; void frame (double x1, double y1, double x2, double y2, double unit) { X1 = x1x1 ? x2 : x1; Y2 = y2>y1 ? y2 : y1; Unit = unit; undefined = 0; printf ("\\psset{unit=%.4fcm}\n\\pspicture*(%.4f,%.4f)(%.4f,%.4f)\n", unit, X1, Y1, X2, Y2); } void default_frame (void) { if (undefined) frame (-2, -2, 8, 6, 1); } void setcolor_string (char *col) { printf ("\\psset{linecolor=%s}\n", col); } void setcolor_flag (int flag) { char *col; switch (flag) { case BLACK: col = "black"; break; case DARKGRAY: col = "darkgray"; break; case GRAY: col = "gray"; break; case LIGHTGRAY: col = "lightgray"; break; case WHITE: col = "white"; break; case RED: col = "red"; break; case GREEN: col = "green"; break; case BLUE: col = "blue"; break; case CYAN: col = "cyan"; break; case MAGENTA: col = "magenta"; break; case YELLOW: col = "yellow"; } printf ("\\psset{linecolor=%s}\n", col); } void setthickness (float ratio) { float w; w = .5 * ratio; printf ("\\psset{linewidth=%.4fpt}\n", w); } void puttricks (char *t) { printf ("\\%s\n", t); } void draw_point (_point * A, int flag, double s) { double scale; char *opt; default_frame (); scale = s * ((flag == CROSS || flag == PLUS) ? 2 : 1); switch (flag) { case DOT: opt = "*"; break; case DISC: opt = "o"; break; case BOX: opt = "square*"; break; case CROSS: opt = "x"; break; case PLUS: opt = "+"; } printf ("\\psdots[dotstyle=%s, dotscale=%.4f](%.4f,%.4f)\n", opt, scale, A->x, A->y); } char *d_flag (int flag) { switch (flag) { case FULL: return ""; case DOTTED: return "[linestyle=dotted]"; case DASHED: return "[linestyle=dashed]"; } return ""; } void draw_vector (_vector * v, _point * A, int flag) { default_frame (); printf ("\\psline%s{->}(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag), A->x, A->y, A->x + v->x, A->y + v->y); } void draw_line (_line * l, int flag1, int flag2) { double x1, y1, x2, y2, m; default_frame (); if (ZERO (Sin (l->angle))) { x1 = X1; y1 = l->y; x2 = X2; y2 = l->y; } else if (ZERO (Cos (l->angle))) { x1 = l->x; y1 = Y1; x2 = l->x; y2 = Y2; } else { m = Tan (l->angle); x1 = (Y1 - l->y) / m + l->x; y1 = Y1; if (x1 < X1) { x1 = X1; y1 = m * (X1 - l->x) + l->y; } if (x1 > X2) { x1 = X2; y1 = m * (X2 - l->x) + l->y; } x2 = (Y2 - l->y) / m + l->x; y2 = Y2; if (x2 < X1) { x2 = X1; y2 = m * (X1 - l->x) + l->y; } if (x2 > X2) { x2 = X2; y2 = m * (X2 - l->x) + l->y; } } switch (flag2) { case HALFLINE: if (l->angle >= 0) { x1 = l->x; y1 = l->y; } else { x2 = l->x; y2 = l->y; } break; case BACKHALFLINE: if (l->angle >= 0) { x2 = l->x; y2 = l->y; } else { x1 = l->x; y1 = l->y; } } if ((x1 >= X1) && (x2 <= X2) && (y1 >= Y1) && (y2 <= Y2)) printf ("\\psline%s(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag1), x1, y1, x2, y2); } char *s_flag (int flag) { switch (flag) { case NOARROW: return ""; case ARROW: return "{->}"; case BACKARROW: return "{<-}"; case DOUBLEARROW: return "{<->}"; } return ""; } void draw_segment (_segment * s, int flag1, int flag2) { default_frame (); printf ("\\psline%s%s(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag1), s_flag (flag2), s->x1, s->y1, s->x2, s->y2); } void draw_circle (_circle * c, int flag) { default_frame (); printf ("\\pscircle%s(%.4f,%.4f){%.4f}\n", d_flag (flag), c->x, c->y, c->radius); } void draw_arc (_circle * c, double a1, double a2, int flag1, int flag2) { default_frame (); printf ("\\psarc%s%s(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", d_flag (flag1), s_flag (flag2), c->x, c->y, c->radius, a1, a2); } void draw_parabola_arc (_conic * C, double min, double max, int flag) { double c0, s0, d, t, x, b, e; c0 = Cos (C->d); s0 = Sin (C->d); d = sqrt (pow ((X1 + X2) / 2 - C->x, 2) + pow ((Y1 + Y2) / 2 - C->y, 2)) + sqrt (pow (X2 - X1, 2) + pow (Y2 - Y1, 2)); Snd_degree (&x, &x, 4 * C->a * C->a, 1, -d * d); t = sqrt (fabs (x)); b = (min < -t) ? -t : min; e = (max > t) ? t : max; printf ("\\parametricplot%s{%.4f}{%.4f}" "{%.4f t %.4f mul t dup %.4f mul mul add add " "%.4f t %.4f mul t dup %.4f mul mul add add}\n", d_flag (flag), b, e, C->x, c0, -2*s0*C->a, C->y, s0, 2*c0*C->a); } void draw_ellipse_arc (_conic * C, double min, double max, int flag) { double c0, s0; c0 = Cos (C->d); s0 = Sin (C->d); printf ("\\parametricplot%s{%.4f}{%.4f}" "{%.4f %.4f t cos mul %.4f t sin mul add add " "%.4f %.4f t cos mul %.4f t sin mul add add }\n", d_flag (flag), DEG (min), DEG (max), C->x, C->a * c0, -C->b * s0, C->y, C->a * s0, C->b * c0); } void draw_hyperbola_arc (_conic * C, double b, double e, int flag) { double c0, s0; c0 = Cos (C->d); s0 = Sin (C->d); printf ("\\parametricplot%s{%.4f}{%.4f}" "{%.4f %.4f t cos div %.4f t sin t cos div mul add add " "%.4f %.4f t cos div %.4f t sin t cos div mul add add }\n", d_flag (flag), DEG (b), DEG (e), C->x, C->a * c0, -C->b * s0, C->y, C->a * s0, C->b * c0); } void draw_conic_arc (_conic * C, double first, double last, int flag) { double min, max, d, t, b, e; default_frame (); if (first < last) { min = first; max = last; } else { min = last; max = first; } switch (C->kind) { case PARABOLA: draw_parabola_arc (C, min, max, flag); break; case ELLIPSE: draw_ellipse_arc (C, min, max, flag); break; case HYPERBOLA: d = sqrt (pow ((X1 + X2) / 2 - C->x, 2) + pow ((Y1 + Y2) / 2 - C->y, 2)) + sqrt (pow (X2 - X1, 2) + pow (Y2 - Y1, 2)); if (C->a < d) { t = atan (sqrt ((d * d - C->a * C->a) / (C->a * C->a + C->b * C->b))) / 2 + M_PI_4; b = (min < -t) ? (-t) : min; e = (t < max) ? t : max; if (b < e) draw_hyperbola_arc (C, b, e, flag); b = (min < -t + M_PI) ? (-t + M_PI) : min; e = (t + M_PI < max) ? (t + M_PI) : max; if (b < e) draw_hyperbola_arc (C, b, e, flag); } } } void draw_conic (_conic * C, int flag) { double d, t; default_frame (); switch (C->kind) { case PARABOLA: draw_parabola_arc (C, -1e8, 1e8, flag); break; case ELLIPSE: draw_ellipse_arc (C, 0, 2 * M_PI, flag); break; case HYPERBOLA: d = sqrt (pow ((X1 + X2) / 2 - C->x, 2) + pow ((Y1 + Y2) / 2 - C->y, 2)) + sqrt (pow (X2 - X1, 2) + pow (Y2 - Y1, 2)); if (C->a < d) { t = atan (sqrt ((d * d - C->a * C->a) / (C->a * C->a + C->b * C->b))) / 2 + M_PI_4; draw_hyperbola_arc (C, -t, t, flag); draw_hyperbola_arc (C, -t + M_PI, t + M_PI, flag); } } } void draw_digon (_point * A, _point * B, int flag1, int flag2) { default_frame (); printf ("\\psline%s%s(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag1), s_flag (flag2), A->x, A->y, B->x, B->y); } void draw_triangle (_point * A, _point * B, _point * C, int flag) { default_frame (); printf ("\\pspolygon%s(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag), A->x, A->y, B->x, B->y, C->x, C->y); } void draw_quadrilateral (_point * A, _point * B, _point * C, _point * D, int flag) { default_frame (); printf ("\\pspolygon%s(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag), A->x, A->y, B->x, B->y, C->x, C->y, D->x, D->y); } void draw_pentagon (_point * A, _point * B, _point * C, _point * D, _point * E, int flag) { default_frame (); printf ("\\pspolygon%s(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)" "(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag), A->x, A->y, B->x, B->y, C->x, C->y, D->x, D->y, E->x, E->y); } void draw_hexagon (_point * A, _point * B, _point * C, _point * D, _point * E, _point * F, int flag) { default_frame (); printf ("\\pspolygon%s(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)" "(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)\n", d_flag (flag), A->x, A->y, B->x, B->y, C->x, C->y, D->x, D->y, E->x, E->y, F->x, F->y); } void draw_label (char *s, _point * A, double l, double a) { default_frame (); printf ("\\uput{%.4f}[%.4f](%.4f,%.4f){$%s$}\n", l, a, A->x, A->y, s); } void draw_P_label (char *s, _point * A, double l, double a) { default_frame (); printf ("\\uput{%.4f}[%.4f](%.4f,%.4f){%s}\n", l, a, A->x, A->y, s); } void draw_S_label (char *s, _segment * sg, double l, double a) { default_frame (); printf ("\\uput{%.4f}[%.4f](%.4f,%.4f){%s}\n", l, a, (sg->x1 + sg->x2) / 2, (sg->y1 + sg->y2) / 2, s); } void draw_P_N (double v, char *s, _point * A, double l, double a) { char *fmt; default_frame (); fmt = (char *) malloc (40 + strlen (s)); sprintf (fmt, "\\uput{%%.4f}[%%.4f](%%.4f,%%.4f){%s}\n", s); printf (fmt, l, a, A->x, A->y, v); free (fmt); } void draw_S_N (double v, char *s, _segment * sg, double l, double a) { char *fmt; default_frame (); fmt = (char *) malloc (40 + strlen (s)); sprintf (fmt, "\\uput{%%.4f}[%%.4f](%%.4f,%%.4f){%s}\n", s); printf (fmt, l, a, (sg->x1 + sg->x2) / 2, (sg->y1 + sg->y2) / 2, v); free (fmt); } void draw_P_NN (double v1, double v2, char *s, _point * A, double l, double a) { char *fmt; default_frame (); fmt = (char *) malloc (40 + strlen (s)); sprintf (fmt, "\\uput{%%.4f}[%%.4f](%%.4f,%%.4f){%s}\n", s); printf (fmt, l, a, A->x, A->y, v1, v2); free (fmt); } void draw_S_NN (double v1, double v2, char *s, _segment * sg, double l, double a) { char *fmt; default_frame (); fmt = (char *) malloc (40 + strlen (s)); sprintf (fmt, "\\uput{%%.4f}[%%.4f](%%.4f,%%.4f){%s}\n", s); printf (fmt, l, a, (sg->x1 + sg->x2) / 2, (sg->y1 + sg->y2) / 2, v1, v2); free (fmt); } void mark_S (_segment * sg, int flag, double sr) { double x, y, a, c, s; default_frame (); x = (sg->x1 + sg->x2) / 2; y = (sg->y1 + sg->y2) / 2; a = S_angle (sg); s = .15 * Sin (a) * sr; c = .15 * Cos (a) * sr; switch (flag) { case SIMPLE: printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s, y + c, x + s, y - c); break; case DOUBLE: printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s - .2 * c, y + c - .2 * s, x + s - .2 * c, y - c - .2 * s); printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s + .2 * c, y + c + .2 * s, x + s + .2 * c, y - c + .2 * s); break; case TRIPLE: printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s - .4 * c, y + c - .4 * s, x + s - .4 * c, y - c - .4 * s); printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s, y + c, x + s, y - c); printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - s + .4 * c, y + c + .4 * s, x + s + .4 * c, y - c + .4 * s); break; case CROSS: printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - .7 * (s + c), y + .7 * (c - s), x + .7 * (s + c), y - .7 * (c - s)); printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", x - .7 * (s - c), y + .7 * (c + s), x + .7 * (s - c), y - .7 * (c + s)); } } void mark_A (_point * A, _point * B, _point * C, int flag, double sr) { double a1, a2, a, s; default_frame (); a1 = angle (A->x - B->x, A->y - B->y); a2 = angle (C->x - B->x, C->y - B->y); a = (a1 + a2) / 2 - ((a1 > a2) ? 180 : 0); s = .5 * sr; switch (flag) { case DOT: printf ("\\psdots[dotstyle=*, dotscale=1.2](%.4f,%.4f)\n", B->x + .2 * sr * (Cos (a1) + Cos (a2)), B->y + .2 * sr * (Sin (a1) + Sin (a2))); case SIMPLE: printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s, a1, a2); break; case DOUBLE: printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s - .05, a1, a2); printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s + .05, a1, a2); break; case TRIPLE: printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s - .08, a1, a2); printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s, a1, a2); printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s + .08, a1, a2); break; case ARROW: printf ("\\psarc{->}(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s, a1, a2); break; case BACKARROW: printf ("\\psarc{<-}(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s, a1, a2); break; case DASHED: printf ("\\psarc(%.4f,%.4f){%.4f}{%.4f}{%.4f}\n", B->x, B->y, s, a1, a2); printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)\n", B->x + (s - .075) * Cos (a), B->y + (s - .075) * Sin (a), B->x + (s + .075) * Cos (a), B->y + (s + .075) * Sin (a)); break; case DOTTED: printf ("\\psdots[dotstyle=*, dotscale=1.2](%.4f,%.4f)\n", B->x + .15 * sr * (Cos (a1) + Cos (a2)), B->y + .15 * sr * (Sin (a1) + Sin (a2))); case RIGHT: printf ("\\psline(%.4f,%.4f)(%.4f,%.4f)(%.4f,%.4f)\n", B->x + .3 * sr * Cos (a1), B->y + .3 * sr * Sin (a1), B->x + .3 * sr * (Cos (a1) + Cos (a2)), B->y + .3 * sr * (Sin (a1) + Sin (a2)), B->x + .3 * sr * Cos (a2), B->y + .3 * sr * Sin (a2)); } } void add_point (_point * A, int flag) { static int ind = 0; if (ind == 0) { default_frame (); printf ("\\psline%s\n", d_flag (flag)); } if (fabs (A->x) <= 500 && fabs (A->y) <= 500) printf ("(%.4f,%.4f)", A->x, A->y); ind++; if (ind%4 == 0) printf ("\n"); if (ind == strokes) { ind = 0; tracevar->object.number = tracebegin; } }