pr2d-main.red 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. % %
  3. % PictureRLISP : A Lisp-Based Graphics Language System with %
  4. % Flexible Syntax and Hierarchical %
  5. % Data Structure %
  6. % 2D version................
  7. %
  8. % Author: Fuh-Meei Chen, Paul Stay and Martin L. Griss %
  9. % Symbolic Computation Group %
  10. % Computer Science Dept. %
  11. % University of Utah %
  12. % %
  13. % <PSL.UTIL>PRLISP.RED.21, 9-Jan-82 22:47:43, Edit by GRISS %
  14. % <STAY.PICT>PRLISP.B 12-april-82 8:00:00 by Paul Stay %
  15. % changed bezier circle and bspline drivers and hp terminal %
  16. % on 10-april-82 by Paul Stay %
  17. % Added MPS support software for use on the graphics vax %
  18. % Added ST.INIT %
  19. % Copyright (c) 1981 University of Utah %
  20. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  21. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  22. % Part of the parser to accomplish the Pratt parser written %
  23. % in New-Rlisp runs at DEC-20. %
  24. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  25. RemFlag('(MKVECT),'TWOREG); %/ Seems in Error
  26. RemProp('!{,'NEWNAM!-OP); %. left and right brackets
  27. RemProp('!},'NEWNAM!-OP); %. handling.
  28. RemProp('!{,'NEWNAM); % left and right brackets are
  29. RemProp('!},'NEWNAM); % used to Define points.
  30. Put('!{, 'NEWNAM,'!*LBRAC!*);
  31. Put('!}, 'NEWNAM,'!*RBRAC!*); % Put on to the property list.
  32. DefineROP('!*LBRAC!*,NIL,LBC); % Define the precedence.
  33. DefineBOP('!*RBRAC!*,1,0);
  34. FLUID '(OP);
  35. Procedure LBC X;
  36. Begin scalar RES;
  37. If X EQ '!*RBRAC!* then
  38. <<OP := X; RES := '!*EMPTY!*>>
  39. else RES:= RDRIGHT(2,X);
  40. If OP EQ '!*RBRAC!* then
  41. OP := SCAN()
  42. else PARERR("Missing } after argument list",NIL);
  43. Return REPCOM('OnePoint,RES)
  44. end;
  45. Procedure REPCOM(TYPE,X); %. Create ARGLIST
  46. IF EQCAR(X,'!*COMMA!*) THEN (TYPE . CDR X)
  47. ELSE IF X EQ '!*EMPTY!* THEN LIST(TYPE)
  48. ELSE LIST(TYPE,X);
  49. RemProp('!_,'NEWNAM); %. underscore handling.
  50. Put('!_,'NEWNAM,'POINTSET); % "_" is used for Pointset.
  51. DefineBOP('POINTSET,17,18,NARY('POINTSET,X,Y));
  52. Put('!&,'NEWNAM,'GROUP); %. and sign handling.
  53. DefineBOP('GROUP,13,14,NARY('GROUP,X,Y)); % "&" is used for Group.
  54. Put('!|,'NEWNAM,'TRANSFORM); %. back slash handling.
  55. DefineROP('TRANSFORM,20, % "|" is used for transform.
  56. If EQCAR(X,'!*COMMA!*) then
  57. REPCOM('TRANSFORM,X));
  58. DefineBOP('TRANSFORM,15,16);
  59. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  60. % conversion of external Procedures to %
  61. % internal form. %
  62. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  63. % **************************************
  64. % conversion on structures of models. *
  65. % **************************************
  66. NExpr Procedure POINTSET L$
  67. 'POINTSET . L$
  68. NExpr Procedure GROUP L$
  69. 'GROUP . L$
  70. NExpr Procedure TRANSFORM L$
  71. 'TRANSFORM . L$
  72. % ***********************************
  73. % conversion on interpreter level *
  74. % Procedures. *
  75. % ***********************************
  76. Procedure BSPLINE;
  77. LIST 'BSPLINE;
  78. Procedure BEZIER;
  79. LIST 'BEZIER;
  80. Procedure LINE;
  81. LIST 'LINE;
  82. Procedure CIRCLE(R);
  83. LIST('CIRCLE,R);
  84. Procedure COLOR N;
  85. List('Color,N);
  86. Procedure REPEATED(COUNT,TRANS);
  87. LIST('REPEATED,COUNT,TRANS);
  88. BothTimes <<Procedure MKLIST L$
  89. 'LIST . L; >>;
  90. MACRO Procedure OnePoint L$
  91. LIST('MKPOINT, MKLIST CDR L)$
  92. MACRO Procedure Mat8 L;
  93. LIST('LIST2VECTOR, MKLIST (CDR L))$
  94. Procedure Pnt2(X1,X2,X3); % create a vector of a point
  95. Begin scalar V;
  96. V:=MKVECT 2;
  97. V[0]:=X1;
  98. V[1]:=X2;
  99. V[2]:=X3;
  100. Return V;
  101. end;
  102. % %%%%%%%%%%%%%%%%%%%%%%%%%
  103. % PAIR KLUDGES %
  104. % %%%%%%%%%%%%%%%%%%%%%%%%%
  105. Procedure PRLISPCDR L$ %. PRLISPCDR of a list.
  106. If PAIRP L then CDR L else 'NIL$
  107. Procedure CAR1 L$ %. the Car1 element of
  108. If PAIRP L then CAR L else 'NIL$ %. a list.
  109. Procedure CAR2 L$ %. the CAR2 element of
  110. If LENGTH L > 1 then CADR L else 'NIL$ %. a list.
  111. Procedure CAR3 L$ %. the CAR3 element of
  112. If LENGTH L > 2 then CADDR L else 'NIL$ %. a list.
  113. Procedure CAR4 L$ %. the CAR4 element of
  114. If LENGTH L > 3 then CADDDR L else 'NIL$ %. a list.
  115. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  116. % interpreter supporting Procedures %
  117. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  118. Procedure V!.COPY V1$ %. Copy a vector
  119. Begin scalar N, V2$
  120. V2 := MKVECT(N := SIZE V1)$
  121. FOR I := 0 : N DO
  122. V2[I] := V1[I]$
  123. Return V2$
  124. end$
  125. % *********************
  126. % point primitive *
  127. % *********************
  128. Procedure MKPOINT (POINTLIST)$ %. make a vector form for
  129. Begin scalar P,I;
  130. P:=Pnt2(0,0,1);
  131. I:=0;
  132. While PairP PointList and I<=2 do
  133. <<P[I]:=Car PointList;
  134. I:=I+1;
  135. PointList:=Cdr PointList>>;
  136. Return P
  137. End;
  138. % **************************
  139. % initialize globals and *
  140. % and fluids *
  141. % set up for compiled *
  142. % version *
  143. % **************************
  144. FLUID '(
  145. DISPLAY!.LIST %. Used for object definition for MPS
  146. MAT!*0 %. 3 x 3 Zero Matrix
  147. MAT!*1 %. 3 x 3 Unit Matrix
  148. FirstPoint!* % FirstPoint of PointSet is MOVED to
  149. GLOBAL!.TRANSFORM %. Accumulation Transform
  150. CURRENT!.TRANSFORM
  151. CURRENT!.LINE %. Line Style
  152. CURRENT!.COLOR %. Default Color
  153. X1CLIP % Set by VWPORT for Clipping
  154. X2CLIP
  155. Y1CLIP
  156. Y2CLIP
  157. ThreeClip % Vector to return New Clipped point
  158. HEREPOINTX %/ Same as Xprevious?
  159. HEREPOINTY
  160. Xprevious % To do DDA on TEL and AAA
  161. Yprevious % Set by Move, used by DRAW
  162. DEV!. % Device Name, set by xxx!.Init()
  163. )$
  164. Procedure SetUpVariables; % Intialize Globals and Fluids
  165. Begin
  166. MAT!*0 := Mat8 ( 0,0,0,
  167. 0,0,0,
  168. 0,0,0)$
  169. MAT!*1 := Mat8 (1,0,0,
  170. 0,1,0,
  171. 0,0,1)$ % unit matrix.
  172. GLOBAL!.TRANSFORM := MAT!*1$
  173. CURRENT!.TRANSFORM := MAT!*1$ % current transformation matrix
  174. % initialized as mat!*1.
  175. CURRENT!.LINE := 'LINE$
  176. CURRENT!.COLOR := 'BLACK$
  177. HEREPOINTX := 0; HEREPOINTY:=0;
  178. ThreeClip := Vector(0,0,0,0);
  179. FirstPoint!* := NIL$
  180. End;
  181. % ---------------- BASIC Moving and Drawing -------------------
  182. % Project from Normalized 3 Vector to X,Y plane
  183. Procedure MoveToXY(X,Y)$ %. Move current cursor to x,y of P
  184. <<MoveS(X,Y);
  185. HEREPOINTX := X;
  186. HEREPOINTY := Y>>$
  187. Procedure DrawToXY(X,Y)$ %. Move cursor to "P" and draw from Previous
  188. <<DrawS(X,Y);
  189. HEREPOINTX := X;
  190. HEREPOINTY := Y>>$
  191. % **************************************
  192. % clipping-- on 2-D display screen *
  193. % **************************************
  194. Smacro procedure MakeThreeClip(X1,Y1,X2,Y2);
  195. <<ThreeClip[0]:=x1; ThreeClip[1]:=y1;
  196. ThreeClip[2]:=x2; ThreeClip[3]:=y2;
  197. ThreeClip>>;
  198. Procedure InView (L);
  199. NULL(Car L) and NULL(cadr L) and NULL(caddr L) and NULL (cadddr L);
  200. Procedure CLIP2D (x1,y1,x2,y2); % Iterative Clipper
  201. Begin scalar P1,P2,TMP;
  202. % Newmann and Sproull
  203. P1 := TESTPOINT(x1,y1); % Classify EndPoints, get 4 List
  204. P2 := TESTPOINT(x2,y2);
  205. If InView(P1) and InView(P2) then Return MakeThreeClip(x1,y1,X2,Y2);
  206. WHILE NOT(InView(P1) AND InView(P2) OR LOGICAND(P1,P2)) DO
  207. << If InView(P1) then % SWAP to get Other END
  208. <<TMP := P1$ P1 := P2$ P2 := TMP$
  209. TMP := X1$ X1 := X2$ X2 := TMP$
  210. TMP := Y1$ Y1 := Y2$ Y2 := TMP>>$
  211. If CADDDR P1 then
  212. <<Y1 := Y1 + ((Y2-Y1)*(X1CLIP-X1)) / (X2-X1)$
  213. X1 := X1CLIP>>
  214. else If CADDR P1 then
  215. <<Y1 := Y1 + ((Y2-Y1)*(X2CLIP-X1)) / (X2-X1)$
  216. X1 := X2CLIP>>
  217. else If CADR P1 then
  218. <<X1 := X1 + ((X2-X1)*(Y1CLIP-Y1)) / (Y2-Y1)$
  219. Y1 := Y1CLIP>>
  220. else If CAR P1 then
  221. <<X1 := X1 + ((X2-X1)*(Y2CLIP-Y1)) / (Y2-Y1)$
  222. Y1 := Y2CLIP>>$
  223. P1 := TESTPOINT(X1,Y1)>>; % reTest P1 after clipping
  224. If Not LOGICAND(P1,P2) then Return MakeThreeClip(X1,Y1,X2,Y2);
  225. Return NIL
  226. end$
  227. Procedure LOGICAND (P1, P2)$ %. logical "and".
  228. (CAR P1 AND CAR P2) OR %. use in clipping
  229. (CADR P1 AND CADR P2) OR
  230. (CADDR P1 AND CADDR P2) OR
  231. (CADDDR P1 AND CADDDR P2) $
  232. Procedure TESTPOINT(x,y)$ %. test If "P"
  233. LIST (If y > Y2CLIP then T else NIL, %. inside the viewport.
  234. If y < Y1CLIP then T else NIL, %.used in clipping
  235. If x > X2CLIP then T else NIL,
  236. If x < X1CLIP then T else NIL)$
  237. % All NIL if Inside
  238. % **********************************
  239. % tranformation matrices *
  240. % matrices internal are stored as *
  241. % OnePoint = [x y w] *
  242. % matrix = [v0 v3 v6 *
  243. % v1 v4 v7 *
  244. % v2 v5 v8 ] *
  245. % **********************************
  246. %*******************************************************
  247. % Matrix Multiplication given two 3 by 3 matricies *
  248. %*******************************************************
  249. Procedure MAT!*MAT (V1,V2)$ %. multiplication of matrices.
  250. Mat8 ( % V1 and V2 are 3 by 3 matrices.
  251. V1[0] * V2[0] + V1[3] * V2[1] + V1[6] * V2[2],
  252. V1[1] * V2[0] + V1[4] * V2[1] + V1[7] * V2[2],
  253. V1[2] * V2[0] + V1[5] * V2[1] + V1[8] * V2[2],
  254. V1[0] * V2[3] + V1[3] * V2[4] + V1[6] * V2[5],
  255. V1[1] * V2[3] + V1[4] * V2[4] + V1[7] * V2[5],
  256. V1[2] * V2[3] + V1[5] * V2[4] + V1[8] * V2[5],
  257. V1[0] * v2[6] + V1[3] * V2[7] + V1[6] * V2[8],
  258. V1[1] * v2[6] + V1[4] * V2[7] + V1[7] * V2[8],
  259. V1[2] * v2[6] + V1[5] * V2[7] + V1[8] * V2[8]);
  260. Procedure PNT!*PNT(U,V)$ %. multiplication of matrices
  261. U[0] * V[0] +
  262. U[1] * V[1] + %. 1 by 3 and 3 by 1.
  263. U[2] * V[2] $ % Returning a value.
  264. Procedure PNT!*MAT(U,V)$ %. multiplication of matrices
  265. Begin scalar U0,U1,U2$ %. 1 by 3 with 3 by 3.
  266. U0 := U[0]$
  267. U1 := U[1]$ % Returning a 1 by 3 vector.
  268. U2 := U[2]$
  269. U:=Mkvect 2;
  270. u[0]:= U0 * V[0] + U1 * V[3] + U2 * V[6];
  271. u[1]:= U0 * V[1] + U1 * V[4] + U2 * V[7];
  272. u[2]:= U0 * V[2] + U1 * V[5] + U2 * V[8];
  273. Return U;
  274. end$
  275. % **********************
  276. % translation *
  277. % **********************
  278. Procedure XMove(TX)$ %. x translation only
  279. Move (TX,0) $
  280. Procedure YMove(TY)$ %. y translation only
  281. Move (0,TY) $
  282. Procedure Move(TX,TY)$ %. Move origin / object$
  283. Mat8(1, 0, TX, %. make a translation
  284. 0, 1, TY, %. transformation matrix
  285. 0, 0, 1)$
  286. % *******************
  287. % Z rotation *
  288. % *******************
  289. Procedure ZROT(Theta)$ %. rotation about z
  290. Begin scalar S,C;
  291. S := SIND (THETA)$ %. sin in degrees uses mathlib
  292. C := COSD (THETA)$ %. cos in degrees uses mathlib
  293. Return Mat8( C,-S,0,
  294. S,C,0,
  295. 0,0,1);
  296. end $
  297. % ******************
  298. % scaling *
  299. % ******************
  300. Procedure XSCALE (SX)$ %. scaling along X axis only.
  301. SCALE1 (SX,1) $
  302. Procedure YSCALE (SY)$ %. scaling along Y axis only.
  303. SCALE1 (1,SY) $
  304. Procedure SCALE1(XT,YT)$ %. scaling transformation
  305. Mat8 ( XT, 0, 0, %. matrix.
  306. 0 ,YT, 0,
  307. 0, 0, 1)$
  308. Procedure SCALE SFACT; %. scaling along 2 axes.
  309. SCALE1(SFACT,SFACT);
  310. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  311. % Procedure definitions %
  312. % in the interpreter %
  313. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  314. Put('OnePoint,'PBINTRP,'DrawPOINT)$
  315. Put('POINTSET,'PBINTRP,'DrawPOINTSET)$
  316. Put('GROUP,'PBINTRP,'DrawGROUP)$
  317. Put('TRANSFORM,'PBINTRP,'PERFORMTRANSFORM)$
  318. Put('PICTURE,'PBINTRP,'DrawModel)$
  319. Put('CIRCLE,'PBINTRP,'DrawCIRCLE)$
  320. Put('BEZIER,'PBINTRP,'DOBEZIER)$
  321. Put('LINE,'PBINTRP,'DOLINE)$
  322. Put('BSPLINE,'PBINTRP,'DOBSPLINE)$
  323. Put('REPEATED, 'PBINTRP,'DOREPEATED)$
  324. Put('Color,'pbintrp,'Docolor);
  325. %******************************************
  326. % SETUP Procedure FOR BEZIER AND BSPLINE *
  327. % LINE and COLOR
  328. %******************************************
  329. procedure DoColor(Object,N);
  330. Begin scalar SaveColor;
  331. SaveColor:=Current!.color;
  332. N:=Car1 N; % See CIRCLE example, huh?
  333. If IDP N then N:=EVAL N;
  334. ChangeColor N;
  335. Draw1(Object,CURRENT!.TRANSFORM);
  336. ChangeColor SaveColor;
  337. Return NIL;
  338. End;
  339. Procedure DOBEZIER OBJECT$
  340. Begin scalar CURRENT!.LINE$
  341. CURRENT!.LINE := 'BEZIER$
  342. Draw1(Object,CURRENT!.TRANSFORM);
  343. end$
  344. Procedure DOBSPLINE OBJECT$
  345. Begin scalar CURRENT!.LINE$
  346. CURRENT!.LINE := 'BSPLINE$
  347. Draw1(Object,CURRENT!.TRANSFORM);
  348. end$
  349. Procedure DOLINE OBJECT$
  350. Begin scalar CURRENT!.LINE$
  351. CURRENT!.LINE := 'LINE$
  352. Draw1(Object,CURRENT!.TRANSFORM);
  353. end$
  354. %*************************************
  355. % interpreted function calls *
  356. %*************************************
  357. Procedure DOREPEATED(MODEL,REPTFUN)$ %. repeat applying
  358. Begin scalar TEMP,I,TRANS,COUNT,TS,TA,GRP$ %. transformations.
  359. TRANS := PRLISPCDR REPTFUN$
  360. If LENGTH TRANS = 1 then
  361. TRANS := EVAL CAR1 TRANS
  362. else % "TRANS": transformation
  363. << TS :=CAR1 TRANS$ % matrix.
  364. TA := PRLISPCDR TRANS $ % "MODEL": the model.
  365. TRANS := APPLY(TS,TA) >> $ % "COUNT": the times "MODEL"
  366. COUNT := CAR1 REPTFUN$ % is going to be
  367. GRP := LIST('GROUP)$ % repeated.
  368. TEMP := V!.COPY TRANS$
  369. FOR I := 1 : COUNT DO
  370. << GRP := LIST('TRANSFORM,MODEL,TEMP) . GRP$
  371. TEMP := MAT!*MAT(TEMP,TRANS) >>$
  372. GRP := REVERSE GRP$
  373. Return GRP
  374. end$
  375. %***********************************
  376. % Define SHOW ESHOW Draw AND EDraw *
  377. % ESHOW AND EDraw ERASE THE SCREEN *
  378. %***********************************
  379. Procedure SHOW X; %. ALIAS FOR Draw
  380. <<
  381. If DEV!. = 'MPS then %. MPS driver don't call
  382. << %. echo functions for diplay
  383. %. device
  384. DISPLAY!.LIST := LIST (X, DISPLAY!.LIST);
  385. FOR EACH Z IN DISPLAY!.LIST DO
  386. If Z neq NIL then
  387. Draw1(Z,GLOBAL!.TRANSFORM); % Draw object list
  388. % to frame
  389. PSnewframe(); % display frame
  390. >>
  391. else
  392. << GraphOn(); % call echo off If not emode
  393. % If neccessary turn low level
  394. Draw1(X,GLOBAL!.TRANSFORM); % Draw model tekronix style
  395. GraphOff(); % call echoon
  396. >>;
  397. >>;
  398. Procedure ESHOW ZZ$ %. erases the screen and
  399. <<Erase(); %. display the picture "ZZ"
  400. GraphOn();
  401. DELAY();
  402. Draw1(ZZ,GLOBAL!.TRANSFORM); % Draw model tekronix style
  403. If DEV!. = 'MPS then << % Mps display frame
  404. PSnewframe();
  405. DISPLAY!.LIST := ZZ; >>;
  406. GraphOff();
  407. 0 >>;
  408. DefineROP('SHOW,10); %. set up precedence
  409. DefineROP('ESHOW,10);
  410. Procedure Draw X; %. ALIAS FOR SHOW
  411. SHOW X$
  412. Procedure EDraw ZZ$ %. erases the screen and
  413. ESHOW ZZ$
  414. DefineROP('Draw,10);
  415. DefineROP('EDraw,10);
  416. Procedure Col N; % User top-level color
  417. <<GraphOn(); ChangeColor N; GraphOff()>>;
  418. %*************************************
  419. % Define Draw FUNCTIONS FOR VARIOUS *
  420. % TYPES OF DISPLAYABLE OBJECTS *
  421. %*************************************
  422. Procedure DrawModel PICT$ %. given picture "PICT" will
  423. Draw1(PICT,CURRENT!.TRANSFORM)$ %. be applyied with global
  424. Procedure DERROR(MSG,OBJECT);
  425. <<PRIN2 " Draw Error `"; PRIN2T MSG;
  426. PRIN2 OBJECT; ERROR(700,MSG)>>;
  427. Procedure Draw1 (PICT,CURRENT!.TRANSFORM)$ % Draw PICT with TRANSFORMATION
  428. Begin scalar ITM,ITSARGS$
  429. If NULL Pict then Return NIL;
  430. If IDP PICT then PICT:=EVAL PICT;
  431. If VECTORP PICT AND SIZE(PICT)=2 then Return DrawPOINT PICT$
  432. If NOT PAIRP PICT then DERROR("Non Pair in Draw1: ",PICT);
  433. ITM := CAR1 PICT$
  434. ITSARGS := PRLISPCDR PICT$
  435. If NOT (ITM = 'TRANSFORM) then
  436. ITSARGS := LIST ITSARGS$ % gets LIST of args
  437. ITM := GET (ITM,'PBINTRP)$
  438. If NULL ITM then DERROR("Unknown Operator in Draw1:",PICT);
  439. APPLY(ITM,ITSARGS)$
  440. Return PICT$
  441. end$
  442. Procedure DrawGROUP(GRP)$ % Draw a group object
  443. Begin scalar ITM,ITSARGS,LMNT$
  444. If PAIRP GRP then
  445. FOR EACH LMNT IN GRP DO
  446. If PAIRP LMNT then Draw1 (LMNT,CURRENT!.TRANSFORM)
  447. else Draw1 (EVAL LMNT,CURRENT!.TRANSFORM)
  448. else Draw1 (EVAL GRP,CURRENT!.TRANSFORM)$
  449. Return GRP$
  450. end$
  451. Procedure DrawPOINTSET (PNTSET)$
  452. Begin scalar ITM,ITSARGS,PT$
  453. FirstPoint!* := 'T$
  454. If PAIRP PNTSET then
  455. << If CURRENT!.LINE = 'BEZIER then
  456. PNTSET := DrawBEZIER PNTSET
  457. else If CURRENT!.LINE = 'BSPLINE then
  458. PNTSET := DrawBSPLINE PNTSET$
  459. FOR EACH PT IN PNTSET DO
  460. <<If PAIRP PT then Draw1 (PT,CURRENT!.TRANSFORM)
  461. else Draw1 (EVAL PT,CURRENT!.TRANSFORM)$
  462. FirstPoint!* := 'NIL>> >>
  463. else Draw1 (EVAL PNTSET,CURRENT!.TRANSFORM)$
  464. Return PNTSET$
  465. end$
  466. Procedure DrawPOINT (PNT)$
  467. Begin scalar CLP,X1,Y1,W1,V,U0,U1,U2;
  468. If IDP PNT then PNT := EVAL PNT$
  469. If PAIRP PNT then PNT := MKPOINT PNT;
  470. V:=CURRENT!.TRANSFORM;
  471. % Transform Only x,y and W
  472. U0:=PNT[0]; U1:=PNT[1]; U2:=PNT[2];
  473. X1:=U0 * V[0] + U1 * V[1] + U2 * V[2];
  474. Y1:=U0 * V[3] + U1 * V[4] + U2 * V[5];
  475. W1:=U0 * V[6] + U1 * V[7] + U2 * V[8];
  476. IF NOT( (W1=1) or (W1 = 1.0)) then <<x1:=x1/w1; y1:=y1/w1>>;
  477. If FirstPoint!* then Return MoveToXY(X1,Y1);
  478. % back to w=1 plane If needed.
  479. CLP := CLIP2D(HEREPOINTX,HerePointY, X1,Y1)$
  480. If CLP then <<MoveToXY(CLP[0],CLP[1])$
  481. DrawToXY(CLP[2],CLP[3])>>$
  482. end$
  483. Procedure PERFORMTRANSFORM(PCTSTF,TRNSFRM)$
  484. Begin scalar PROC,OLDTRNS,TRNSFMD,TRANSFOP,
  485. TRANSARG,ITM,ITSARGS$
  486. If IDP TRNSFRM then
  487. TRNSFRM := EVAL TRNSFRM$
  488. If VECTORP TRNSFRM AND SIZE(TRNSFRM) = 8 then
  489. Draw1 (PCTSTF,MAT!*MAT(TRNSFRM,CURRENT!.TRANSFORM))
  490. else If PAIRP TRNSFRM then
  491. <<TRANSFOP := CAR1 TRNSFRM$
  492. If (TRANSARG := PRLISPCDR TRNSFRM)
  493. then TRANSARG := LIST (PCTSTF,TRANSARG)
  494. else TRANSARG := LIST PCTSTF$
  495. If (TRANSFOP = 'BEZIER OR TRANSFOP = 'BSPLINE) then
  496. APPLY(GET(TRANSFOP,'PBINTRP),TRANSARG)
  497. else
  498. Draw1 (APPLY(GET(TRANSFOP,'PBINTRP),TRANSARG),
  499. CURRENT!.TRANSFORM) >>
  500. end$
  501. %***************************************
  502. % circle bezier and bspline functions *
  503. %***************************************
  504. Procedure DrawCIRCLE(CCNTR,RADIUS); %. Draw a circle
  505. Begin scalar APNT,POLY,APNTX, APNTY$
  506. POLY := LIST('POINTSET)$
  507. If IDP CCNTR then CCNTR := EVAL CCNTR$
  508. RADIUS := CAR1 RADIUS$
  509. If IDP RADIUS then
  510. RADIUS := EVAL RADIUS$
  511. FOR ANGL := 180 STEP -15 UNTIL -180 DO % each line segment
  512. << APNTX := CCNTR[0] + RADIUS * COSD ANGL$ % represents an arc of 15 dgrs
  513. APNTY := CCNTR[1] + RADIUS * SIND ANGL$
  514. POLY := LIST('Onepoint,APNTX,APNTY) . POLY>>$
  515. Return REVERSE POLY
  516. end$
  517. Procedure DrawBspline CONPTS$ %. a "closed" Periodic bspline curve
  518. Begin scalar N,CURPTS, % See CATMUL thesis Appendix
  519. CPX,CPY, % Note correction in Matrix!
  520. X0,X1,X2,X3,
  521. Y0,Y1,Y2,Y3,
  522. T1,T2,T3,
  523. J0,J1,J2,
  524. NPTS;
  525. NPTS := 4;
  526. N := LENGTH CONPTS$ %/ Check at least 4 ?
  527. CONPTS := Append (CONPTS,CONPTS)$ % To make a Closed Loop
  528. % Set the Initial 4 points
  529. X0:=0; % Dummy
  530. Y0:=0;
  531. X1:=GETV(CAR CONPTS,0); % Will Be X0,Y0 in loop
  532. Y1:=GETV(CAR CONPTS,1);
  533. CONPTS := CDR CONPTS;
  534. X2:=GETV(CAR CONPTS,0);
  535. Y2:=GETV(CAR CONPTS,1);
  536. CONPTS := CDR CONPTS;
  537. X3:=GETV(CAR CONPTS,0);
  538. Y3:=GETV(CAR CONPTS,1);
  539. WHILE N > 0 DO
  540. << X0 := X1; Y0 := Y1; % Cycle Points
  541. X1 := X2; Y1 := Y2;
  542. X2 := X3; Y2 := Y3;
  543. CONPTS := CDR CONPTS;
  544. X3:=GETV(CAR CONPTS,0);
  545. Y3:=GETV(CAR CONPTS,1);
  546. % Compute X(t) and Y(t) for NPTS points on [0.0,1.0]
  547. FOR I := 0:NPTS-1 DO
  548. << T1 := FLOAT(I)/NPTS$ % Powers of t
  549. T2 := T1 * T1;
  550. T3 := T2 * T1;
  551. %/ ( -1 3 -3 1
  552. %/ 3 -6 3 0
  553. %/ -3 0 3 0
  554. %/ 1 4 1 0 )
  555. J0:= (1.0-T3) + 3.0*(T2-T1);
  556. J1 := 3.0*T3 - 6*T2 +4.0;
  557. J2 := 1.0+ 3.0*(T1 +T2- T3);
  558. CPX := (X0*J0 +X1*J1 + X2 *J2 +X3*T3)/6.0;
  559. CPY := (Y0*J0 +Y1*J1 + Y2 *J2 +Y3*T3)/6.0;
  560. CURPTS := Pnt2(CPX, CPY,1.0) . CURPTS >>$
  561. N := N - 1>>;
  562. Return CURPTS
  563. end$
  564. % Faster 2-d Bezier
  565. procedure DrawBEZIER CNTS; % Give list of Points
  566. Begin
  567. scalar LEN, NALL, SAVEX, SAVEY, CPX, CPY,
  568. CURPTS, T0, T1, TEMP, FACTL, TI, FI,COEFF;
  569. LEN := Isub1 LENGTH(CNTS);
  570. SaveX := MKVect Len;
  571. SaveY := MKVect Len;
  572. FACTL := IFACT LEN;
  573. FOR I := 0:LEN DO
  574. <<Coeff := FactL/(IFACT(i)*IFACT(Len-i));
  575. SAVEX[I] := GETV(CAR CNTS, 0) * Coeff;
  576. SAVEY[I] := GETV(CAR CNTS, 1) * Coeff;;
  577. CNTS := CDR CNTS>>;
  578. NALL := 1.0/(8.0 * LEN); % Step Size
  579. FOR T0 := 0.0 STEP NALL UNTIL 1.0 DO
  580. << T1 := 1.0-T0;
  581. TI := T0;
  582. TEMP := T1**LEN;
  583. CPX := TEMP * SAVEX[0];
  584. CPY := TEMP * SAVEY[0];
  585. FOR I := 1:LEN DO
  586. << TEMP := (TI * (T1**(LEN - I)));
  587. TI := TI * T0;
  588. CPX := TEMP * SAVEX[I] + CPX;
  589. CPY := TEMP * SAVEY[I] + CPY >>;
  590. CURPTS := LIST ('ONEPOINT, CPX, CPY) . CURPTS
  591. >>;
  592. Return REVERSE CURPTS;
  593. end;
  594. procedure IFACT N; % fast factorial
  595. Begin scalar M;
  596. M:=1;
  597. While Igreaterp(N,1) do <<M:=Itimes2(N,M); N :=Isub1 N>>;
  598. Return M;
  599. end;
  600. LoadTime SetUpVariables();
  601. % --------- OTHER UTILITIES ------------
  602. Procedure SAVEPICT (FIL,PICT,NAM)$ %. save a picture with no
  603. Begin scalar OLD; %. vectors.
  604. FIL := OPEN (FIL,'OUTPUT)$ % fil : list('dir,file.ext)
  605. OLD := WRS FIL$ % nam : id
  606. PRIN2 NAM$ PRIN2 '! !:!=! !'$ PRIN2 PICT$ % pict: name of pict to
  607. PRIN2 '!;$ WRS 'NIL$ CLOSE FIL$ % be saved.
  608. Return PICT$
  609. % fil: file name to save
  610. % "pict".
  611. end$ % nam: name to be used
  612. % after TAILore.
  613. % type "in fil" to TAILore
  614. % old picture.