! Routines for the EDWIN transformation stack. %record %format POINTFM (%integer X, Y) %include "Inc:maths.imp" %include "edwin:txstack.inc" { as consistancy check } %own %record (TRANS FM) %array T STACK (0:TRANSFORM STACK DEPTH) %own %record (TRANS FM) %name CUR, OLD %own %real %array UNITY (0:8) = 1, 0, 0, 0, 1, 0, 0, 0, 1 %own %real %array MX (0:8) = -1, 0, 0, 0, 1, 0, 0, 0, 1 %own %real %array MY (0:8) = 1, 0, 0, 0, -1, 0, 0, 0, 1 %own %integer STACK PTR = -1 %external %routine UNITY TRANSFORM %alias "EDWIN_UNITY_TX" (%record (TRANSFM) %name T) T = record(addr(UNITY(0))) %end %external %routine TRANSLATE TRANSFORM %alias "EDWIN_TRANSLATE_TX" (%real X, Y, %record (TRANSFM) %name T) T = record(addr(UNITY(0))) T_A(6) = X T_A(7) = Y %end %external %routine MIRROR X TRANSFORM %alias "EDWIN_MIRROR_X_TX" (%record (TRANSFM) %name T) T = record(addr(MX(0))) %end %external %routine MIRROR Y TRANSFORM %alias "EDWIN_MIRROR_Y_TX" (%record (TRANSFM) %name T) T = record(addr(MY(0))) %end %external %routine ROT DV TRANSFORM %alias "EDWIN_ROT_DV_TX" (%real A, B, %record (TRANSFM) %name T) %long %real SQRT AA BB %real DIR AC, DIR BC T = record(addr(UNITY(0))) %return %if A = 0 %and B = 0 SQRT AA BB = SQRT (A*A + B*B) DIR AC = A/SQRT AA BB DIR BC = B/SQRT AA BB T_A(0) = DIR AC T_A(4) = DIR AC T_A(1) = DIR BC T_A(3) = -DIR BC %end %external %routine ROT ANG TRANSFORM %alias "EDWIN_ROT_ANG_TX" (%real ANG, %record (TRANSFM) %name T) %real SA, CA T = record(addr(UNITY(0))) ANG = ANG / DtoR SA = SIN (ANG) CA = COS (ANG) T_A(0) = CA T_A(1) = SA T_A(3) = -SA T_A(4) = CA %end %external %routine SCALE TRANSFORM %alias "EDWIN_SCALE_TX" (%real XS, YS, %record (TRANSFM) %name T) T = record(addr(UNITY(0))) T_A(0) = XS T_A(4) = YS %end %external %routine COMPOSE TRANSFORM %alias "EDWIN_COMPOSE_TX" (%record (TRANSFM) %name TA, TB, TC) ! Performs the matrix multiplication C = A*B on the arrays in parameters. %real %array %name A, B, C (0:8) %integer I, J, K %real %name R A == TA_A; B == TB_A; C == TC_A %for I = 0,3,6 %cycle %for J = 0,1,2 %cycle R == C(I+J); R = 0 %for K = 0, 1, 2 %cycle R = R + A(I+K) * B(K*3+J) %repeat %repeat %repeat %end %external %routine POP TRANSFORM %alias "EDWIN_POP_TX" %signal 14, 9 %if STACK PTR < 0; ! Stack not initialised. STACK PTR = STACK PTR - 1 %signal 14, 11 %if STACK PTR<0 CUR == OLD OLD == TSTACK(STACK PTR-1) %if STACK PTR>0 %end %external %routine INIT TRANSFORM %alias "EDWIN_INIT_TX" ! Initialise the transformation stack. STACK PTR = 0 CUR == T STACK (0) CUR = record(addr(UNITY(0))) %end %external %routine SET TRANSFORM %alias "EDWIN_SET_TX" (%record (TRANSFM) %name T) INIT TRANSFORM %if STACK PTR < 0 OLD == CUR STACK PTR = STACK PTR + 1 %signal 14, 10 %if STACK PTR > TRANSFORM STACK DEPTH CUR == T STACK(STACK PTR) CUR = T %end %external %routine PUSH TRANSFORM %alias "EDWIN_PUSH_TX" (%record (TRANSFM) %name T) INIT TRANSFORM %if STACK PTR < 0 OLD == CUR STACK PTR = STACK PTR + 1 %signal 14, 10 %if STACK PTR > TRANSFORM STACK DEPTH CUR == T STACK(STACK PTR) COMPOSE TRANSFORM (T, OLD, CUR); ! CUR = T * OLD gives new transformation to be done. %end %external %routine POINT TRANSFORM %alias "EDWIN_POINT_TX" (%record (POINTFM) %name P, NP) ! Transforms a point P to NP under the current transformation. NP_X = INT(P_X*CUR_A(0) + P_Y*CUR_A(3) + CUR_A(6)) NP_Y = INT(P_X*CUR_A(1) + P_Y*CUR_A(4) + CUR_A(7)) %end %external %routine VECTOR TRANSFORM %alias "EDWIN_VECTOR_TX" (%record (POINTFM) %name V, NV) ! Transforms a vector V to NV under the current transformation. NV_X = INT(V_X*CUR_A(0) + V_Y*CUR_A(3)) NV_Y = INT(V_X*CUR_A(1) + V_Y*CUR_A(4)) %end %external %routine BB TRANSFORM %alias "EDWIN_BB_TX" (%record (POINTFM) %name OPL, OPU, NPL, NPU) ! Transforms a bounding box to a new paraxial bounding box %integer SWAP %record (POINTFM) UL, LR %integer %function MAX (%integer A, B) %result = A %if A > B %result = B %end %integer %function MIN (%integer A, B) %result = A %if A < B %result = B %end POINT TRANSFORM (OPL, NPL) POINT TRANSFORM (OPU, NPU) SWAP = OPL_Y OPL_Y = OPU_Y OPU_Y = SWAP POINT TRANSFORM(OPL, UL) POINT TRANSFORM(OPU, LR) SWAP = OPL_Y OPL_Y = OPU_Y OPU_Y = SWAP NPU_X = MAX ( MAX(NPU_X,NPL_X) , MAX(UL_X,LR_X) ) ;! Get max X from 4 corners NPL_X = MIN ( MIN(NPU_X,NPL_X) , MIN(UL_X,LR_X) ) ;! Get min X from 4 corners NPU_Y = MAX ( MAX(NPU_Y,NPL_Y) , MAX(UL_Y,LR_Y) ) ;! Get max Y from 4 corners NPL_Y = MIN ( MIN(NPU_Y,NPL_Y) , MIN(UL_Y,LR_Y) ) ;! Get min Y from 4 corners %end %external %routine GET TRANSFORM %alias "EDWIN_GET_TX" (%record (TRANSFM) %name TX) TX = CUR %end %external %routine PRINT TRANSFORM %alias "EDWIN_PRINT_TX" (%record (TRANSFM) %name T) ! PRINT TRANS is only required if debugging. %integer I %for I = 0, 1, 8 %cycle PRINT (T_A(I), 3, 1) NEWLINE %if I=2 %or I=5 %or I=8 %repeat %end %end %of %file