/*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#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 = x1<x2 ? x1 : x2;
Y1 = y1<y2 ? y1 : y2;
X2 = x2>x1 ? 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;
}
}
syntax highlighted by Code2HTML, v. 0.9.1