home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- extern double sqrt();
-
- #include "vogle.h"
-
- static int do_dash = 1;
-
- /* a == b or b > a */
- #define NEAR(a, b) (((a) - (b)) / (a) < 0.0001)
- #define checkdash(l) ((*(++l->dashp) == '\0' ? *(l->dashp = l->style) : *l->dashp) != '0')
-
- /*
- * Set the current dash length
- */
- void
- setdash(d)
- float d;
- {
- if (d < 0.0)
- d = -d;
-
- if (d == 0.0)
- d = 0.1;
-
- vdevice.attr->a.dash = d;
- }
-
- /*
- * Set the current linestyle as a character string of 1's and 0's
- */
- void
- linestyle(l)
- unsigned char *l;
- {
- Attribute *line;
- unsigned char *c;
-
- line = &vdevice.attr->a;
-
- if (!l || !*l) {
- line->style = NULL;
- } else {
- /*
- * If it's all non-0 (or ' ') then it's a solid line
- */
- for (c = l; *c != '\0'; c++) {
- if (*c == '0' || *c == ' ') {
- if (line->style)
- free(line->style); /* probably could realloc */
- line->style = (unsigned char *)vallocate(strlen(l) + 1);
- strcpy(line->style, l);
- line->dashp = line->style;
- line->adist = 0.0;
- do_dash = *line->dashp != '0';
-
- return;
- }
- }
- line->style = NULL;
- }
-
- return;
- }
-
- /*
- * Draw dashed lines (Duh)
- * Assumes p0 - p1 are valid (possibly clipped endpoints)
- */
- void
- dashline(p0, p1)
- register Vector p0, p1;
- {
- int vx, vy, sync;
- float dx, dy, dz, dw, dist, ldist, tdist;
- Vector pd;
- Attribute *line;
-
-
- line = &vdevice.attr->a;
- if (line->dash == 0.0) {
- vx = WtoVx(p1);
- vy = WtoVy(p1);
-
- (*vdevice.dev.Vdraw)(vx, vy);
- return;
- }
-
- /*
- * The distance for this line segment
- */
- dx = p1[V_X] - p0[V_X];
- dy = p1[V_Y] - p0[V_Y];
- dz = p1[V_Z] - p0[V_Z];
- dw = p1[V_W] - p0[V_W];
- ldist = sqrt(dx*dx + dy*dy + dz*dz + dw*dw);
-
- /*
- * If this distance is less than it takes to
- * complete the current dash then just do it.
- */
- if (ldist <= (line->dash - line->adist)) {
-
- if (NEAR(line->dash, line->adist)) {
- line->adist = 0.0;
- do_dash = checkdash(line);
- }
-
- line->adist += ldist;
-
- vx = WtoVx(p1);
- vy = WtoVy(p1);
-
- if (do_dash)
- (*vdevice.dev.Vdraw)(vx, vy);
-
- vdevice.cpVx = vx;
- vdevice.cpVy = vy;
-
- return;
-
- } else {
- if ((sync = vdevice.sync)) /* We'll sync at the end */
- vdevice.sync = 0;
-
- /*
- * If this distance will take us over the end of a
- * dash then break it up.
- */
-
- /*
- * Handle the initial case where we start in the middle
- * of a dash.
- */
-
- tdist = 0.0;
- copyvector(pd, p0);
-
- if (line->adist > 0.0) {
-
- tdist = (line->dash - line->adist);
-
- if (NEAR(line->dash, line->adist)) {
- line->adist = 0.0;
- do_dash = checkdash(line);
- }
-
- line->adist += tdist;
-
- dist = tdist / ldist;
- pd[V_X] += dx * dist;
- pd[V_Y] += dy * dist;
- pd[V_Z] += dz * dist;
- pd[V_W] += dw * dist;
- vx = WtoVx(pd);
- vy = WtoVy(pd);
-
-
- if (do_dash)
- (*vdevice.dev.Vdraw)(vx, vy);
-
- vdevice.cpVx = vx;
- vdevice.cpVy = vy;
- }
-
- dx *= line->dash / ldist;
- dy *= line->dash / ldist;
- dz *= line->dash / ldist;
- dw *= line->dash / ldist;
- dist = line->dash;
-
- while (tdist <= ldist - dist) {
-
- if (NEAR(line->dash, line->adist)) {
- line->adist = 0.0;
- do_dash = checkdash(line);
- }
-
- pd[V_X] += dx;
- pd[V_Y] += dy;
- pd[V_Z] += dz;
- pd[V_W] += dw;
-
- vx = WtoVx(pd);
- vy = WtoVy(pd);
-
- line->adist += dist;
- tdist += dist;
-
- if (do_dash)
- (*vdevice.dev.Vdraw)(vx, vy);
-
- vdevice.cpVx = vx;
- vdevice.cpVy = vy;
- }
-
-
- /*
- * Check the last little bit....
- */
- if (NEAR(line->dash, line->adist)) {
- line->adist = 0.0;
- do_dash = checkdash(line);
- }
-
- dx = p1[V_X] - pd[V_X];
- dy = p1[V_Y] - pd[V_Y];
- dz = p1[V_Z] - pd[V_Z];
- dw = p1[V_W] - pd[V_W];
- dist = sqrt(dx*dx + dy*dy + dz*dz + dw*dw);
-
- line->adist += dist;
-
- vx = WtoVx(p1);
- vy = WtoVy(p1);
-
- if (do_dash)
- (*vdevice.dev.Vdraw)(vx, vy);
-
- vdevice.cpVx = vx;
- vdevice.cpVy = vy;
- }
-
- if (sync) {
- vdevice.sync = 1;
- (*vdevice.dev.Vsync)();
- }
-
- }
-
- /*
- * draw
- *
- * draw a line form the logical graphics position to the
- * the world coordinates x, y, z.
- *
- */
- void
- draw(x, y, z)
- float x, y, z;
- {
- Token *tok;
- int vx, vy;
- Vector res;
-
-
- if (!vdevice.initialised)
- verror("draw: vogle not initialised");
-
- if (vdevice.inpolygon) {
- (*vdevice.pdraw)(x, y, z);
-
- vdevice.cpW[V_X] = x;
- vdevice.cpW[V_Y] = y;
- vdevice.cpW[V_Z] = z;
-
- vdevice.cpVvalid = 0;
-
- return;
- }
-
- if (vdevice.inobject) {
- tok = newtokens(4);
-
- tok[0].i = DRAW;
- tok[1].f = x;
- tok[2].f = y;
- tok[3].f = z;
-
- vdevice.cpW[V_X] = x;
- vdevice.cpW[V_Y] = y;
- vdevice.cpW[V_Z] = z;
-
- vdevice.cpVvalid = 0;
-
- return;
- }
-
- if (!vdevice.cpVvalid)
- multvector(vdevice.cpWtrans, vdevice.cpW, vdevice.transmat->m);
-
- vdevice.cpW[V_X] = x;
- vdevice.cpW[V_Y] = y;
- vdevice.cpW[V_Z] = z;
- multvector(res, vdevice.cpW, vdevice.transmat->m);
-
- if (vdevice.clipoff) {
- vx = WtoVx(res); /* just draw it */
- vy = WtoVy(res);
-
- if (vdevice.attr->a.style) {
- dashline(vdevice.cpWtrans, res);
- vdevice.cpVvalid = 0;
- return;
- }
-
- (*vdevice.dev.Vdraw)(vx, vy);
-
- vdevice.cpVx = vx;
- vdevice.cpVy = vy;
-
- vdevice.cpVvalid = 0;
- } else {
- if (vdevice.cpVvalid)
- quickclip(vdevice.cpWtrans, res);
- else
- clip(vdevice.cpWtrans, res);
- }
-
- vdevice.cpWtrans[V_X] = res[V_X];
- vdevice.cpWtrans[V_Y] = res[V_Y];
- vdevice.cpWtrans[V_Z] = res[V_Z];
- vdevice.cpWtrans[V_W] = res[V_W];
- }
-
-
- /*
- * draw2
- *
- * draw a line from the logical graphics position to the
- * the world coordinates x, y.
- *
- */
- void
- draw2(x, y)
- float x, y;
- {
- if (!vdevice.initialised)
- verror("draw2: vogle not initialised");
-
- draw(x, y, 0.0);
- }
-
- /*
- * rdraw
- *
- * 3D relative draw from the logical graphics position by dx, dy, dz.
- *
- */
- void
- rdraw(dx, dy, dz)
- float dx, dy, dz;
- {
- if (!vdevice.initialised)
- verror("rdraw: vogle not initialised");
-
- draw((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
- }
-
- /*
- * rdraw2
- *
- * 2D relative draw from the logical graphics position by dx, dy.
- *
- */
- void
- rdraw2(dx, dy)
- float dx, dy;
- {
- if (!vdevice.initialised)
- verror("rdraw2: vogle not initialised");
-
- draw((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), 0.0);
- }
-
- /*
- * sdraw2
- *
- * Draw directly in proportion to screen coordinates.
- */
- void
- sdraw2(xs, ys)
- float xs, ys;
- {
- int nx, ny;
-
- if (!vdevice.initialised)
- verror("sdraw2: vogle not initialised");
-
- nx = (xs / 2 + 0.5) * vdevice.sizeX;
- ny = (0.5 + ys / 2) * vdevice.sizeY;
-
- (*vdevice.dev.Vdraw)(nx, ny);
-
- vdevice.cpVx = nx;
- vdevice.cpVy = ny;
- vdevice.cpVvalid = 0;
- }
-
- /*
- * rsdraw2
- *
- * Relative draw as a fraction of screen size.
- */
- void
- rsdraw2(dxs, dys)
- float dxs, dys;
- {
- int ndx, ndy;
-
- if (!vdevice.initialised)
- verror("rsdraw2: vogle not initialised");
-
- ndx = dxs * vdevice.sizeSx / 2;
- ndy = dys * vdevice.sizeSy / 2;
-
- (*vdevice.dev.Vdraw)(vdevice.cpVx + ndx, vdevice.cpVy + ndy);
-
- vdevice.cpVx += ndx;
- vdevice.cpVy += ndy;
- }
-
-