Annotation of researchv10no/cmd/picasso/xform.c, revision 1.1.1.1

1.1       root        1: /*     Copyright (c) 1988 AT&T */
                      2: /*       All Rights Reserved   */
                      3: 
                      4: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
                      5: /*     The copyright notice above does not evidence any        */
                      6: /*     actual or intended publication of such source code.     */
                      7: 
                      8: /*     @(#)picasso:xform.c     1.0     */
                      9: 
                     10: #include       "picasso.h"
                     11: #include       "y.tab.h"
                     12: #include    <math.h>
                     13: 
                     14: /* shorthand for a 3x3 affine matrix applied as follows:
                     15:  *
                     16:  *     C(x, y) = |x y 1| | C[0]  C[1]  0 | 
                     17:  *                       | C[2]  C[3]  0 |
                     18:  *                       | C[4]  C[5]  1 |
                     19:  *
                     20:  *             = (C[0]x+C[2]y+C[4], C[1]x+C[3]y+C[5])
                     21:  */
                     22: 
                     23: matmult (A, B)                 /* A <- A * B; A is an object transformation */
                     24:        valtype A[6];           /* or cur_xform updated by a new transform.  */
                     25:        double  B[6];
                     26: {
                     27:        register double p;
                     28: 
                     29:        p = A[0].f * B[0] + A[1].f * B[2];
                     30:        A[1].f = A[0].f * B[1] + A[1].f * B[3];
                     31:        A[0].f = p;
                     32: 
                     33:        p = A[2].f * B[0] + A[3].f * B[2];
                     34:        A[3].f = A[2].f * B[1] + A[3].f * B[3];
                     35:        A[2].f = p;
                     36: 
                     37:        p = A[4].f * B[0] + A[5].f * B[2] + B[4];
                     38:        A[5].f = A[4].f * B[1] + A[5].f * B[3] + B[5];
                     39:        A[4].f = p;
                     40: }
                     41: 
                     42: matmult2 (A, B)                        /* same, but updates a double array; this is  */
                     43:        double  A[6];           /* done only in going up the block hierarchy. */
                     44:        valtype B[6];
                     45: {
                     46:        register double p;
                     47: 
                     48:        p = A[0] * B[0].f + A[1] * B[2].f;
                     49:        A[1] = A[0] * B[1].f + A[1] * B[3].f;
                     50:        A[0] = p;
                     51: 
                     52:        p = A[2] * B[0].f + A[3] * B[2].f;
                     53:        A[3] = A[2] * B[1].f + A[3] * B[3].f;
                     54:        A[2] = p;
                     55: 
                     56:        p = A[4] * B[0].f + A[5] * B[2].f + B[4].f;
                     57:        A[5] = A[4] * B[1].f + A[5] * B[3].f + B[5].f;
                     58:        A[4] = p;
                     59: }
                     60: 
                     61: mat_inverse(Ainv, A)
                     62:        double Ainv[6];
                     63:        float  A[6];
                     64: {
                     65:        double  det, det_1;
                     66: 
                     67:        det = A[0] * A[3] - A[1] * A[2];
                     68:        if (det == 0.0) {
                     69:                Ainv[0] = Ainv[3] = 1.0;
                     70:                Ainv[1] = Ainv[2] = 0.0;
                     71:                Ainv[4] = Ainv[5] = 0.0;
                     72:                return;
                     73:        }
                     74:        det_1 = 1.0 / det;
                     75:        Ainv[0] = A[3] * det_1;
                     76:        Ainv[1] = - A[1] * det_1;
                     77:        Ainv[2] = - A[2] * det_1;
                     78:        Ainv[3] = A[0] * det_1;
                     79:        Ainv[4] = (A[2] * A[5] - A[3] * A[4]) * det_1;
                     80:        Ainv[5] = (A[1] * A[4] - A[0] * A[5]) * det_1;
                     81: }
                     82: 
                     83: double T[6];
                     84: 
                     85: compose (p)                    /* accumulate xforms over block hierarchy */
                     86:        obj     *p;
                     87: {
                     88:        if (p == NULL || p->o_type > TEXT) {
                     89:                T[0] = T[3] = 1;
                     90:                T[1] = T[2] =
                     91:                T[4] = T[5] = 0;
                     92:                if (p == NULL)
                     93:                        return;
                     94:        }
                     95:        else {
                     96:                T[0] = p->o_mxx;        T[1] = p->o_myx;
                     97:                T[2] = p->o_mxy;        T[3] = p->o_myy;
                     98:                T[4] = p->o_mxt;        T[5] = p->o_myt;
                     99:        }
                    100:        while ((p = p->o_parent) != NULL)
                    101:                if (p->o_type <= TEXT)
                    102:                        if (p->o_mxx != 1 || p->o_mxy != 0 || p->o_mxt != 0
                    103:                        ||  p->o_myx != 0 || p->o_myy != 1 || p->o_myt != 0)
                    104:                                matmult2(T, p->o_xform);
                    105: }
                    106: 
                    107: get_matrix(M0, M1, M2, M3)
                    108:        double  *M0, *M1, *M2, *M3;
                    109: {
                    110:        *M0 = T[0];     *M1 = T[1];     *M2 = T[2];     *M3 = T[3];
                    111: }
                    112: 
                    113: double Xformx (p, flag, x, y)
                    114:        obj     *p;
                    115:        int     flag;
                    116:        double  x, y;
                    117: {
                    118:        if (flag)
                    119:                compose(p);
                    120:        return x*T[0] + y*T[2] + T[4];
                    121: }
                    122: 
                    123: double Xformy (p, flag, x, y)
                    124:        obj     *p;
                    125:        int     flag;
                    126:        double  x, y;
                    127: {
                    128:        if (flag)
                    129:                compose(p);
                    130:        return x*T[1] + y*T[3] + T[5];
                    131: }
                    132: 
                    133: double Linx (p, flag, x, y)            /* linear component, only */
                    134:        obj     *p;
                    135:        int     flag;
                    136:        double  x, y;
                    137: {
                    138:        if (flag)
                    139:                compose(p);
                    140:        return T[0]*x + T[2]*y;
                    141: }
                    142: 
                    143: double Liny (p, flag, x, y)
                    144:        obj     *p;
                    145:        int     flag;
                    146:        double  x, y;
                    147: {
                    148:        if (flag)
                    149:                compose(p);
                    150:        return T[1]*x + T[3]*y;
                    151: }
                    152: 
                    153: apply (p, M, d)                        /* apply matrix M (determinant d) to object p */
                    154:        obj     *p;
                    155:        double  *M, d;
                    156: {
                    157:        float   bnd[4];
                    158: 
                    159:        if (p->o_type == PLACE) {
                    160:                matmult (cur_xform, M);
                    161:                if (d != 1)
                    162:                        checkscale(sqrt(d));
                    163:        }
                    164:        else if (p->o_type <= TEXT) {
                    165:                matmult (p->o_xform, M);
                    166:                get_bounds(p, bnd, 0);
                    167:                track_bounds(bnd[0], bnd[1], bnd[2], bnd[3]);
                    168:                redo_gbox = 1;
                    169:        }
                    170: }
                    171: 
                    172: translate (p, x, y)           /* the easy case of applying a transformation */
                    173:        obj     *p;
                    174:        double  x, y;
                    175: {
                    176:        float   bnd[4];
                    177:        int     i;
                    178: 
                    179:        if (p->o_type == PLACE) {
                    180:                cur_xform[4].f += x;
                    181:                cur_xform[5].f += y;
                    182:        }
                    183:        else if (p->o_type <= TEXT) {
                    184:                if (p->o_type == BLOCK  || p->o_mxx != 1 || p->o_myy != 1
                    185:                                        || p->o_mxy != 0 || p->o_myx != 0
                    186:                                        || p->o_mxt != 0 || p->o_myt != 0) {
                    187:                        p->o_mxt += x;
                    188:                        p->o_myt += y;
                    189:                }
                    190:                else {  /* no existing transformation, move center */
                    191:                        /* DBK: probably should also test to make sure
                    192:                           there is no higher level transformation?? */
                    193:                        p->o_x += x;
                    194:                        p->o_y += y;
                    195:                        switch (p->o_type) {
                    196: 
                    197:                        case LINE:
                    198:                        case ARROW:
                    199:                        case SPLINE:
                    200:                                for (i = 0; i <= p->o_val[N_VAL+3].f; i++) {
                    201:                                        p->o_val[N_VAL+4+i+i].f += x;
                    202:                                        p->o_val[N_VAL+5+i+i].f += y;
                    203:                                }
                    204:                                break;
                    205:                        case ARC:
                    206:                        case SECTOR:
                    207:                                p->o_val[N_VAL+2].f += x;
                    208:                                p->o_val[N_VAL+3].f += y;
                    209:                                p->o_val[N_VAL+4].f += x;
                    210:                                p->o_val[N_VAL+5].f += y;
                    211:                                break;
                    212:                        }
                    213:                }
                    214:                get_bounds(p, bnd, 0);
                    215:                track_bounds(bnd[0], bnd[1], bnd[2], bnd[3]);
                    216:                redo_gbox = 1;
                    217:        }
                    218: }
                    219: 
                    220: xlate (p, q)
                    221:        obj     *p, *q;
                    222: {
                    223:        translate (p, q->o_x, q->o_y);
                    224: }
                    225: 
                    226: xlate_to (p, q)                        /* destination given in absolute coordinates */
                    227:        obj     *p, *q;
                    228: {
                    229:        translate (p, q->o_x - p->o_x, q->o_y - p->o_y);
                    230: }
                    231: 
                    232: static double  picscale = 1.0;
                    233: 
                    234: rescale (v)            /* implicit scaling from user's "scale = v" statement */
                    235:        double  v;      /* rather unintuitively, this is like "scale O 1/v".  */
                    236: {
                    237:        picscale = v;
                    238: }
                    239: 
                    240: scale_pic()            /* for PIC compatibility--called at end of parse */
                    241: {
                    242:        double  sc;
                    243:        obj     *o;
                    244:        int     i;
                    245:        float   bnd[4];
                    246: 
                    247:        if (picscale == 0.0)
                    248:                picscale = 1.0;
                    249:        if (picscale == 1.0)
                    250:                return;
                    251:        sc = 1.0 / picscale;
                    252:        
                    253:        for (o = objhead; o != objtail; o = o->o_next) {
                    254:                if (o->o_type == PLACE || o->o_type == TEXT ||
                    255:                                                o->o_type == MOVE) {
                    256:                        o->o_x *= sc;
                    257:                        o->o_y *= sc;
                    258:        /* NOTE!! may need to adjust center offset of text */
                    259:                }
                    260:                else if (o->o_type < TEXT) {    /* PIC couldn't scale text */
                    261:                        for (i = 0; i < 6; i++)
                    262:                                o->o_xform[i].f *= sc;
                    263:                }
                    264:                if (o->o_type == BLOCK)         /* skip the contents */
                    265:                        o = o->o_val[N_VAL].o;
                    266:        }
                    267:        /* make arrowheads large to compensate for later shrinkage */
                    268:        for (o = objhead; o != objtail; o = o->o_next) {
                    269:                if ((o->o_type == LINE || o->o_type == SPLINE ||
                    270:                    o->o_type == ARROW) && (o->o_attr & HEAD12) != 0) {
                    271:                        o->o_val[N_VAL+1].f *= picscale;
                    272:                        o->o_val[N_VAL+2].f *= picscale;
                    273:                }
                    274:                if (o->o_type == ARC && (o->o_attr & HEAD12) != 0) {
                    275:                        o->o_val[N_VAL+8].f *= picscale;
                    276:                        o->o_val[N_VAL+9].f *= picscale;
                    277:                }
                    278:        }
                    279:        picscale = 1.0;
                    280: 
                    281:        Gbox[2] = Gbox[3] = -(Gbox[0] = Gbox[1] = 32767);
                    282:        for (o = objhead->o_next; o != objtail; o = o->o_next) {
                    283:                get_bounds(o, bnd, 1);
                    284:                track_bounds (bnd[0], bnd[1], bnd[2], bnd[3]);
                    285:                if (o->o_type == BLOCK)
                    286:                        o = o->o_val[N_VAL].o;
                    287:        }
                    288: #if 0
                    289:        cur_xform[0].f /= v;
                    290:        cur_xform[1].f /= v;
                    291:        cur_xform[2].f /= v;
                    292:        cur_xform[3].f /= v;
                    293:        checkscale(v);
                    294: #endif
                    295: }
                    296: 
                    297: scale (p, n, q)
                    298:        obj     *p, *q;
                    299:        int     n;
                    300: {
                    301: register double        det;
                    302:        double  M[6];
                    303: 
                    304:        M[0] = exprlist[nexpr-n];
                    305:        M[3] = (n == 1 ? M[0] : exprlist[nexpr-n+1]);
                    306:        nexpr = 0;
                    307:        if ((det = M[0] * M[3]) == 0.0) {
                    308:                yyerror("can't scale by 0 factor");
                    309:                return;
                    310:        }
                    311:        M[1] = M[2] = M[4] = M[5] = 0.;
                    312:        if (q != NULL) {
                    313:                M[4] = (1 - M[0]) * Xformx(q,1,q->o_x,q->o_y);
                    314:                M[5] = (1 - M[3]) * Xformy(q,0,q->o_x,q->o_y);
                    315:        }
                    316:        apply(p, M, det);
                    317: }
                    318: 
                    319: olpscaleobj (p, sx, sy, cx, cy)
                    320:        obj     *p;
                    321:         double sx, sy;    /* scale factor in x and y directions */
                    322:         double cx, cy;    /* center for scaling in real (inches) units */
                    323: {
                    324: register double        det;
                    325:                 double M[6];
                    326: 
                    327:        M[0] = sx;
                    328:        M[3] = sy;
                    329:        if ((det = M[0] * M[3]) == 0.0) {
                    330:                yyerror("can't scale by 0 factor");
                    331:                return;
                    332:        }
                    333:        M[1] = M[2] = 0.0;
                    334:         M[4] = cx * (1. - sx);
                    335:         M[5] = cy * (1. - sy);
                    336:         
                    337:        apply(p, M, det);
                    338: }
                    339: 
                    340: rotate (p, phi, q)
                    341:        obj     *p, *q;
                    342:        double  phi;    /* in radians */
                    343: {
                    344: register double        x, y;
                    345:        double  M[6];
                    346: 
                    347:        M[3] =   M[0] = Cos(phi);
                    348:        M[2] = -(M[1] = Sin(phi));
                    349:        if (q == NULL)
                    350:                M[4] = M[5] = 0;
                    351:        else {
                    352:                x = Xformx(q, 1, q->o_x, q->o_y);
                    353:                y = Xformy(q, 0, q->o_x, q->o_y);
                    354:                M[4] = (1 - M[0]) * x + M[1] * y;
                    355:                M[5] = (1 - M[0]) * y - M[1] * x;
                    356:        }
                    357:        apply(p, M, 1);
                    358: }
                    359: 
                    360: void 
                    361: rotate_point(x, y,  angle, cx, cy, pointx, pointy)
                    362:         double  x, y;
                    363:        double  angle;  /* in radians */
                    364:         double  cx, cy; /* center for rotation in screen units. */
                    365:         double *pointx, *pointy;    /* rotated point to be passed back */
                    366: {
                    367:        double tempx, tempy;
                    368: 
                    369:         tempx = x - cx;
                    370:         tempy = y - cy;
                    371: 
                    372:         *pointx = (tempx * cos(angle)) - (tempy* sin(angle)) + cx;
                    373:         *pointy = (tempx * sin(angle)) + (tempy* cos(angle)) + cy;
                    374: }
                    375: 
                    376: void
                    377: olprotateobj (p, angle, cx, cy)
                    378:        obj     *p;
                    379:        double  angle;  /* in radians */
                    380:         double  cx, cy; /* center for rotation in real (inches) units. */
                    381: {
                    382:        double  M[6];
                    383: 
                    384:        M[3] =   M[0] = cos(angle);
                    385:        M[2] = -(M[1] = sin(angle));
                    386: 
                    387: 
                    388:        M[4] = (1 - M[0]) * cx + M[1] * cy;
                    389:        M[5] = (1 - M[0]) * cy - M[1] * cx;
                    390: 
                    391:        apply(p, M, 1);
                    392: }
                    393: 
                    394: xform (p, n)
                    395:        obj     *p;
                    396:        int     n;
                    397: {
                    398: register double        det;
                    399:        double  M[6];
                    400:        int     i;
                    401: 
                    402:        for (i = 0; i < n; ++i)
                    403:                M[i] = exprlist[i];
                    404:        while (i < 6)
                    405:                M[i++] = 0;
                    406:        nexpr = 0;
                    407:        if ((det = M[0]*M[3] - M[1]*M[2]) == 0)
                    408:                yyerror ("singular transformation matrix");
                    409:        else 
                    410:                apply(p, M, det);
                    411: }
                    412: 
                    413: reflect (p, q)
                    414:        obj     *p, *q;
                    415: {
                    416:        float   bnd[4];
                    417:        double  phi, c, s, x0, y0, x1, y1, M[6];
                    418:        int     axial;
                    419: 
                    420:        if (q == NULL)
                    421:                axial = x0 = x0 = x1 = y1 = 0;
                    422:        else
                    423:                switch (q->o_type) {
                    424:                case ARC:
                    425:                case ARROW:
                    426:                case LINE:
                    427:                case SPLINE:    whatpos(q, START, bnd, bnd+1);
                    428:                                whatpos(q, END,   bnd+2, bnd+3);
                    429:                                x0 = Xformx(q, 1, bnd[0], bnd[1]);
                    430:                                y0 = Xformy(q, 0, bnd[0], bnd[1]);
                    431:                                x1 = Xformx(q, 0, bnd[2], bnd[3]);
                    432:                                y1 = Xformy(q, 0, bnd[2], bnd[3]);
                    433:                                if (axial = (x0 != x1 || y0 != y1))
                    434:                                        break;
                    435:                                /* fall through to default case; i.e., use  */
                    436:                                /* center, for closed lines. otherwise, use */
                    437:                                /* closest point to p along q as start of q */
                    438: #if 0      /*MS: The next few lines never get used */                                 
                    439:                                S = (y1-y0)/(x1-x0);    /* slope of the line  */
                    440:                                B = y0 - S*x0;          /* intercept term.    */
                    441:                                s = -1/S;               /* perpendicular slope*/
                    442:                                x = Xformx(p, 1, p->o_x, p->o_y);
                    443:                                y = Xformy(p, 0, p->o_x, p->o_y);
                    444:                                b = y - s*x;
                    445:                                x0 = (b - B)/(S - s);   y0 = S*x0 + B;
                    446: #endif                                
                    447: 
                    448:                default:
                    449:                                x0 = Xformx(q, 1, q->o_x, q->o_y);
                    450:                                y0 = Xformy(q, 0, q->o_x, q->o_y);
                    451:                                axial = 0;
                    452:                }
                    453:        if (!axial) {
                    454:                M[0] = M[3] = -1;
                    455:                M[1] = M[2] = 0;
                    456:                M[4] = 2 * x0;
                    457:                M[5] = 2 * y0;
                    458:        }
                    459:        else {
                    460:                if (x1 == x0 || y1 == y0) {     /* note: not both */
                    461:                        s = 0;
                    462:                        c = (x1 == x0 ? -1 : 1);
                    463:                }
                    464:                else if (fabs(x1-x0) == fabs(y1-y0)) {
                    465:                        c = 0;
                    466:                        s = (x1-x0 == y1-y0 ? 1 : -1);
                    467:                }
                    468:                else {
                    469:                        c = cos(phi = 2 * atan2(y1-y0, x1-x0));
                    470:                        s = sin(phi);
                    471:                }
                    472:                M[1] = M[2] = s;
                    473:                M[3] = -(M[0] = c);
                    474:                M[4] = x0*(1-c) - y0*s;
                    475:                M[5] = y0*(1+c) - x0*s;
                    476:        }
                    477:        apply(p, M, 1);
                    478: }
                    479: 
                    480: olpreflectobj (p, x0, y0, x1, y1)
                    481:        obj     *p;
                    482:         double  x0, y0, x1, y1;
                    483: {
                    484:        double  phi, c, s, M[6];
                    485:        int     axial;
                    486: 
                    487:         if  (x0 != x1 || y0 != y1)
                    488:            axial = 1;
                    489:         else    axial = 0;
                    490: 
                    491:        if (!axial) {
                    492:                M[0] = M[3] = -1;
                    493:                M[1] = M[2] = 0;
                    494:                M[4] = 2 * x0;
                    495:                M[5] = 2 * y0;
                    496:        }
                    497:        else {
                    498:                if (x1 == x0 || y1 == y0) {     /* note: not both */
                    499:                        s = 0;
                    500:                        c = (x1 == x0 ? -1 : 1);
                    501:                }
                    502:                else if (fabs(x1-x0) == fabs(y1-y0)) {
                    503:                        c = 0;
                    504:                        s = (x1-x0 == y1-y0 ? 1 : -1);
                    505:                }
                    506:                else {
                    507:                        c = cos(phi = 2 * atan2(y1-y0, x1-x0));
                    508:                        s = sin(phi);
                    509:                }
                    510:                M[1] = M[2] = s;
                    511:                M[3] = -(M[0] = c);
                    512:                M[4] = x0*(1-c) - y0*s;
                    513:                M[5] = y0*(1+c) - x0*s;
                    514:        }
                    515:        apply(p, M, 1);
                    516: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.