home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 31 */
-
- /* TADC.C
- ¬⌐┼v (C) 1991-1992 Autodesk ñ╜Ñq
-
- Ñ╗│n┼ΘºK╢O¿╤▒z╢iªµÑ⌠ª≤Ñ╬│~╗▌¿D¬║½■¿⌐íB¡╫º∩ñ╬╡oªµ, ª²¼O░╚╜╨┐φ┤`ñU¡z
- ¡∞½h :
-
- 1) ñWªC¬║¬⌐┼v│qºi░╚╗▌ÑX▓{ªb¿Cñ@Ñ≈½■¿⌐∙╪íC
- 2) ¼█├÷¬║╗í⌐·ñσÑ≤ñ]Ñ▓╢╖⌐·╕ⁿ¬⌐┼v│qºiñ╬Ñ╗╢╡│\Ñi│qºiíC
-
- Ñ╗│n┼Θ╢╚┤ú¿╤º@¼░└│Ñ╬ñW¬║░╤ª╥, ª╙Ñ╝┴n⌐·⌐╬┴⌠ºtÑ⌠ª≤½O├╥; ╣∩⌐≤Ñ⌠ª≤»S«φ
- Ñ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºtÑX¿π¬║½O├╥, ªbª╣ñ@╖ºñ⌐ÑHº_╗{íC
-
-
-
- Some example ADS code demonstrating the use of ads_tablet() and
- tablet mode in general.
-
- DIGPASS shows how to establish a "pass-through" tablet
- transformation in any UCS (doing it in world coordinates is
- trivial). It is used by BILINCAL.
-
- SAMPLE, BILINCAL, and BILINMPT together demonstrate a possible
- implementation of a different tablet transformation than any
- supported directly by AutoCAD.
-
- SAVCAL and RSTCAL constitute a trivial matched pair of functions
- to save the current tablet calibration and subsequently to restore
- it.
-
- Greg Lutz
- May, 1991
-
- The matrix arithmetic in this file holds strictly to the ADS/LISP
- conventions:
-
- 1. m[i][j] is the element in row i, column j of matrix m.
- 2. Transforming vector v by matrix m is done by treating v
- as a column vector and computing m x v.
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "adslib.h"
-
- /* Special assertion handler for ADS applications. */
-
- #ifndef NDEBUG
- #define assert(ex) {if (!(ex)){ads_printf( \
- /*MSG1*/"TADC: ┴n⌐· (%s) Ñó▒╤: └╔«╫íu%sív, \
- ▓─ %d ªC\n", /*MSG0*/" ex ",__FILE__,__LINE__); \
- ads_abort(/*MSG2*/"íu┴n⌐·ívÑó▒╤íC");}}
- #else
- #define assert(ex)
- #endif
-
- #ifndef GOOD
- #define GOOD 0
- #define BAD (-1)
- #endif
-
-
- /* Some macros which we need more generally available somewhere, sometime: */
-
- #define TYPSTRUC(size) typedef struct {char dummy[size];}
- #define movecnt(c,t,f) if (1) {TYPSTRUC(c)*_p_; *(_p_)(t) = *(_p_)(f);} else
- #define cpy(s,t,f) movecnt(sizeof(s), t, f)
-
- #define cpyname(to, from) cpy(ads_name, to, from) /* Copy an ads_name */
- #define cpypoint(to, from) cpy(ads_point, to, from) /* Copy an ads_point */
-
-
- /* The arbaxis crossover point: */
- #define ARBBOUND 0.015625 /* aka "1/64" */
-
- /* Saved tablet calibration from savcal() */
- static struct resbuf *tcal = NULL;
-
-
- /* Local function declarations */
-
- int digpass _((void));
- int idigpass _((void));
- int bilincal _((void));
- int ibilinmpt _((ads_real *in, ads_real *out));
- int bilinmpt _((void));
- void cross _((ads_real *ap, ads_real *bp, ads_real *cp));
- void matxmat _((ads_matrix cp, ads_matrix ap, ads_matrix bp));
- int normalize _((ads_real *ap, ads_real *bp));
- void pswap _((ads_real *p1, ads_real *p2));
- int sample _((void));
- void dline _((char *p1str, char *p2str));
- void dvert _((char *p1str));
- int savcal _((void));
- int rstcal _((void));
- void aperror _((char *routine));
-
-
- /* Table of externally defined functions */
- static struct {
- char *fcn_name;
- int (*fcn) _((void));
- } fcn_table[] = {
- {/*MSG0*/"digpass", digpass},
- {/*MSG0*/"c:bilincal", bilincal},
- {/*MSG0*/"bilinmpt", bilinmpt},
- {/*MSG0*/"c:sample", sample},
- {/*MSG0*/"savcal", savcal},
- {/*MSG0*/"rstcal", rstcal},
- };
- #define NFCN (sizeof fcn_table/sizeof fcn_table[0])
-
-
- /* Calibration points for bilincal() and bilinmpt(): */
- static ads_point t[4], p[4];
- static int cbrated = FALSE; /* Not calibrated yet */
- static int bilinsgn; /* Sign to use in quadratic */
-
-
- /* MAIN - the main routine */
-
-
- void
- /*FCN*/main(argc, argv)
- int argc;
- char *argv[];
- {
- int rqcode, rscode, i;
-
- ads_init(argc, argv); /* Initialize the interface */
- rscode = RSRSLT; /* Initial request code */
- for ( ;; ) {
- /* Send link partner a result code, get back a request: */
- if ((rqcode = ads_link(rscode)) < 0) {
-
- printf(/*MSG1*/"TADC: Ñ╤ ads_link() ╢╟ª^¬║ñú¿╬íu╗▌¿D╜Xív= %d\n", rqcode);
- /* Note the printf, not ADS_printf */
- fflush(stdout);
- exit(1);
- }
-
- /* Handle the request code */
- switch (rqcode) {
- case RQXLOAD:
- /* (Re-)define functions */
- rscode = RSRSLT;
- for (i = 0; i < NFCN && rscode == RSRSLT; i++)
- if (ads_defun(fcn_table[i].fcn_name, i) != RTNORM
- || ads_regfunc(fcn_table[i].fcn, i) != RTNORM
- )
- rscode = RSERR; /* Result code = error */
- if (rscode == RSRSLT)
- /* NOTE!!! The following line will have unknown
- consequences if this application is loaded via
- acad.ads!!!!*/
- ads_printf(/*MSG2*/"\n\n┴ΣñJ SAMPLE ¿╙░⌡ªµíu└│Ñ╬╡{ªíív┤·╕╒\n");
- break;
- case RQSUBR:
- i = ads_getfuncode();
- rscode = (*fcn_table[i].fcn)();
- break;
- }
- }
- }
-
-
- /* DIGPASS -- External function to establish a tablet transformation
- such that a tablet point with coordinates (x,y) maps
- into the point (x,y) in the current UCS. Returns
- RSRSLT or RSERR. */
-
- static int
- /*FCN*/digpass()
- {
- register int stat = idigpass();
- ads_retvoid();
- return stat;
- }
-
-
-
- /* IDIGPASS -- Internal function which does the actual work of
- DIGPASS. Returns RSRSLT or RSERR. */
- static int
- /*FCN*/idigpass()
- {
- ads_matrix uwxform, wlxform, ulxform;
- static ads_point ey = {0.0, 1.0, 0.0},
- ez = {0.0, 0.0, 1.0};
- ads_point ucszdir;
- struct resbuf uo, ux, uy, *ttl;
- int i;
-
- /* Fetch the origin, x-axis direction, and y-axis direction of the
- current UCS, and compute the z-axis direction */
-
- ads_getvar(/*MSG0*/"UCSORG", &uo);
- ads_getvar(/*MSG0*/"UCSXDIR", &ux);
- ads_getvar(/*MSG0*/"UCSYDIR", &uy);
- cross(ucszdir, ux.resval.rpoint, uy.resval.rpoint);
-
- /* Use these to build the transformation from UCS to world coords
- (the above axis vectors, and the origin, become the COLUMNS of
- this matrix). */
-
- for (i = X; i <= Z; i++) {
- uwxform[i][X] = ux.resval.rpoint[i];
- uwxform[i][Y] = uy.resval.rpoint[i];
- uwxform[i][Z] = ucszdir[i];
- uwxform[i][T] = uo.resval.rpoint[i];
- }
-
- /* Use the AutoCAD "arbaxis" algorithm to construct the transforma-
- tion from world coordinates to the current LCS (determined
- solely by the UCS Z-axis direction) */
-
- if (fabs(ucszdir[X]) < ARBBOUND && fabs(ucszdir[Y]) < ARBBOUND)
- cross(wlxform[X], ey, ucszdir);
- else
- cross(wlxform[X], ez, ucszdir);
- normalize(wlxform[X], wlxform[X]);
- cross(wlxform[Y], ucszdir, wlxform[X]);
- normalize(wlxform[Y], wlxform[Y]);
- cpypoint(wlxform[Z], ucszdir);
- for (i = X; i <= Z; i++)
- wlxform[i][T] = 0.0; /* No translation */
-
- /* Compose those two matrices to get the UCS-to-LCS transformation */
- matxmat(ulxform, wlxform, uwxform);
-
- /* Transformation's Z-column should be (0,0,1): */
-
- #if 0 /* These asserts cause compilation errors on the Sparc... */
- assert(fabs(ulxform[X][Z]) < 1.0E-10);
- assert(fabs(ulxform[Y][Z]) < 1.0E-10);
- assert(fabs(ulxform[Z][Z] - 1.0) < 1.0E-10);
- #endif
-
- /* That's it: if the tablet sends in point (x,y), this matrix will
- act as if x and y were in UCS coords and transform them into the
- corresponding point (u,v) in LCS coords. AutoCAD needs to turn
- that back into UCS coordinates, and (x,y) is the pair it comes
- up with. We just need to throw away the Z-column (which we just
- assured is zero anyway) and pass the rows to ads_tablet(). */
-
- ulxform[X][Z] = ulxform[X][T];
- ulxform[Y][Z] = ulxform[Y][T];
- ttl = ads_buildlist(RTSHORT, 1,
- RT3DPOINT, ulxform[X],
- RT3DPOINT, ulxform[Y],
- RT3DPOINT, ez,
- RT3DPOINT, ucszdir,
- RTNONE);
- i = ads_tablet(ttl, NULL); /* Send it to AutoCAD */
- ads_relrb(ttl);
- if (i != RTNORM) {
- aperror(/*MSG0*/"ads_tablet");
- return RSERR;
- } else
- return RSRSLT;
- }
-
-
-
- /* Some geometric utility functions */
-
-
- /* CROSS - cross product of two vectors, a = b X c */
-
- void
- /*FCN*/cross(ap, bp, cp)
- ads_real *ap;
- ads_real *bp, *cp;
- {
- ap[X] = bp[Y] * cp[Z] - bp[Z] * cp[Y];
- ap[Y] = bp[Z] * cp[X] - bp[X] * cp[Z];
- ap[Z] = bp[X] * cp[Y] - bp[Y] * cp[X];
- }
-
-
- /* MATXMAT -- Multiply two matrices. The matrix type, ads_matrix,
- may be any array type with at least three rows and four
- columns. */
-
- void
- /*FCN*/matxmat(matrixc, matrixa, matrixb)
- ads_matrix matrixc, matrixa, matrixb;
- {
- int i, k;
-
- for (i = X; i <= Z; i++)
- for (k = X; k <= Z; k++)
- matrixc[i][k] = matrixa[i][X] * matrixb[X][k] +
- matrixa[i][Y] * matrixb[Y][k] +
- matrixa[i][Z] * matrixb[Z][k];
- for (i = X; i <= Z; i++)
- matrixc[i][T] = matrixa[i][X] * matrixb[X][T] +
- matrixa[i][Y] * matrixb[Y][T] +
- matrixa[i][Z] * matrixb[Z][T] +
- matrixa[i][T];
- }
-
-
- /* NORMALIZE -- Normalize a vector: ap = unit vector in direction of bp.
- Returns BAD if bp is null. */
-
- int
- /*FCN*/normalize(ap, bp)
- register ads_real *ap;
- ads_real *bp;
- {
- ads_real d;
-
- if ((d = (bp[X] * bp[X] + bp[Y] * bp[Y] + bp[Z] * bp[Z]))
- <= 1.0E-12)
- return BAD;
- d = 1.0 / sqrt(d);
- ap[X] = bp[X] * d;
- ap[Y] = bp[Y] * d;
- ap[Z] = bp[Z] * d;
- return GOOD;
- }
-
-
-
- /* BILINCAL -- Calibrate the digitizer for a bilinear mapping, i.e.,
- a transformation which maps a quadrilateral on the
- tablet into a quadrilateral in model space, with edges
- mapping linearly into edges and interior points
- mapping as follows: given point P inside the
- quadrilateral on the tablet, draw a line which passes
- through P and divides the two quadrilateral edges it
- intersects in equal ratios. Draw a line between the
- two corresponding edges of the target quadrilateral
- (in model space) which divides those edges in the same
- ratio as that determined above. Repeat this
- operation, constructing a line between the other pair
- of edges of the tablet quadrilateral, and similarly
- draw a line between the corresponding edges of the
- target quadrilateral dividing them in the same ratio.
- P maps into the point at the intersection of the two
- lines thus drawn in the target quadrilateral. This is
- essentially the 2-space analogue of a Coon's patch.
-
- BILINCAL just determines the mapping by soliciting the
- calibration points. bilinmpt(), below, does the hard
- work. Note that, though there is one case in which we
- complain about degenerate calibration points, there
- are many other cases we miss entirely. This code does
- not purport to be very robust with respect to bad
- input points. */
-
- static int
- /*FCN*/bilincal()
- {
- struct resbuf tm;
- int i;
- char sb[100];
- ads_point p11, p12, p0;
-
- /* Make AutoCAD pass us raw digitizer coordinates */
-
- if (digpass() != RSRSLT) {
- ads_fail(/*MSG3*/"╡L¬k½╪Ñ▀íu╝╞ñ╞╗÷ívñº pass-through ºδ¼M (mapping)");
- return RSERR;
- }
-
- /* Turn Tablet mode on */
-
- tm.restype = RTSHORT;
- tm.resval.rint = 1;
- ads_setvar(/*MSG0*/"TABMODE", &tm);
- ads_getvar(/*MSG0*/"TABMODE", &tm);
- if (tm.resval.rint == 0) {
- ads_fail(/*MSG4*/"╡L¬k╢}▒╥íu╝╞ª∞¬Oív╝╥ªí");
- return RSERR;
- }
-
- /* Get the calibration points */
-
- ads_printf(/*MSG5*/"\n╢iªµíu4-┬I «╒Ñ┐íví╨ bilinear ºδ¼M (mapping) ...");
- for (i = 0; i < 4; i++) {
- tm.resval.rint = 1;
- ads_setvar(/*MSG0*/"TABMODE", &tm);
- sprintf(sb, /*MSG6*/"\n╝╞ñ╞ í╨ ┬I#%d: ", i + 1);
- if (ads_getpoint(NULL, sb, t[i]) != RTNORM)
- return RSERR;
- tm.resval.rint = 0;
- ads_setvar(/*MSG0*/"TABMODE", &tm); /* Turn Tablet mode off */
- sprintf(sb, /*MSG7*/"\n┐ΘñJ«y╝╨ñ⌐íu┬I #%dív: ", i + 1);
- if (ads_getpoint(NULL, sb, p[i]) != RTNORM)
- return RSERR;
- }
-
- /* Reorder the points to assure that the last two tablet points
- have different Y-coordinates (to avoid some divisions by zero
- in bilinmpt) */
-
- if (t[2][Y] == t[3][Y]) {
- if (t[1][Y] != t[3][Y]) {
- pswap(t[1],t[2]);
- pswap(p[1],p[2]);
- } else if (t[0][Y] != t[3][Y]) {
- pswap(t[0],t[2]);
- pswap(p[0],p[2]);
- } else {
- ads_fail(/*MSG8*/"íu⌐Φ¿ε▓úÑ═ív¬║«╒Ñ┐┬I");
- return RSERR;
- }
- }
-
- /* Figure out which sign to use in the solution of the quadratic
- equation inside bilinmpt, by determining which choice most
- nearly maps one of the calibration points correctly: */
-
- bilinsgn = 1;
- ibilinmpt(t[0], p11);
- bilinsgn = -1;
- ibilinmpt(t[0], p12);
- cpypoint(p0, p[0]);
- p0[Z] = p11[Z] = p12[Z] = 0.0;
- if (ads_distance(p11, p0) < ads_distance(p12, p0))
- bilinsgn = 1;
-
- tm.resval.rint = 1; /* Exit with Tablet mode ON */
- ads_setvar(/*MSG0*/"TABMODE", &tm);
-
- cbrated = TRUE;
- ads_retvoid();
- return RSRSLT;
- }
-
-
- /* BILINMPT -- External function to perform the bilinear mapping on
- a point. Expects a single ads_point as argument,
- returns an ads_point as value (if successful). */
-
- static int
- /*FCN*/bilinmpt()
- {
- struct resbuf *args;
- ads_point pprime;
-
- if (!cbrated) {
- ads_fail(/*MSG9*/"Bilinear ºδ¼M (mapping) Ñ╝«╒Ñ┐");
- return RSERR;
- }
- args = ads_getargs();
- if (args->rbnext != NULL ||
- (args->restype != RTPOINT && args->restype != RT3DPOINT)) {
- ads_fail(/*MSG10*/"ñ⌐ bilinmpt ¬║íuñ▐╝╞ívñúÑ┐╜T");
- return RSERR;
- }
-
- /* Call function to do the actual mathematics */
-
- if (ibilinmpt(args->resval.rpoint, pprime) != RSRSLT) {
- ads_fail(/*MSG11*/"bilinmpt ╡L¬k┬α╕m┬Iª∞");
- return RSERR;
- } else {
- pprime[Z] = 0.0;
- ads_retpoint(pprime);
- return RSRSLT;
- }
- }
-
-
- /* IBILINMPT -- Perform the bilinear transformation on point "inpt",
- leaving the result in "pprime" */
-
- static int
- /*FCN*/ibilinmpt(inpt, pprime)
- ads_real *inpt, *pprime;
- {
- ads_real x, y, xb, yb, xt, yt, a, b, c, r1, r2;
- ads_real x1, x2, x3, x4, y1, y2, y3, y4;
-
- x = inpt[X];
- y = inpt[Y];
-
- /* Ok, Mathematica time. Pardon the dearth of details, and the
- utter lack of simplification. */
-
- /* Put the four corners of the tablet quadrilateral in individual
- variables (this was helpful during debugging) */
-
- x1 = t[0][X];
- x2 = t[1][X];
- x3 = t[2][X];
- x4 = t[3][X];
- y1 = t[0][Y];
- y2 = t[1][Y];
- y3 = t[2][Y];
- y4 = t[3][Y];
-
- /* Compute the three coefficients in the quadratic equation whose
- solution is yt */
-
- c = x2*y*y3*y3 - x4*y*y3*y3 - x*y2*y3*y3 + x4*y2*y3*y3 - x1*y*y3*y4 -
- x2*y*y3*y4 + x3*y*y3*y4 + x4*y*y3*y4 + x*y1*y3*y4 - x4*y1*y3*y4 +
- x*y2*y3*y4 - x3*y2*y3*y4 + x1*y*y4*y4 - x3*y*y4*y4 - x*y1*y4*y4 +
- x3*y1*y4*y4;
-
- b = x1*y*y3 - x2*y*y3 - x3*y*y3 + x4*y*y3 - x*y1*y3 + x4*y1*y3 +
- x*y2*y3 + x3*y2*y3 - 2*x4*y2*y3 + x*y3*y3 - x2*y3*y3 - x1*y*y4 +
- x2*y*y4 + x3*y*y4 - x4*y*y4 + x*y1*y4 - 2*x3*y1*y4 + x4*y1*y4 -
- x*y2*y4 + x3*y2*y4 - 2*x*y3*y4 + x1*y3*y4 + x2*y3*y4 + x*y4*y4 -
- x1*y4*y4;
-
- a = x3*y1 - x4*y1 - x3*y2 + x4*y2 - x1*y3 + x2*y3 + x1*y4 -
- x2*y4;
-
- /* The quadratic equation for yt has two solutions; the choice of
- which to use is made externally by an appropriate setting of
- bilinsgn. */
-
- yt = (-b + bilinsgn * sqrt(b * b - 4.0 * a * c)) / (2.0 * a);
-
- /* Fill in xb, yb, and xt. When finished, (xb,yb) will be a point
- on the lower edge of the quadrilateral, and (xt,yt) will be a
- point on its upper edge. They will divide their respective
- edges in the same ratio, and inpt(x,y) will lie on the line
- joining them. */
-
- xb = (x2*y3 - x1*y4 + x1*yt - x2*yt) / (y3 - y4);
- yb = (y2*y3 - y1*y4 + y1*yt - y2*yt) / (y3 - y4);
- xt = (x4*y3 - x3*y4 + x3*yt - x4*yt) / (y3 - y4);
- if (x2 == x1)
- r1 = (y2 - yb) / (y2 - y1);
- else
- r1 = (x2 - xb) / (x2 - x1);
- if (xt == xb)
- r2 = (yt - y) / (yt - yb);
- else
- r2 = (xt - x) / (xt - xb);
-
- /* The r1 and r2 are the "Coon's patch" coordinates of the input
- point; transfer them to the output. */
-
- xb = r1 * p[0][X] + (1 - r1) * p[1][X];
- yb = r1 * p[0][Y] + (1 - r1) * p[1][Y];
- xt = r1 * p[2][X] + (1 - r1) * p[3][X];
- yt = r1 * p[2][Y] + (1 - r1) * p[3][Y];
- pprime[X] = r2 * xb + (1 - r2) * xt;
- pprime[Y] = r2 * yb + (1 - r2) * yt;
- return RSRSLT;
- }
-
-
-
- /* PSWAP -- Swap two 2D points */
-
- static void
- /*FCN*/pswap(p1, p2)
- ads_real *p1, *p2;
- {
- ads_real t;
-
- t = p1[X];
- p1[X] = p2[X];
- p2[X] = t;
- t = p1[Y];
- p1[Y] = p2[Y];
- p2[Y] = t;
- }
-
-
-
- /* SAMPLE -- Draw a sample figure for exercising the bilinear
- mapping. This function is not religious about
- restoring system variables to previous settings. */
-
- static int
- /*FCN*/sample()
- {
- char junk[20];
- struct resbuf svb;
- int i;
- static char *msg[] = {
- "",
- /*MSG12*/"We will now draw a sample figure which you can use to test",
- /*MSG13*/"bilinear tablet transformations. When complete, plot this",
- /*MSG14*/"figure and attach it to your tablet surface. Replace one of",
- /*MSG15*/"the items in your BUTTONS menu with the following:",
- "",
- /*MSG0*/"^P(bilinmpt (getpoint)) \\^P",
- "",
- /*MSG16*/"Then enter BILINCAL, and when you are prompted for points,",
- /*MSG17*/"digitize (with the normal pick button) the corners of the",
- /*MSG18*/"quadrilateral in this order:",
- "",
- /*MSG19*/" lower left, lower right, upper left, upper right",
- "",
- /*MSG20*/"Give them coordinates of (0,0), (16,0), (0,16), and (16,16),",
- /*MSG21*/"respectively. Then, using the button to which you attached",
- /*MSG22*/"the above menu item, digitize lines connecting the four",
- /*MSG23*/"corners of the quadrilateral. To see what this transformation",
- /*MSG24*/"does to straight lines, enter a polyline following the curved",
- /*MSG25*/"path in the figure and another polyline along the straight",
- /*MSG26*/"diagonal path.",
- "",
- NULL
- };
-
- /* Print the message */
-
- ads_textscr();
- for (i = 0; msg[i] != NULL; i++)
- ads_printf("%s\n", msg[i]);
- if (ads_getstring(0, /*MSG27*/"½÷ <Return> ┴Σ─~─≥: ", junk) != RTNORM)
- return RSERR;
-
- /* Draw the figure */
-
- ads_graphscr();
- ads_getvar(/*MSG0*/"CMDECHO", &svb);
- svb.resval.rint = 0;
- ads_setvar(/*MSG0*/"CMDECHO", &svb);
-
- ads_command(RTSTR, /*MSG0*/"ZOOM", RTSTR, /*MSG0*/"W", RTSTR, "-10,0",
- RTSTR, "1.5,12", RTNONE);
-
- dline("1.0,1.0", "-7.0,1.0");
- dline("-7.0,1.0", "-9.0,8.0");
- dline("-9.0,8.0", "-6.0,11.0");
- dline("-6.0,11.0", "1.0,1.0");
- dline("0.5,1.0", "-6.1875,10.8125");
- dline("-6.375,10.625", "0.0,1.0");
- dline("-0.5,1.0", "-6.5625,10.4375");
- dline("-6.75,10.25", "-1.0,1.0");
- dline("-1.5,1.0", "-6.9375,10.0625");
- dline("-7.125,9.875", "-2.0,1.0");
- dline("-2.5,1.0", "-7.3125,9.6875");
- dline("-7.5,9.5", "-3.0,1.0");
- dline("-3.5,1.0", "-7.6875,9.3125");
- dline("-7.875,9.125", "-4.0,1.0");
- dline("-4.5,1.0", "-8.0625,8.9375");
- dline("-8.25,8.75", "-5.0,1.0");
- dline("-5.5,1.0", "-8.4375,8.5625");
- dline("-8.625,8.375", "-6.0,1.0");
- dline("-6.5,1.0", "-8.8125,8.1875");
- dline("0.5625,1.625", "-7.125,1.4375");
- dline("-7.25,1.875", "0.125,2.25");
- dline("-0.3125,2.875", "-7.375,2.3125");
- dline("-7.5,2.75", "-0.75,3.5");
- dline("-1.1875,4.125", "-7.625,3.1875");
- dline("-7.75,3.625", "-1.625,4.75");
- dline("-2.0625,5.375", "-7.875,4.0625");
- dline("-8.0,4.5", "-2.5,6.0");
- dline("-2.9375,6.625", "-8.125,4.9375");
- dline("-8.25,5.375", "-3.375,7.25");
- dline("-3.8125,7.875", "-8.375,5.8125");
- dline("-8.5,6.25", "-4.25,8.5");
- dline("-4.6875,9.125", "-8.625,6.6875");
- dline("-8.75,7.125", "-5.125,9.75");
- dline("-5.5625,10.375", "-8.875,7.5625");
-
- ads_command(RTSTR,/*MSG0*/"PLINE", RTNONE);
- dvert("-7.0,1.0");
- dvert("-6.7636,1.2868");
- dvert("-6.6445,1.4492");
- dvert("-6.3673,1.8608");
- dvert("-6.3281,1.9219");
- dvert("-6.1843,2.1674");
- dvert("-6.0508,2.418");
- dvert("-5.926,2.6764");
- dvert("-5.8125,2.9375");
- dvert("-5.7069,3.2089");
- dvert("-5.6133,3.4805");
- dvert("-5.5271,3.7649");
- dvert("-5.4531,4.0469");
- dvert("-5.3866,4.3442");
- dvert("-5.332,4.6367");
- dvert("-5.2853,4.947");
- dvert("-5.25,5.25");
- dvert("-5.2231,5.573");
- dvert("-5.207,5.8867");
- dvert("-5.2001,6.2224");
- dvert("-5.2031,6.5469");
- dvert("-5.2163,6.8951");
- dvert("-5.2383,7.2305");
- dvert("-5.2716,7.5911");
- dvert("-5.3125,7.9375");
- dvert("-5.3659,8.3105");
- dvert("-5.4258,8.668");
- dvert("-5.4993,9.0532");
- dvert("-5.5781,9.4219");
- dvert("-5.5911,9.477");
- dvert("-5.7695,10.1992");
- dvert("-5.8442,10.4783");
- dvert("-6.0,11.0");
- ads_command(RTSTR, "", RTNONE);
-
- dline("-7.0,1.0", "-6.0,11.0"); /* Draw the "diagonal" */
-
- svb.resval.rint = 1;
- ads_setvar(/*MSG0*/"CMDECHO", &svb); /* Turn command echo back on. */
-
- ads_retvoid();
- return RSRSLT;
- }
-
-
- /* DLINE -- Draw a line. */
-
- static void
- /*FCN*/dline(p1str, p2str)
- char *p1str, *p2str;
- {
- ads_command(RTSTR, /*MSG0*/"LINE", RTSTR, p1str, RTSTR, p2str, RTSTR, "",
- RTNONE);
- }
-
- /* DVERT -- Draw one vertex of a Polyline */
-
- static void
- /*FCN*/dvert(p1str)
- char *p1str;
- {
- ads_command(RTSTR, p1str, RTNONE);
- }
-
-
- /* SAVCAL -- External function to save the current tablet calibration
- locally. */
-
- static int
- /*FCN*/savcal()
- {
- int stat;
- struct resbuf *rb;
-
- /* Free any previously saved calibration */
- if (tcal != NULL) {
- ads_relrb(tcal);
- tcal = NULL;
- }
-
- /* Build argument list to request current calibration from
- ads_tablet() */
- rb = ads_buildlist(RTSHORT, 0, RTNONE);
- stat = ads_tablet(rb, &tcal);
- ads_relrb(rb);
-
- if (stat == RTNORM)
- stat = RSRSLT;
- else {
- aperror(/*MSG0*/"ads_tablet");
- stat = RSERR;
- }
- ads_retvoid();
- return stat;
- }
-
-
- /* RSTCAL -- External function to restore a tablet calibration
- previously saved by savcal(). */
-
- static int
- /*FCN*/rstcal()
- {
- int stat = RSERR;
-
- if (tcal == NULL)
- ads_fail(/*MSG28*/"rstcal: savcal Ñ╝└xªsÑ⌠ª≤íu«╒Ñ┐ív\n");
- else if (ads_tablet(tcal, NULL) != RTNORM)
- aperror(/*MSG0*/"ads_tablet");
- else
- stat = RSRSLT;
- ads_retvoid();
- return stat;
- }
-
-
- /* APERROR -- Poor brother to ads_perr: display the value of
- errno associated with a given ADS routine. */
- static void
- /*FCN*/aperror(routine)
- char *routine;
- {
- struct resbuf gvb;
- char msgbuf[60];
-
- ads_getvar(/*MSG0*/"ERRNO", &gvb);
- if (routine == NULL)
- sprintf(msgbuf, /*MSG29*/"┐∙╗~ %d", gvb.resval.rint);
- else
- sprintf(msgbuf, /*MSG30*/"┐∙╗~ %d í╨ ╖╜ª█ %s", gvb.resval.rint, routine);
- ads_fail(msgbuf);
- }