?? spaces.c
字號:
*/ struct xobject *t1_Xform(obj, M) register struct xobject *obj; /* object to transform */ register double M[2][2]; /* transformation matrix */{ if (obj == NULL) return(NULL); if (obj->type == FONTTYPE) { register struct font *F = (struct font *) obj; F = UniqueFont(F); return((struct xobject*)F); } if (obj->type == PICTURETYPE) {/*In the case of a picture, we choose both to update the picture'stransformation matrix and keep the handles up to date.*/ register struct picture *P = (struct picture *) obj; register struct segment *handles; /* temporary path to transform handles */ P = UniquePicture(P); handles = PathSegment(LINETYPE, P->origin.x, P->origin.y); handles = Join(handles, PathSegment(LINETYPE, P->ending.x, P->ending.y) ); handles = (struct segment *)Xform((struct xobject *) handles, M); P->origin = handles->dest; P->ending = handles->link->dest; KillPath(handles); return((struct xobject *)P); } if (ISPATHTYPE(obj->type)) { struct XYspace pseudo; /* local temporary space */ PseudoSpace(&pseudo, M); return((struct xobject *) PathTransform(obj, &pseudo)); } if (obj->type == SPACETYPE) { register struct XYspace *S = (struct XYspace *) obj; /* replaced ISPERMANENT(S->flag) with S->references > 1 3-26-91 PNM */ if (S->references > 1) S = CopySpace(S); else S->ID = NEXTID; MatrixMultiply(S->tofract.normal, M, S->tofract.normal); /* * mark inverted matrix invalid: */ S->flag &= ~HASINVERSE(ON); FillOutFcns(S); return((struct xobject *) S); } return(ArgErr("Untransformable object", obj, obj));} /*:h3.Transform() - Transform an Object This is the external user's entry point.*/struct xobject *t1_Transform(obj, cxx, cyx, cxy, cyy) struct xobject *obj; double cxx,cyx,cxy,cyy; /* 2x2 transform matrix elements in row order */{ double M[2][2]; IfTrace1((MustTraceCalls),"Transform(%z,", obj); IfTrace4((MustTraceCalls)," %f %f %f %f)\n", &cxx, &cyx, &cxy, &cyy); M[0][0] = cxx; M[0][1] = cyx; M[1][0] = cxy; M[1][1] = cyy; ConsiderContext(obj, M); return(Xform(obj, M));}/*:h3.Scale() - Special Case of Transform() This is a user operator.*/ struct xobject *t1_Scale(obj, sx, sy) struct xobject *obj; /* object to scale */ double sx,sy; /* scale factors in x and y */{ double M[2][2]; IfTrace3((MustTraceCalls),"Scale(%z, %f, %f)\n", obj, &sx, &sy); M[0][0] = sx; M[1][1] = sy; M[1][0] = M[0][1] = 0.0; ConsiderContext(obj, M); return(Xform(obj, M));} /*:h3 id=rotate.Rotate() - Special Case of Transform() We special-case different settings of 'degrees' for performanceand accuracy within the DegreeSin() and DegreeCos() routines themselves.*/ #ifdef notdefstruct xobject *xiRotate(obj, degrees) struct xobject *obj; /* object to be transformed */ double degrees; /* degrees of COUNTER-clockwise rotation */{ double M[2][2]; IfTrace2((MustTraceCalls),"Rotate(%z, %f)\n", obj, °rees); M[0][0] = M[1][1] = DegreeCos(degrees); M[1][0] = - (M[0][1] = DegreeSin(degrees)); ConsiderContext(obj, M); return(Xform(obj, M));}#endif /*:h3.PseudoSpace() - Build a Coordinate Space from a Matrix Since we have built all this optimized code that, given an (x,y) anda coordinate space, yield transformed (x,y), it seems a shame not touse the same logic when we need to multiply an (x,y) by an arbitrarymatrix that is not (initially) part of a coordinate space. Thissubroutine takes the arbitrary matrix and builds a coordinatespace, with all its nifty function pointers.*/ void PseudoSpace(S, M) struct XYspace *S; /* coordinate space structure to fill out */ double M[2][2]; /* matrix that will become 'tofract.normal' */{ S->type = SPACETYPE; S->flag = ISPERMANENT(ON) + ISIMMORTAL(ON); S->references = 2; /* 3-26-91 added PNM */ S->tofract.normal[0][0] = M[0][0]; S->tofract.normal[1][0] = M[1][0]; S->tofract.normal[0][1] = M[0][1]; S->tofract.normal[1][1] = M[1][1]; FillOutFcns(S);} /*:h2 id=matrixa.Matrix Arithmetic Following the convention in Newman and Sproull, :hp1/InteractiveComputer Graphics/,matrices are organized::xmp. | cxx cyx | | cxy cyy |:exmp.A point is horizontal, for example::xmp. [ x y ]:exmp.This means that::formula/x prime = cxx times x + cxy times y/:formula/y prime = cyx times x + cyy times y/I've seen the other convention, where transform matrices aretransposed, equally often in the literature.*/ /*:h3.MatrixMultiply() - Implements Multiplication of Two Matrices Implements matrix multiplication, A * B = C. To remind myself, matrix multiplication goes rows of A times columnsof B.The output matrix may be the same as one of the input matrices.*/void MatrixMultiply(A, B, C) register double A[2][2],B[2][2]; /* input matrices */ register double C[2][2]; /* output matrix */{ register double txx,txy,tyx,tyy; txx = A[0][0] * B[0][0] + A[0][1] * B[1][0]; txy = A[1][0] * B[0][0] + A[1][1] * B[1][0]; tyx = A[0][0] * B[0][1] + A[0][1] * B[1][1]; tyy = A[1][0] * B[0][1] + A[1][1] * B[1][1]; C[0][0] = txx; C[1][0] = txy; C[0][1] = tyx; C[1][1] = tyy;}/*:h3.MatrixInvert() - Invert a Matrix My reference for matrix inversion was :hp1/Elementary Linear Algebra/by Paul C. Shields, Worth Publishers, Inc., 1968.*/void MatrixInvert(M, Mprime) double M[2][2]; /* input matrix */ double Mprime[2][2]; /* output inverted matrix */{ register double D; /* determinant of matrix M */ register double txx,txy,tyx,tyy; txx = M[0][0]; txy = M[1][0]; tyx = M[0][1]; tyy = M[1][1]; D = M[1][1] * M[0][0] - M[1][0] * M[0][1]; if (D == 0.0) abort("MatrixInvert: can't"); Mprime[0][0] = tyy / D; Mprime[1][0] = -txy / D; Mprime[0][1] = -tyx / D; Mprime[1][1] = txx / D;}/*:h2.Initialization, Queries, and Debug*//*:h3.InitSpaces() - Initialize Constant Spaces For compatibility, we initialize a coordinate space called USER whichmaps 72nds of an inch to pels on the default device.*/ struct XYspace *USER = &identity; void InitSpaces(){ extern char *DEFAULTDEVICE; IDENTITY->type = SPACETYPE; FillOutFcns(IDENTITY); contexts[NULLCONTEXT].normal[1][0] = contexts[NULLCONTEXT].normal[0][1] = contexts[NULLCONTEXT].inverse[1][0] = contexts[NULLCONTEXT].inverse[0][1] = 0.0; contexts[NULLCONTEXT].normal[0][0] = contexts[NULLCONTEXT].normal[1][1] = contexts[NULLCONTEXT].inverse[0][0] = contexts[NULLCONTEXT].inverse[1][1] = 1.0; USER->flag |= ISIMMORTAL(ON); CoerceInverse(USER);}/*:h3.QuerySpace() - Returns the Transformation Matrix of a Space Since the tofract matrix of an XYspace includes the scale factornecessary to produce fractpel results (i.e., FRACTFLOAT), thismust be taken out before we return the matrix to the user. Fortunately,this is simple: just multiply by the inverse of IDENTITY!*/ void QuerySpace(S, cxxP, cyxP, cxyP, cyyP) register struct XYspace *S; /* space asked about */ register double *cxxP,*cyxP,*cxyP,*cyyP; /* where to put answer */{ double M[2][2]; /* temp matrix to build user's answer */ if (S->type != SPACETYPE) { ArgErr("QuerySpace: not a space", S, NULL); return; } MatrixMultiply(S->tofract.normal, IDENTITY->tofract.inverse, M); *cxxP = M[0][0]; *cxyP = M[1][0]; *cyxP = M[0][1]; *cyyP = M[1][1];} /*:h3.FormatFP() - Format a Fixed Point Pel We format the pel as "dddd.XXXX", where XX's are hexidecimal digits,and the dd's are decimal digits. This might be a little confusingmixing hexidecimal and decimal like that, but it is convenientto use for debug. We make sure we have N (FRACTBITS/4) digits past the decimal point.*/#define FRACTMASK ((1<<FRACTBITS)-1) /* mask for fractional part */ void FormatFP(string, fpel) register char *string; /* output string */ register fractpel fpel; /* fractional pel input */{ char temp[8]; register char *s; register char *sign; if (fpel < 0) { sign = "-"; fpel = -fpel; } else sign = ""; sprintf(temp, "000%x", fpel & FRACTMASK); s = temp + strlen(temp) - (FRACTBITS/4); sprintf(string, "%s%d.%sx", sign, fpel >> FRACTBITS, s);} /*:h3.DumpSpace() - Display a Coordinate Space*//*ARGSUSED*/void DumpSpace(S) register struct XYspace *S;{ IfTrace4(TRUE,"--Coordinate space at %x,ID=%d,convert=%x,iconvert=%x\n", S, S->ID, S->convert, S->iconvert); IfTrace2(TRUE," | %12.3f %12.3f |", &S->tofract.normal[0][0], &S->tofract.normal[0][1]); IfTrace2(TRUE," [ %p %p ]\n", S->itofract[0][0], S->itofract[0][1]); IfTrace2(TRUE," | %12.3f %12.3f |", &S->tofract.normal[1][0], &S->tofract.normal[1][1]); IfTrace2(TRUE," [ %p %p ]\n", S->itofract[1][0], S->itofract[1][1]);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -