escher.ps 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. %!
  2. % If you're concerned that the cpu in your PostScript printer will atrophy
  3. % from disuse, here is another Escher-like contribution to to keep it busy
  4. % for a while. It uses PostScript color commands, but will still work on
  5. % a monochrome printer (but isn't very pretty in black & white).
  6. %
  7. % The butterflies are arranged in a hexagonal grid (wallpaper group p6),
  8. % and the moveto, lineto, curveto commands used to render the tesselation
  9. % are redefined so as to impose a nonlinear transform that shrinks the
  10. % infinite plane to an ellipse. This is a sleazy way to mimic Escher's
  11. % "circle limit" sorts of things.
  12. %
  13. % The butterfly permimeter was made by imposing all the symmetry constraints
  14. % on a path, and then that path was filled in using Adobe Illustrator
  15. %
  16. % The routines Xform and next_color are easy to change if you want to hack
  17. % with them. The code was written to sacrifice efficiency for readability.
  18. %
  19. % Bob Wallis
  20. %
  21. % UUCP {sun,pyramid,cae780,apple}!weitek!wallis
  22. /eschersave save def % prevent left over side effects
  23. %statusdict begin waittimeout 6000 lt % if you have a slow printer, you
  24. % {0 60 6000 setdefaulttimeouts} % might need to uncomment this
  25. %if end
  26. /nlayers 1 def % 1 takes about 10 minutes on a LW+; 2 takes 4x longer
  27. /warp 1 def % 1 -> ellipsoidal distortion; 0 -> flat Euclidean
  28. /inch {72 mul} def
  29. /x4 152 def /y4 205.6 def % 6 fold rotation center of bfly
  30. /x12 387.20 def /y12 403.84 def % 3 fold center of bfly
  31. /dx x4 x12 sub def % [dx,dy] = distance between the
  32. /dy y4 y12 sub def % two fixed points above
  33. /Dm dx dup mul dy dup mul % magnitude of basis vectors of
  34. add sqrt 3 sqrt mul % parallelogram lattice
  35. def % = |dx,dy| * sqrt(3)
  36. /Da dy dx atan 30 add def
  37. /D1x Dm Da cos mul def % [D1x, D1y] = basis vector vector #1
  38. /D1y Dm Da sin mul def % = [Dm,0] exp(j30)
  39. /Da dy dx atan 30 sub def
  40. /D2x Dm Da cos mul def % [D2x, D2y] = basis vector vector #2
  41. /D2y Dm Da sin mul def % = [Dm,0] exp(-j30)
  42. /m { moveto} def
  43. /L {lineto} def
  44. /S {stroke} def
  45. /c {curveto} def
  46. /f {closepath fill} def
  47. /F {closepath fill} def
  48. /g { setgray} def
  49. /FillStroke { % fill interior & stroke black border
  50. closepath gsave fill grestore 0 setgray stroke
  51. } def
  52. %
  53. % Description of 1 butterfly
  54. %
  55. /body {
  56. 314.96 280.19 m
  57. 383.4 261.71 445.11 243.23 513.52 224.68 c
  58. 463.68 256.59 490.26 328.83 446.99 360.76 c
  59. 423.71 347.32 397.08 339.7 367.07 337.9 c
  60. 388.93 358.28 414.14 372.84 442.73 381.58 c
  61. 426.68 398.18 394.07 389.7 387.2 403.84 c
  62. 371.52 404.96 362.56 372.48 340.16 366.88 c
  63. 346.88 396.01 346.88 425.12 340.16 454.24 c
  64. 326.72 427.35 320 400.48 320 373.6 c
  65. 270.71 352.1 221.44 411.23 168.88 384.02 c
  66. 189.04 388.03 202.48 380.4 212.57 366.95 c
  67. 216.72 350.85 209.23 341.46 190.1 338.79 c
  68. 177.34 343.57 167.94 354.17 161.9 370.59 c
  69. 176.06 305.52 132.02 274.05 152 205.6 c
  70. 201.29 257.12 250.56 234.72 299.84 279.52 c
  71. 288.64 266.08 284.16 252.64 286.4 239.2 c
  72. 298.27 223.97 310.15 222.18 322.02 233.82 c
  73. 328.62 249.28 328.51 264.74 314.96 280.19 c
  74. FillStroke
  75. } def
  76. /eyes {
  77. 294.8125 238.3246 m
  78. 296.9115 238.3246 298.6132 242.7964 298.6132 248.3125 c
  79. 298.6132 253.8286 296.9115 258.3004 294.8125 258.3004 c
  80. 292.7135 258.3004 291.0118 253.8286 291.0118 248.3125 c
  81. 291.0118 242.7964 292.7135 238.3246 294.8125 238.3246 c
  82. closepath gsave 1 g fill grestore 0 g S
  83. 319.5 241.1782 m
  84. 321.7455 241.1782 323.5659 245.4917 323.5659 250.8125 c
  85. 323.5659 256.1333 321.7455 260.4468 319.5 260.4468 c
  86. 317.2545 260.4468 315.4341 256.1333 315.4341 250.8125 c
  87. 315.4341 245.4917 317.2545 241.1782 319.5 241.1782 c
  88. closepath gsave 1 g fill grestore 0 g S
  89. 0 g
  90. 296.875 242.0939 m
  91. 297.4608 242.0939 297.9356 243.479 297.9356 245.1875 c
  92. 297.9356 246.896 297.4608 248.2811 296.875 248.2811 c
  93. 296.2892 248.2811 295.8143 246.896 295.8143 245.1875 c
  94. 295.8143 243.479 296.2892 242.0939 296.875 242.0939 c
  95. f
  96. 0 g
  97. 318.5 243.7707 m
  98. 319.281 243.7707 319.9142 245.0766 319.9142 246.6875 c
  99. 319.9142 248.2984 319.281 249.6043 318.5 249.6043 c
  100. 317.719 249.6043 317.0858 248.2984 317.0858 246.6875 c
  101. 317.0858 245.0766 317.719 243.7707 318.5 243.7707 c
  102. f
  103. } def
  104. /stripes {
  105. 292 289 m
  106. 252 294 241 295 213 279 c
  107. 185 263 175 252 159 222 c
  108. S
  109. 285 313 m
  110. 239 326 226 325 206 315 c
  111. 186 305 164 278 161 267 c
  112. S
  113. 298 353 m
  114. 262 342 251 339 237 355 c
  115. 223 371 213 380 201 383 c
  116. S
  117. 330 288 m
  118. 384 293 385 292 418 280 c
  119. 451 268 452 264 473 247 c
  120. S
  121. 342 306 m
  122. 381 311 386 317 410 311 c
  123. 434 305 460 287 474 262 c
  124. S
  125. 345 321 m
  126. 352 357 359 367 379 377 c
  127. 399 387 409 385 426 382 c
  128. S
  129. 327.75 367.75 m
  130. 336.5 392.25 333.682 403.348 335.25 415.5 c
  131. S
  132. 320 364.75 m
  133. 322 361.75 323.5 360.5 326.25 360 c
  134. 329 359.5 332 360.5 334 362.75 c
  135. S
  136. 316.25 356.5 m
  137. 318.75 353.25 320 353 323.25 352.25 c
  138. 326.5 351.5 329 352 331.5 353.25 c
  139. S
  140. 312.5 349 m
  141. 316.75 345.5 318.25 344.5 321.25 343.75 c
  142. 324.25 343 327 344 329.75 346 c
  143. S
  144. 310.75 340.75 m
  145. 314.25 336.5 316.25 335.25 320 335.25 c
  146. 323.75 335.25 327 336.5 329.25 338 c
  147. S
  148. 308.5 332 m
  149. 311.75 328.5 312.5 327.25 317 327 c
  150. 321.5 326.75 325.75 328.25 327.75 329.75 c
  151. S
  152. 305 322 m
  153. 309.5 317.75 310.75 317 315 316.5 c
  154. 319.25 316 322.25 318 324.75 320 c
  155. S
  156. 302.25 311 m
  157. 307 307.5 307.75 306.25 312.75 306 c
  158. 317.75 305.75 320 307.25 323.75 309.5 c
  159. S
  160. 301.25 298.25 m
  161. 304.5 292.75 305.25 292 308.25 292 c
  162. 311.25 292 313.75 293.75 315.75 295.75 c
  163. S
  164. } def
  165. /nostrils {
  166. 0 g
  167. 304.062 227.775 m
  168. 304.599 227.775 305.034 228.883 305.034 230.25 c
  169. 305.034 231.616 304.599 232.724 304.062 232.724 c
  170. 303.525 232.724 303.09 231.616 303.09 230.25 c
  171. 303.09 228.883 303.525 227.775 304.062 227.775 c
  172. f
  173. 304.062 230.25 m
  174. F
  175. 309.562 228.275 m
  176. 310.099 228.275 310.534 229.383 310.534 230.75 c
  177. 310.534 232.116 310.099 233.224 309.562 233.224 c
  178. 309.025 233.224 308.59 232.116 308.59 230.75 c
  179. 308.59 229.383 309.025 228.275 309.562 228.275 c
  180. f
  181. } def
  182. /thorax
  183. {
  184. 327.5 300 m
  185. 316.5 283 315.5 275.5 308 277.5 c
  186. 294 311.5 299 313.5 304 334 c
  187. 309 354.5 315.5 362 322.5 372 c
  188. 329.5 382 327.5 376.5 331 376 c
  189. 334.5 375.5 339.1367 379.1109 339 369 c
  190. 338.5 332 333.4999 324.5 330.5 311.5 c
  191. 0 g S
  192. } def
  193. /spots {
  194. next_color
  195. 192 242.201 m
  196. 202.1535 242.201 210.3848 251.0655 210.3848 262 c
  197. 210.3848 272.9345 202.1535 281.799 192 281.799 c
  198. 181.8465 281.799 173.6152 272.9345 173.6152 262 c
  199. 173.6152 251.0655 181.8465 242.201 192 242.201 c
  200. FillStroke
  201. next_color
  202. 447.5 250.2365 m
  203. 459.6061 250.2365 469.4203 257.5181 469.4203 266.5 c
  204. 469.4203 275.4819 459.6061 282.7635 447.5 282.7635 c
  205. 435.3939 282.7635 425.5797 275.4819 425.5797 266.5 c
  206. 425.5797 257.5181 435.3939 250.2365 447.5 250.2365 c
  207. FillStroke
  208. next_color
  209. 401 369.1005 m
  210. 409.5914 369.1005 416.5563 373.5327 416.5563 379 c
  211. 416.5563 384.4673 409.5914 388.8995 401 388.8995 c
  212. 392.4086 388.8995 385.4436 384.4673 385.4436 379 c
  213. 385.4436 373.5327 392.4086 369.1005 401 369.1005 c
  214. FillStroke
  215. next_color
  216. 249 348.2721 m
  217. 261.4966 348.2721 271.6274 353.9707 271.6274 361 c
  218. 271.6274 368.0293 261.4966 373.7279 249 373.7279 c
  219. 236.5034 373.7279 226.3726 368.0293 226.3726 361 c
  220. 226.3726 353.9707 236.5034 348.2721 249 348.2721 c
  221. FillStroke
  222. } def
  223. /ncolor 6 def
  224. /cidx 0 def
  225. /next_color {
  226. cidx ncolor div % hue
  227. .75 % saturation (change these if you like)
  228. .8 % lightness
  229. sethsbcolor
  230. /cidx cidx 1 add ncolor mod def
  231. } def
  232. /cidx 0 def
  233. /max_r2 % radius^2 for center of outermost ring of butterflies
  234. Dm nlayers mul 1.05 mul dup mul
  235. def
  236. /max_radius max_r2 sqrt def
  237. /max_radius_inv 1 max_radius div def
  238. /Dm_inv 1 Dm div def
  239. %
  240. % Ellipsoidal distortion, maps "nlayers" concentric rings of cells into
  241. % an ellipse centered on page
  242. % D length of 1 basis vector separating hexagonal cells
  243. % z0 center of 6-fold rotation = origin of shrink xform
  244. % z' = (z - z0)/D new coord system
  245. % |z'| = sqrt(x^2 + [(8.5/11)*y]^2) aspect ratio of paper
  246. % z" = z' * a/M(|z'|) shrink by "a/M(|z|)" as fcn of radius
  247. % At the max radius, we want the shrunk ellipse to be "W" units wide so it
  248. % just fits our output format - solve for scale factor "a"
  249. % zmax = n+0.5 for n layers of cells
  250. % zmax * [a/M(zmax)] = W 1/2 width of output on paper
  251. % a = M(zmax)*W/zmax solve for "a"
  252. %/M{dup mul 1 add sqrt}bind def % M(u) = sqrt(1+|u|^2) = one possible shrink
  253. /M { 1.5 add } bind def % M(u) = (1.5+|u|) = another possible one
  254. /W 3.8 inch def % 1/2 width of ellipse
  255. /zmax 0.5 nlayers add def % radius at last layer of hexagons
  256. /a zmax M W mul zmax div def % a = M(zmax)*W/zmax
  257. /Xform { % [x0,y0] = ctr ellipse
  258. Matrix transform
  259. /y exch def
  260. /x exch def
  261. /z x dup mul y .773 mul dup mul add sqrt def % ellipse radius
  262. /Scale a z M div def % z=a/M(|z|)
  263. x Scale mul x0 add % magnify back up
  264. y Scale mul y0 add % [x0+x*s, y0+y*s]
  265. } def
  266. /Helvetica findfont 8 scalefont setfont
  267. 4.25 inch 0.5 inch moveto
  268. (RHW) stringwidth pop -0.5 mul 0 rmoveto
  269. (RHW) show % autograph
  270. warp 1 eq { % redefine commands to use Xform
  271. /moveto { Xform //moveto} def
  272. /lineto { Xform //lineto} def
  273. /curveto {
  274. Xform 6 -2 roll
  275. Xform 6 -2 roll
  276. Xform 6 -2 roll
  277. //curveto
  278. } def
  279. }if
  280. /bfly { % paint 1 butterfly
  281. next_color body
  282. 1 setgray eyes
  283. stripes
  284. 0 setgray nostrils
  285. 0.5 setgray thorax next_color
  286. spots
  287. } def
  288. /x0 x4 def % center
  289. /y0 y4 def
  290. /T1matrix % xlate to center of image
  291. x0 neg y0 neg matrix translate
  292. def
  293. /Smatrix % scale so that 1 basis vector = 1.0
  294. Dm_inv dup matrix scale
  295. def
  296. /HexCell { % 6 butterflys rotated about center of
  297. /cidx 0 def % 6 fold symmetry
  298. /color 0 def
  299. /T2matrix dx dy matrix translate def
  300. 0 60 300 {
  301. /angle exch def
  302. /Rmatrix angle matrix rotate def
  303. /Matrix % translate, rotate, scale - used by Xform
  304. T1matrix Rmatrix matrix concatmatrix
  305. T2matrix matrix concatmatrix
  306. Smatrix matrix concatmatrix
  307. def
  308. gsave
  309. warp 0 eq % then may use usual PostScript machinery
  310. { % else using Xform
  311. x0 y0 translate angle rotate
  312. .5 dup scale
  313. dx x0 sub dy y0 sub translate
  314. } if
  315. bfly
  316. next_color
  317. grestore
  318. } for
  319. } def
  320. %320 x4 sub 240 y4 sub translate
  321. 4.25 inch x4 sub 5.5 inch y4 sub translate
  322. 0 setlinewidth
  323. /N 2 def
  324. N neg 1 N {
  325. /i exch def % translate to
  326. N neg 1 N { % i*D1 + j*D2
  327. /j exch def % and draw HexCell
  328. gsave
  329. /dx i D1x mul j D2x mul add def % translate HexCell by
  330. /dy i D1y mul j D2y mul add def % [dx,dy]
  331. /r2 dx dup mul dy dup mul add def % r^2 = |dx,dy|^2
  332. r2 max_r2 lt % inside radius?
  333. { % yes
  334. 1 r2 max_r2 div sub sqrt 2 div
  335. setlinewidth % make skinnier lines
  336. HexCell % 6 butterflies
  337. }
  338. if
  339. grestore
  340. } for
  341. } for
  342. showpage
  343. clear cleardictstack
  344. eschersave restore