23 static double tmin
, tmax
;
24 static double xmin
, xmax
;
25 static double ymin
, ymax
;
36 static int draw_count
;
41 draw_buf
=(DRAWBUF
*)calloc(YMAX
,sizeof(DRAWBUF
));
45 if (T
== symbol(NIL
)) {
60 set_binding_and_arglist(T
, p1
, p2
);
71 draw_flag
= 0; // so "stop" really stops
72 stop("draw calls draw");
83 check_for_parametric_draw();
92 /* xrange sets the horizontal scale
94 yrange sets the vertical scale
96 Normally, the function F is evaluated from xrange[1] to xrange[2].
98 However, if F returns a vector then parametric drawing is used. In this
99 case F is evaluated from trange[1] to trange[2].
103 check_for_parametric_draw(void)
116 create_point_set(void)
123 for (i
= 0; i
<= N
; i
++) {
124 t
= tmin
+ ((double) i
/ (double) N
) * (tmax
- tmin
);
130 for (i
= 0; i
< n
- 1; i
++)
139 if (draw_count
>= YMAX
)
142 draw_buf
[draw_count
].x
= -10000;
143 draw_buf
[draw_count
].y
= -10000;
144 draw_buf
[draw_count
].t
= t
;
150 if (!isnum(XT
) || !isnum(YT
))
155 x
= (x
- xmin
) / (xmax
- xmin
);
156 x
= (double) DIMX
* x
+ 0.5; // map 0-1 to 0-DIM, +0.5 so draw(x^3) looks right
160 y
= (y
- ymin
) / (ymax
- ymin
);
161 y
= (double) DIMY
* y
+ 0.5; // map 0-1 to 0-DIM, +0.5 so draw(x^3) looks right
172 draw_buf
[draw_count
- 1].x
= (int) x
;
173 draw_buf
[draw_count
- 1].y
= (int) y
;
176 // Evaluate F(t) and return in XT and YT.
186 if (p1
->u
.tensor
->nelem
>= 2) {
187 XT
= p1
->u
.tensor
->elem
[0];
188 YT
= p1
->u
.tensor
->elem
[1];
201 // Evaluate F(t) without stopping due to an error such as divide by zero.
206 // These must be volatile or it crashes. (Compiler error?)
207 // Read it backwards, save_tos is a volatile int, etc.
209 int volatile save_tos
;
210 U
** volatile save_frame
;
218 if (setjmp(draw_stop_return
)) {
243 fill(int i
, int k
, int level
)
248 if (level
>= MAX_DEPTH
|| draw_count
>= YMAX
)
251 dx
= abs(draw_buf
[i
].x
- draw_buf
[k
].x
);
252 dy
= abs(draw_buf
[i
].y
- draw_buf
[k
].y
);
254 if (dx
< 1 && dy
< 1)
257 t
= (draw_buf
[i
].t
+ draw_buf
[k
].t
) / 2.0;
263 fill(i
, j
, level
+ 1);
264 fill(j
, k
, level
+ 1);
267 //-----------------------------------------------------------------------------
269 // Normalize x to [0,1]
271 // Example: xmin = -10, xmax = 10, xmax - xmin = 20
273 // x x - xmin (x - xmin) / (xmax - xmin)
285 //-----------------------------------------------------------------------------
298 // default range is (-pi, pi)
304 p1
= usr_symbol("trange");
309 p1
= get_binding(p1
);
311 // must be two element vector
313 if (!istensor(p1
) || p1
->u
.tensor
->ndim
!= 1 || p1
->u
.tensor
->nelem
!= 2)
316 push(p1
->u
.tensor
->elem
[0]);
322 push(p1
->u
.tensor
->elem
[1]);
328 if (!isnum(p2
) || !isnum(p3
))
338 stop("draw: trange is zero");
352 // default range is (-10,10)
358 p1
= usr_symbol("xrange");
363 p1
= get_binding(p1
);
365 // must be two element vector
367 if (!istensor(p1
) || p1
->u
.tensor
->ndim
!= 1 || p1
->u
.tensor
->nelem
!= 2)
370 push(p1
->u
.tensor
->elem
[0]);
376 push(p1
->u
.tensor
->elem
[1]);
382 if (!isnum(p2
) || !isnum(p3
))
392 stop("draw: xrange is zero");
395 //-----------------------------------------------------------------------------
397 // Example: yrange=(-10,10)
399 // y d v (vertical pixel coordinate)
415 // = (B - y) / (B - A)
417 // where yrange=(A,B)
419 // To convert d to v, multiply by N where N = 400.
421 //-----------------------------------------------------------------------------
434 // default range is (-10,10)
440 p1
= usr_symbol("yrange");
445 p1
= get_binding(p1
);
447 // must be two element vector
449 if (!istensor(p1
) || p1
->u
.tensor
->ndim
!= 1 || p1
->u
.tensor
->nelem
!= 2)
452 push(p1
->u
.tensor
->elem
[0]);
458 push(p1
->u
.tensor
->elem
[1]);
464 if (!isnum(p2
) || !isnum(p3
))
474 stop("draw: yrange is zero");
477 void get_xyminmax(double* xminp
, double* xmaxp
, double* yminp
, double* ymaxp
) {
487 static void emit_xaxis(void);
488 static void emit_yaxis(void);
489 static void emit_xscale(void);
490 static void emit_yscale(void);
492 static void get_xzero(void);
493 static void get_yzero(void);
495 static int xzero
, yzero
;
509 for (i
= 0; i
< draw_count
; i
++) {
511 y
= DIMY
- draw_buf
[i
].y
; // flip the y coordinate
512 if (x
< 0 || x
> DIMX
)
514 if (y
< 0 || y
> DIMY
)
516 Bdisp_SetPoint_VRAM(x
+XOFF
, y
+YOFF
, 1);
526 if (yzero
< 0 || yzero
> DIMY
)
535 Bdisp_DrawLineVRAM(x
, y
, x2
, y2
);
543 if (xzero
< 0 || xzero
> DIMX
)
552 Bdisp_DrawLineVRAM(x
, y
, x2
, y2
);
559 x
= -((double) DIMX
) * xmin
/ (xmax
- xmin
) + 0.5;
571 y
= -((double) DIMY
) * ymin
/ (ymax
- ymin
) + 0.5;
576 yzero
= DIMY
- (int) y
; // flip the y coordinate
579 static void emit_xscale_f(int, char *);
585 sprintf(s
, "%g", xmin
);
587 sprintf(s
, "%g", xmax
);
588 emit_xscale_f(DIMX
, s
);
592 emit_xscale_f(int xx
, char *s
)
597 PrintMini( w
, y
, (unsigned char*)s
, 0); // get width
600 if(x
>= DIMX
) x
= x
-w
;
601 y
= YOFF
+ yzero
- 24+2;
603 PrintMini( x
, y
, (unsigned char*)s
, 0);
606 static void emit_yscale_f(int, char *);
612 sprintf(s
, "%g", ymax
);
614 sprintf(s
, "%g", ymin
);
615 emit_yscale_f(DIMY
, s
);
619 emit_yscale_f(int yy
, char *s
)
625 PrintMini( w
, y
, (unsigned char*)s
, 0); // get width
629 if(y
>= DIMY
) y
= y
-9;
631 PrintMini( x
, y
, (unsigned char*)s
, 0);
640 static unsigned char *buf;
642 static void emit_box(void);
643 static void emit_xaxis(void);
644 static void emit_yaxis(void);
645 static void emit_xscale(void);
646 static void emit_yscale(void);
647 static void emit_xzero(void);
648 static void emit_yzero(void);
649 static void get_xzero(void);
650 static void get_yzero(void);
652 static int xzero, yzero;
662 len = 1000 + 5 * draw_count;
664 buf = (unsigned char *) malloc(len);
666 h = DIM + SHIM + text_metric[SMALL_FONT].ascent + text_metric[SMALL_FONT].descent;
668 //buf[0] = (unsigned char) (h >> 8);
669 //buf[1] = (unsigned char) h;
671 //buf[2] = (unsigned char) (DIM >> 8);
672 //buf[3] = (unsigned char) DIM;
687 for (i = 0; i < draw_count; i++) {
689 y = DIM - draw_buf[i].y; // flip the y coordinate
690 if (x < 0 || x > DIM)
692 if (y < 0 || y > DIM)
696 buf[k++] = DRAW_POINT;
697 buf[k++] = (unsigned char) (x >> 8);
698 buf[k++] = (unsigned char) x;
699 buf[k++] = (unsigned char) (y >> 8);
700 buf[k++] = (unsigned char) y;
705 shipout(buf, DIM + 1, h);
712 x = -((double) DIM) * xmin / (xmax - xmin) + 0.5;
724 y = -((double) DIM) * ymin / (ymax - ymin) + 0.5;
729 yzero = DIM - (int) y; // flip the y coordinate
741 buf[k++] = (unsigned char) (x >> 8);
742 buf[k++] = (unsigned char) x;
743 buf[k++] = (unsigned char) (y >> 8);
744 buf[k++] = (unsigned char) y;
748 buf[k++] = (unsigned char) (x >> 8);
749 buf[k++] = (unsigned char) x;
750 buf[k++] = (unsigned char) (y >> 8);
751 buf[k++] = (unsigned char) y;
759 if (yzero < 0 || yzero > DIM)
762 buf[k++] = DRAW_LINE;
767 buf[k++] = (unsigned char) (x >> 8);
768 buf[k++] = (unsigned char) x;
769 buf[k++] = (unsigned char) (y >> 8);
770 buf[k++] = (unsigned char) y;
775 buf[k++] = (unsigned char) (x >> 8);
776 buf[k++] = (unsigned char) x;
777 buf[k++] = (unsigned char) (y >> 8);
778 buf[k++] = (unsigned char) y;
786 if (xzero < 0 || xzero > DIM)
789 buf[k++] = DRAW_LINE;
794 buf[k++] = (unsigned char) (x >> 8);
795 buf[k++] = (unsigned char) x;
796 buf[k++] = (unsigned char) (y >> 8);
797 buf[k++] = (unsigned char) y;
802 buf[k++] = (unsigned char) (x >> 8);
803 buf[k++] = (unsigned char) x;
804 buf[k++] = (unsigned char) (y >> 8);
805 buf[k++] = (unsigned char) y;
808 static void emit_xscale_f(int, char *);
814 sprintf(s, "%g", xmin);
816 sprintf(s, "%g", xmax);
817 emit_xscale_f(DIM, s);
821 emit_xscale_f(int xx, char *s)
823 int d, i, len, w, x, y;
825 // want to center the number w/o sign
827 w = text_width(SMALL_FONT, s);
830 d = w - text_width(SMALL_FONT, s + 1);
834 x = XOFF + xx - (w - d) / 2 - d;
835 y = YOFF + DIM + SHIM;
837 buf[k++] = SMALL_FONT;
838 buf[k++] = (unsigned char) (x >> 8);
839 buf[k++] = (unsigned char) x;
840 buf[k++] = (unsigned char) (y >> 8);
841 buf[k++] = (unsigned char) y;
843 len = (int) strlen(s);
845 buf[k++] = (unsigned char) len;
847 for (i = 0; i < len; i++)
848 buf[k++] = (unsigned char) s[i];
851 static void emit_yscale_f(int, char *);
857 sprintf(s, "%g", ymax);
859 sprintf(s, "%g", ymin);
860 emit_yscale_f(DIM, s);
864 emit_yscale_f(int yy, char *s)
868 w = text_width(SMALL_FONT, s);
871 y = YOFF + yy - text_metric[SMALL_FONT].ascent / 2;
873 buf[k++] = SMALL_FONT;
874 buf[k++] = (unsigned char) (x >> 8);
875 buf[k++] = (unsigned char) x;
876 buf[k++] = (unsigned char) (y >> 8);
877 buf[k++] = (unsigned char) y;
879 len = (int) strlen(s);
881 buf[k++] = (unsigned char) len;
883 for (i = 0; i < len; i++)
884 buf[k++] = (unsigned char) s[i];
887 // emit the '0' axis label
889 // make sure it doesn't hit the other labels
896 if (xzero < DIM / 4 || xzero > 3 * DIM / 4)
899 x = XOFF + xzero - text_width(SMALL_FONT, "0") / 2;
900 y = YOFF + DIM + SHIM;
902 buf[k++] = SMALL_FONT;
903 buf[k++] = (unsigned char) (x >> 8);
904 buf[k++] = (unsigned char) x;
905 buf[k++] = (unsigned char) (y >> 8);
906 buf[k++] = (unsigned char) y;
911 // emit the '0' axis label
913 // make sure it doesn't hit the other labels
920 if (yzero < DIM / 4 || yzero > 3 * DIM / 4)
923 x = XOFF - SHIM - text_width(SMALL_FONT, "0");
924 y = YOFF + yzero - text_metric[SMALL_FONT].ascent / 2;
926 buf[k++] = SMALL_FONT;
927 buf[k++] = (unsigned char) (x >> 8);
928 buf[k++] = (unsigned char) x;
929 buf[k++] = (unsigned char) (y >> 8);
930 buf[k++] = (unsigned char) y;