home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / elk / part09 < prev    next >
Encoding:
Text File  |  1989-09-23  |  57.0 KB  |  1,675 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v08i057: Elk (Extension Language Toolkit) part 09 of 14
  4. Reply-To: net@tub.UUCP (Oliver Laumann)
  5.  
  6. Posting-number: Volume 8, Issue 57
  7. Submitted-by: net@tub.UUCP (Oliver Laumann)
  8. Archive-name: elk/part09
  9.  
  10. [Let this be a lesson to submitters:  this was submitted as uuencoded,
  11. compressed files.  I lost the source information while unpacking it; this
  12. is the best approximation I could come up with.  ++bsa]
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 9 (of 14)."
  21. # Contents:  tst/billiard lib/xlib/examples/properties
  22. #   lib/xlib/examples/track lib/xlib/examples/picture
  23. #   lib/xlib/examples/useful lib/xlib/pixel.c
  24. # Wrapped by net@tub on Sun Sep 17 17:32:32 1989
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f tst/billiard -a "${1}" != "-c" ; then 
  27.   echo shar: Will not over-write existing file \"tst/billiard\"
  28. else
  29. echo shar: Extracting \"tst/billiard\" \(46118 characters\)
  30. sed "s/^X//" >tst/billiard <<'END_OF_tst/billiard'
  31. X;;;
  32. X;;; BILLIARD.SCM: This file contains code for a very simple billiard ball
  33. X;;;               simulator.  The simulation takes place in two dimensions.
  34. X;;;               The balls are really disks in that their height is not taken
  35. X;;;               into account.  All interactions are assumed to be
  36. X;;;               frictionless so spin in irrelevant and not accounted for.
  37. X;;;               (See section on limitations.)
  38. X;;;
  39. X;;; NOTES: A simulation is initiated by creating a number of balls and bumpers
  40. X;;;        and and specifying a duration for the simulation.  For each ball,
  41. X;;;        its mass, radius, initial position, and initial velocity must be
  42. X;;;        specified.  For each bumper, the location of its two ends must be
  43. X;;;        specified.  (Bumpers are assumed to have zero width.)
  44. X;;;
  45. X;;;        A sample run might be started as follows:
  46. X;;;        (simulate
  47. X;;;         (list (make-ball 2 1 9 5 -1 -1)
  48. X;;;               (make-ball 4 2 2 5 1 -1))
  49. X;;;         (list (make-bumper 0 0 0 10)
  50. X;;;               (make-bumper 0 0 10 0)
  51. X;;;               (make-bumper 0 10 10 10)
  52. X;;;               (make-bumper 10 0 10 10))
  53. X;;;         30)
  54. X;;;
  55. X;;;        It would create one billiard ball of mass 2 and radius 1 at position
  56. X;;;        (9, 5) with initial velocity (-1, -1) and a second ball of mass 4
  57. X;;;        and radius 2 at position (2, 5) with initial velocity (1, -1).  The
  58. X;;;        table would be a 10X10 square.  (See diagram below)
  59. X;;;
  60. X;;;        +---------------------------+
  61. X;;;        |                           |
  62. X;;;        |                           |
  63. X;;;        |    XXXX                   |
  64. X;;;        |  XXXXXXXX             XX  |
  65. X;;;        |XXXXXX4XXXXX         XXX2XX|
  66. X;;;        |  XXXXXXXX            /XX  |
  67. X;;;        |    XXXX \                 |
  68. X;;;        |                           |
  69. X;;;        |                           |
  70. X;;;        +---------------------------+
  71. X;;;
  72. X;;; LIMITATIONS:  This simulator does not handle 3 body problems correctly.  If
  73. X;;;               3 objects interact at one time, only the interactions of 2 of
  74. X;;;               the bodies will be accounted for.  This can lead to strange
  75. X;;;               effects like balls tunneling through walls and other balls.
  76. X;;;               It is also possible to get balls bouncing inside of each
  77. X;;;               other in this way. 
  78. X;;;           
  79. X
  80. X
  81. X;;MAKE-QUEUE-RECORD returns a queue record with the given next, previous, and
  82. X;;value values
  83. X;;NEXT = The next record pointer
  84. X;;PREV = The previous record pointer
  85. X;;REST = A list of values for any optional fields (this can be used for
  86. X;;       creating structure inheritance)
  87. X(define-macro (make-queue-record next prev . rest)
  88. X  `(vector ,next ,prev ,@rest))
  89. X      
  90. X;;QUEUE-RECORD-NEXT returns the next field of the given queue record
  91. X;;QUEUE-RECORD = The queue record whose next field is to be returned
  92. X(define-macro (queue-record-next queue-record)
  93. X  `(vector-ref ,queue-record 0))
  94. X
  95. X;;SET-QUEUE-RECORD-NEXT! sets the next field of the given queue record
  96. X;;QUEUE-RECORD = The queue record whose next field is to be set
  97. X;;VALUE = The value to which the next field is to be set
  98. X(define-macro (set-queue-record-next! queue-record value)
  99. X  `(vector-set! ,queue-record 0 ,value))
  100. X
  101. X;;QUEUE-RECORD-PREV returns the prev field of the given queue record
  102. X;;QUEUE-RECORD = The queue record whose prev field is to be returned
  103. X(define-macro (queue-record-prev queue-record)
  104. X  `(vector-ref ,queue-record 1))
  105. X
  106. X;;SET-QUEUE-RECORD-PREV! sets the prev field of the given queue record
  107. X;;QUEUE-RECORD = The queue record whose prev field is to be set
  108. X;;VALUE = The value to which the prev field is to be set
  109. X(define-macro (set-queue-record-prev! queue-record value)
  110. X  `(vector-set! ,queue-record 1 ,value))
  111. X
  112. X;;QUEUE-RECORD-LEN returns the length of a queue record which has no optional
  113. X;;fields 
  114. X(define-macro (queue-record-len) 2)
  115. X
  116. X;;QUEUE-HEAD returns a dummy record at the end of the queue with the record
  117. X;;with the smallest key.
  118. X;;QUEUE = the queue whose head record is to be returned
  119. X(define-macro (queue-head queue)
  120. X  `(vector-ref ,queue 0))
  121. X
  122. X;;QUEUE-TAIL returns a dummy record at the end of the queue with the record
  123. X;;with the largest key.
  124. X;;QUEUE = the queue whose tail record is to be returned
  125. X(define-macro (queue-tail queue)
  126. X  `(vector-ref ,queue 1))
  127. X
  128. X;;QUEUE-<? returns the less-than comparitor to be used in sorting
  129. X;;records into the queue
  130. X;;QUEUE = The queue whose comparitor is to be returned
  131. X(define-macro (queue-<? queue)
  132. X  `(vector-ref ,queue 2))
  133. X
  134. X
  135. X;;MAKE-SORTED-QUEUE returns a queue object.  A queue header is a vector which
  136. X;;contains a head pointer, a tail pointer, and a less-than comparitor. 
  137. X;;QUEUE-<? = A predicate for sorting queue items
  138. X(define (make-sorted-queue queue-<?)
  139. X  (let ((queue
  140. X     (vector
  141. X      (make-queue-record        ;The queue head record has no initial
  142. X       '()                ;next, previous, or value values
  143. X       '())
  144. X      (make-queue-record        ;The queue tail record has no intial
  145. X       '()                ;next, previous, or value values
  146. X       '())
  147. X      queue-<?)))
  148. X    (set-queue-record-next!
  149. X     (queue-head queue)
  150. X     (queue-tail queue))
  151. X    (set-queue-record-prev!
  152. X     (queue-tail queue)
  153. X     (queue-head queue))
  154. X    queue))
  155. X
  156. X;;MAKE-EVENT-QUEUE-RECORD returns an event queue record with the given next,
  157. X;;previous, object, and collision-time values
  158. X;;NEXT = The next record pointer
  159. X;;PREV = The previous record pointer
  160. X;;OBJECT = The simulation object associated with this record
  161. X;;COLLISION-TIME = The collision time for this object
  162. X(define-macro (make-event-queue-record next prev object collision-time)
  163. X  `(make-queue-record ,next ,prev ,object ,collision-time))
  164. X
  165. X;;EVENT-QUEUE-RECORD-OBJECT returns the object associated with the given record
  166. X;;QUEUE-RECORD = The queue record whose object field is to be returned
  167. X(define-macro (event-queue-record-object queue-record)
  168. X  `(vector-ref ,queue-record ,(queue-record-len)))
  169. X
  170. X;;EVENT-QUEUE-COLLISION-TIME returns the collision time associated with the
  171. X;;given queue record
  172. X;;QUEUE-RECORD = The queue record whose collision time field is to be returned
  173. X(define-macro (event-queue-record-collision-time queue-record)
  174. X  `(vector-ref ,queue-record ,(1+ (queue-record-len))))
  175. X
  176. X;;SET-EVENT-QUEUE-COLLISION-TIME! sets the collision time associated with the
  177. X;;given queue record
  178. X;;QUEUE-RECORD = The queue record whose collision time field is to be returned
  179. X;;VALUE = The value to which it is to be set
  180. X(define-macro (set-event-queue-record-collision-time! queue-record value)
  181. X  `(vector-set! ,queue-record ,(1+ (queue-record-len)) ,value))
  182. X
  183. X
  184. X;;QUEUE-INSERT inserts the given record in the given queue based on its value
  185. X;;QUEUE = The queue into which the record is to be inserted
  186. X;;QUEUE-RECORD = The record to be inserted in the queue
  187. X(define (queue-insert queue queue-record)
  188. X  (define (actual-insert insert-record next-record)
  189. X    (if (or                ;If the insert position has been found
  190. X     (eq? next-record        ;or the end on the queue has been 
  191. X          (queue-tail queue))    ;reached
  192. X     ((queue-<? queue)        
  193. X      insert-record
  194. X      next-record))
  195. X    (sequence            ;Link the insert record into the queue
  196. X      (set-queue-record-next!    ;just prior to next-record
  197. X       (queue-record-prev
  198. X        next-record)
  199. X       insert-record)
  200. X      (set-queue-record-prev!
  201. X       insert-record
  202. X       (queue-record-prev
  203. X        next-record))
  204. X      (set-queue-record-next!
  205. X       insert-record
  206. X       next-record)
  207. X      (set-queue-record-prev!
  208. X       next-record
  209. X       insert-record))
  210. X    (actual-insert            ;Else, continue searching for the 
  211. X     insert-record            ;insert position
  212. X     (queue-record-next
  213. X      next-record))))
  214. X  (actual-insert            ;Search for the correct position to 
  215. X   queue-record                ;perform the insert starting at the
  216. X   (queue-record-next            ;queue head and perform the insert 
  217. X    (queue-head queue))))        ;once this position has been found
  218. X     
  219. X;;QUEUE-REMOVE removes the given queue record from its queue
  220. X;;QUEUE-RECORD = The record to be removed from the queue
  221. X(define (queue-remove queue-record)
  222. X  (set-queue-record-next!
  223. X   (queue-record-prev
  224. X    queue-record)
  225. X   (queue-record-next
  226. X    queue-record))
  227. X  (set-queue-record-prev!
  228. X   (queue-record-next
  229. X    queue-record)
  230. X   (queue-record-prev
  231. X    queue-record)))
  232. X
  233. X;;QUEUE-SMALLEST returns the queue record with the smallest key on the given
  234. X;;queue 
  235. X;;QUEUE = The queue from which the smallest record is to be extracted
  236. X(define (queue-smallest queue)
  237. X  (queue-record-next
  238. X   (queue-head queue)))
  239. X
  240. X
  241. X;;CLEAR-QUEUE! clears the given queue by destructively removing all the records
  242. X;;QUEUE = The queue to be cleared
  243. X(define (clear-queue queue)
  244. X  (set-queue-record-next!
  245. X   (queue-head queue)
  246. X   (queue-tail queue))
  247. X  (set-queue-record-prev!
  248. X   (queue-tail queue)
  249. X   (queue-head queue)))
  250. X
  251. X;;EMPTY-QUEUE? returns true if the given queue is empty
  252. X;;QUEUE = The queue to be tested for emptiness
  253. X(define (empty-queue? queue)
  254. X  (eq? (queue-record-next
  255. X    (queue-head queue))
  256. X       (queue-tail queue)))
  257. X
  258. X
  259. X;;MAKE-SIMULATION-OBJECT returns a simulation object containing the given
  260. X;;fields 
  261. X;;COLLISION-PROCEDURE = A function for processing information about a potential
  262. X;;                      collision between this object and some ball
  263. X;;REST = A list of values for any optional fields (this can be used for
  264. X;;       creating structure inheritance)
  265. X(define-macro (make-simulation-object collision-procedure . rest)
  266. X  `(vector ,collision-procedure ,@rest))
  267. X
  268. X;;SIMULATION-OBJECT-COLLLISION-PROCEDURE returns the collision procedure for
  269. X;;the given simulation object
  270. X;;OBJECT = The object whose collision procedure is to be returned
  271. X(define-macro (simulation-object-collision-procedure object)
  272. X  `(vector-ref ,object 0))
  273. X
  274. X;;SIMULATION-OBJECT-LEN returns the length of a simulation object which has no
  275. X;;optional fields
  276. X(define-macro (simulation-object-len) 1)
  277. X
  278. X
  279. X;;ACTUAL-MAKE-BALL returns a ball object
  280. X;;BALL-NUMBER = An index into the ball vector for this ball
  281. X;;MASS = The ball's mass
  282. X;;RADIUS = The ball's radius
  283. X;;PX = The x-coordinate of the ball's initial position
  284. X;;PY = The y-coordinate of the ball's initial position
  285. X;;VX = The x-coordinate of the ball's initial velocity
  286. X;;VY = The y-coordinate of the ball's initial velocity
  287. X(define-macro (actual-make-ball ball-number mass radius px py vx vy)
  288. X  `(make-simulation-object
  289. X    ball-collision-procedure        ;The collision procedure for a ball
  290. X    ,ball-number
  291. X    ,mass
  292. X    ,radius
  293. X    (make-sorted-queue            ;The event queue
  294. X     collision-time-<?)
  295. X    0                    ;Time of last collision
  296. X    ,px                    ;Position of last collision
  297. X    ,py                    ; "
  298. X    ,vx                    ;Velocity following last colliosion
  299. X    ,vy                    ; "
  300. X    '()                    ;No vector of queue records for ball's
  301. X                    ;with smaller numbers  
  302. X    '()                    ;No vector of queue records for bumpers
  303. X    '()                    ;No list of balls with larger numbers
  304. X    '()))                ;No global event queue record, yet
  305. X  
  306. X(define (make-ball mass radius px py vx vy)
  307. X  (actual-make-ball '() mass radius px py vx vy))
  308. X
  309. X;;BALL-NUMBER returns the index of the given ball
  310. X;;BALL = The ball whose index is to be returned
  311. X(define-macro (ball-number ball)
  312. X  `(vector-ref ,ball ,(simulation-object-len)))
  313. X
  314. X;;SET-BALL-NUMBER! set the index of the given ball to the given value
  315. X;;BALL = The ball whose index is to be set
  316. X;;VALUE = The value to which it is to be set
  317. X(define-macro (set-ball-number! ball value)
  318. X  `(vector-set! ,ball ,(simulation-object-len) ,value))
  319. X
  320. X;;BALL-MASS returns the mass of the given ball
  321. X;;BALL = The ball whose mass is to be returned
  322. X(define-macro (ball-mass ball)
  323. X  `(vector-ref ,ball ,(+ (simulation-object-len) 1)))
  324. X
  325. X;;BALL-RADIUS returns the radius of the given ball
  326. X;;BALL = The ball whose radius is to be returned
  327. X(define-macro (ball-radius ball)
  328. X  `(vector-ref ,ball ,(+ (simulation-object-len) 2)))
  329. X
  330. X;;BALL-EVENT-QUEUE returns the sort queue of collision events for the given
  331. X;;ball
  332. X;;BALL = The ball whose event is to be returned
  333. X(define-macro (ball-event-queue ball)
  334. X  `(vector-ref ,ball ,(+ (simulation-object-len) 3)))
  335. X
  336. X;;BALL-COLLISION-TIME returns the time of the last collision for the given ball
  337. X;;BALL = The ball whose collision time is to be returned
  338. X(define-macro (ball-collision-time ball)
  339. X  `(vector-ref ,ball ,(+ (simulation-object-len) 4)))
  340. X
  341. X
  342. X;;SET-BALL-COLLISION-TIME! sets the time of the last collision for the given
  343. X;;ball 
  344. X;;BALL = The ball whose collision time is to be set
  345. X;;VALUE = The value to which the ball's collision time is to be set
  346. X(define-macro (set-ball-collision-time! ball value)
  347. X  `(vector-set! ,ball ,(+ (simulation-object-len) 4) ,value))
  348. X
  349. X;;BALL-COLLISION-X-POSITION returns the x-coordinate of the position  of the
  350. X;;last collision for the given ball 
  351. X;;BALL = The ball whose collision position is to be returned
  352. X(define-macro (ball-collision-x-position ball)
  353. X  `(vector-ref ,ball ,(+ (simulation-object-len) 5)))
  354. X
  355. X;;SET-BALL-COLLISION-X-POSITION! sets the x-coordinate of the position of the
  356. X;;last collision for the given ball 
  357. X;;BALL = The ball whose collision position is to be set
  358. X;;VALUE = The value to which the ball's collision position is to be set
  359. X(define-macro (set-ball-collision-x-position! ball value)
  360. X  `(vector-set! ,ball ,(+ (simulation-object-len) 5) ,value))
  361. X
  362. X;;BALL-COLLISION-Y-POSITION returns the y-coordinate of the position  of the
  363. X;;last collision for the given ball 
  364. X;;BALL = The ball whose collision position is to be returned
  365. X(define-macro (ball-collision-y-position ball)
  366. X  `(vector-ref ,ball ,(+ (simulation-object-len) 6)))
  367. X
  368. X;;SET-BALL-COLLISION-Y-POSITION! sets the y-coordinate of the position of the
  369. X;;last collision for the given ball 
  370. X;;BALL = The ball whose collision position is to be set
  371. X;;VALUE = The value to which the ball's collision position is to be set
  372. X(define-macro (set-ball-collision-y-position! ball value)
  373. X  `(vector-set! ,ball ,(+ (simulation-object-len) 6) ,value))
  374. X
  375. X;;BALL-X-VELOCITY returns the x-coordinate of the velocity of the given ball
  376. X;;following its last collision
  377. X;;BALL = The ball whose velocity is to be returned
  378. X(define-macro (ball-x-velocity ball)
  379. X  `(vector-ref ,ball ,(+ (simulation-object-len) 7)))
  380. X
  381. X;;SET-BALL-X-VELOCITY! sets the x-coordinate of the velocity of the given ball
  382. X;;BALL = The ball whose velocity is to be set
  383. X;;VALUE = The value to which the ball's velocity is to be set
  384. X(define-macro (set-ball-x-velocity! ball value)
  385. X  `(vector-set! ,ball ,(+ (simulation-object-len) 7) ,value))
  386. X
  387. X;;BALL-Y-VELOCITY returns the y-coordinate of the velocity  of the given ball
  388. X;;following its last collision
  389. X;;BALL = The ball whose velocity is to be returned
  390. X(define-macro (ball-y-velocity ball)
  391. X  `(vector-ref ,ball ,(+ (simulation-object-len) 8)))
  392. X
  393. X;;SET-BALL-Y-VELOCITY! sets the y-coordinate of the velocity of the given ball
  394. X;;BALL = The ball whose velocity is to be set
  395. X;;VALUE = The value to which the ball's velocity is to be set
  396. X(define-macro (set-ball-y-velocity! ball value)
  397. X  `(vector-set! ,ball ,(+ (simulation-object-len) 8) ,value))
  398. X
  399. X
  400. X;;BALL-BALL-VECTOR returns the vector of queue records for balls with smaller
  401. X;;ball numbers
  402. X;;BALL = The ball whose ball vector is to be returned
  403. X(define-macro (ball-ball-vector ball)
  404. X  `(vector-ref ,ball ,(+ (simulation-object-len) 9)))
  405. X
  406. X;;SET-BALL-BALL-VECTOR! sets the vector of queue records for balls with smaller
  407. X;;ball numbers
  408. X;;BALL = The ball whose ball vector is to be set
  409. X;;VALUE = The vector to which the field is to be set
  410. X(define-macro (set-ball-ball-vector! ball value)
  411. X  `(vector-set! ,ball ,(+ (simulation-object-len) 9) ,value))
  412. X
  413. X;;BALL-BUMPER-VECTOR returns the vector of queue records for bumpers
  414. X;;BALL = The ball whose bumper vector is to be returned
  415. X(define-macro (ball-bumper-vector ball)
  416. X  `(vector-ref ,ball ,(+ (simulation-object-len) 10)))
  417. X
  418. X;;SET-BALL-BUMPER-VECTOR! sets the vector of queue records for bumpers
  419. X;;BALL = The ball whose bumper vector is to be set
  420. X;;VALUE = The vector to which the field is to be set
  421. X(define-macro (set-ball-bumper-vector! ball value)
  422. X  `(vector-set! ,ball ,(+ (simulation-object-len) 10) ,value))
  423. X
  424. X;;BALL-BALL-LIST returns a list of balls with larger ball numbers than the
  425. X;;given ball
  426. X;;BALL = The ball whose ball list is to be returned
  427. X(define-macro (ball-ball-list ball)
  428. X  `(vector-ref ,ball ,(+ (simulation-object-len) 11)))
  429. X
  430. X;;SET-BALL-BALL-LIST! sets the list of balls with larger ball numbers than the
  431. X;;given ball
  432. X;;BALL = The ball whose ball list is to be set
  433. X;;VALUE = The value to which the ball list is to be set
  434. X(define-macro (set-ball-ball-list! ball value)
  435. X  `(vector-set! ,ball ,(+ (simulation-object-len) 11) ,value))
  436. X
  437. X;;BALL-GLOBAL-EVENT-QUEUE-RECORD returns the global event queue record for the
  438. X;;given ball
  439. X;;BALL = The ball whose global event queue record is to be returned
  440. X(define-macro (ball-global-event-queue-record ball)
  441. X  `(vector-ref ,ball ,(+ (simulation-object-len) 12)))
  442. X
  443. X;;SET-BALL-GLOBAL-EVENT-QUEUE-RECORD! set the global event queue record for the
  444. X;;given ball to the given value
  445. X;;BALL = The ball whose global event queue record is to be set
  446. X;;VALUE = The value to which the global event queue record field is to be set
  447. X(define-macro (set-ball-global-event-queue-record! ball value)
  448. X  `(vector-set! ,ball ,(+ (simulation-object-len) 12) ,value))
  449. X
  450. X
  451. X
  452. X;;ACTUAL-MAKE-BUMPER returns a bumper object
  453. X;;BUMPER-NUMBER = An index into the bumper vector for this bumper
  454. X;;X1 = The x-coordiante of one end of the bumper
  455. X;;Y1 = The y-coordiante of one end of the bumper
  456. X;;X2 = The x-coordiante of the other end of the bumper
  457. X;;Y2 = The y-coordiante of the other end of the bumper
  458. X(define-macro (actual-make-bumper bumper-number x1 y1 x2 y2)
  459. X  `(make-simulation-object
  460. X    bumper-collision-procedure        ;The collision procedure for a bumper
  461. X    ,bumper-number
  462. X    ,x1                    ;The bumper endpoints
  463. X    ,y1
  464. X    ,x2
  465. X    ,y2))
  466. X
  467. X(define (make-bumper x1 y1 x2 y2)
  468. X  (actual-make-bumper '() x1 y1 x2 y2))
  469. X
  470. X;;BUMPER-NUMBER returns the index of the given bumper
  471. X;;BUMPER = The bumper whose index is to be returned
  472. X(define-macro (bumper-number bumper)
  473. X  `(vector-ref ,bumper ,(simulation-object-len)))
  474. X
  475. X;;SET-BUMPER-NUMBER! set the index of the given bumper to the given value
  476. X;;BUMPER = The bumper whose index is to be set
  477. X;;VALUE = The value to which it is to be set
  478. X(define-macro (set-bumper-number! bumper value)
  479. X  `(vector-set! ,bumper ,(simulation-object-len) ,value))
  480. X
  481. X;;BUMPER-X1 returns the x-coordinate of one end of the given bumber
  482. X;;BUMPER = the bumper whose x-coordinate is to be returned
  483. X(define-macro (bumper-x1 bumper)
  484. X  `(vector-ref ,bumper ,(1+ (simulation-object-len))))
  485. X
  486. X;;SET-BUMPER-X1! sets the x-coordinate of one end of the given bumber
  487. X;;BUMPER = the bumper whose x-coordinate is to be set
  488. X;;VALUE = The value to which the bumpers x-coordinate is to be set
  489. X(define-macro (set-bumper-x1! bumper value)
  490. X  `(vector-set! ,bumper ,(1+ (simulation-object-len)) ,value))
  491. X
  492. X;;BUMPER-Y1 returns the y-coordinate of one end of the given bumber
  493. X;;BUMPER = the bumper whose y-coordinate is to be returned
  494. X(define-macro (bumper-y1 bumper)
  495. X  `(vector-ref ,bumper ,(+ (simulation-object-len) 2)))
  496. X
  497. X;;SET-BUMPER-Y1! sets the y-coordinate of one end of the given bumber
  498. X;;BUMPER = the bumper whose y-coordinate is to be set
  499. X;;VALUE = The value to which the bumpers y-coordinate is to be set
  500. X(define-macro (set-bumper-y1! bumper value)
  501. X  `(vector-set! ,bumper ,(+ (simulation-object-len) 2) ,value))
  502. X
  503. X;;BUMPER-X2 returns the x-coordinate of the other end of the given bumber
  504. X;;BUMPER = the bumper whose x-coordinate is to be returned
  505. X(define-macro (bumper-x2 bumper)
  506. X  `(vector-ref ,bumper ,(+ (simulation-object-len) 3)))
  507. X
  508. X;;SET-BUMPER-X2! sets the x-coordinate of the other end of the given bumber
  509. X;;BUMPER = the bumper whose x-coordinate is to be set
  510. X;;VALUE = The value to which the bumpers x-coordinate is to be set
  511. X(define-macro (set-bumper-x2! bumper value)
  512. X  `(vector-set! ,bumper ,(+ (simulation-object-len) 3) ,value))
  513. X
  514. X
  515. X;;BUMPER-Y2 returns the y-coordinate of the other end of the given bumber
  516. X;;BUMPER = the bumper whose y-coordinate is to be returned
  517. X(define-macro (bumper-y2 bumper)
  518. X  `(vector-ref ,bumper ,(+ (simulation-object-len) 4)))
  519. X
  520. X;;SET-BUMPER-Y2! sets the y-coordinate of the other end of the given bumber
  521. X;;BUMPER = the bumper whose y-coordinate is to be set
  522. X;;VALUE = The value to which the bumpers y-coordinate is to be set
  523. X(define-macro (set-bumper-y2! bumper value)
  524. X  `(vector-set! ,bumper ,(+ (simulation-object-len) 4) ,value))
  525. X
  526. X;;COLLISION-TIME-<? is a predicate which returns true if the first event queueu
  527. X;;record represents a collision that will take place at an earlier time than
  528. X;;the one for the second event queue record
  529. X;;EVENT-QUEUE-RECORD1 = The first event queue record
  530. X;;EVENT-QUEUE-RECORD2 = The second event queue record
  531. X(define (collision-time-<? event-queue-record1 event-queue-record2)
  532. X  (time-<?
  533. X   (event-queue-record-collision-time
  534. X    event-queue-record1)
  535. X   (event-queue-record-collision-time
  536. X    event-queue-record2)))
  537. X
  538. X;;TIME-<? is a predicate which returns true if the first time is smaller than
  539. X;;the second.  '() represents a time infinitly large.
  540. X(define (time-<? time1 time2)
  541. X  (if (null? time1)
  542. X      #f
  543. X      (if (null? time2)
  544. X      #t
  545. X      (< time1 time2))))
  546. X
  547. X;;SQUARE returns the square of its argument
  548. X(define (square x)
  549. X  (* x x))
  550. X
  551. X
  552. X;;BALL-BALL-COLLISION-TIME returns the time at which the two given balls would
  553. X;;collide if neither interacted with any other objects, '() if never.  This
  554. X;;calculation is performed by setting the distance between the balls to the sum
  555. X;;of their radi and solving for the contact time.
  556. X;;BALL1 = The first ball
  557. X;;BALL2 = The second ball
  558. X(define (ball-ball-collision-time ball1 ball2)
  559. X  (let ((delta-x-velocity        ;Cache the difference in the ball's
  560. X     ( - (ball-x-velocity ball2)    ;velocities,
  561. X         (ball-x-velocity ball1)))
  562. X    (delta-y-velocity
  563. X     ( - (ball-y-velocity ball2)    
  564. X         (ball-y-velocity ball1)))
  565. X    (radius-sum            ;the sum of their radi,
  566. X     (+ (ball-radius ball1)
  567. X        (ball-radius ball2)))
  568. X    (alpha-x            ;and common subexpressions in the time
  569. X     (-                ;equation
  570. X      (- (ball-collision-x-position
  571. X          ball2)
  572. X         (ball-collision-x-position
  573. X          ball1))
  574. X      (-
  575. X       (* (ball-x-velocity ball2)    
  576. X          (ball-collision-time
  577. X           ball2))
  578. X       (* (ball-x-velocity ball1)    
  579. X          (ball-collision-time
  580. X           ball1)))))
  581. X    (alpha-y
  582. X     (-
  583. X      (- (ball-collision-y-position
  584. X          ball2)
  585. X         (ball-collision-y-position
  586. X          ball1))
  587. X      (-
  588. X       (* (ball-y-velocity ball2)    
  589. X          (ball-collision-time
  590. X           ball2))
  591. X       (* (ball-y-velocity ball1)    
  592. X          (ball-collision-time
  593. X           ball1))))))
  594. X    (let* ((delta-velocity-magnitude-squared
  595. X        (+ (square
  596. X        delta-x-velocity)
  597. X           (square        
  598. X        delta-y-velocity)))
  599. X       (discriminant
  600. X        (- (* (square radius-sum)
  601. X          delta-velocity-magnitude-squared)
  602. X           (square
  603. X        (- (* delta-y-velocity
  604. X              alpha-x)
  605. X           (* delta-x-velocity
  606. X              alpha-y))))))
  607. X
  608. X
  609. X      (if (or (negative? discriminant)    ;If the balls don't colloide:
  610. X          (zero?
  611. X           delta-velocity-magnitude-squared))
  612. X      '()                ;Return infinity
  613. X      (let ((time            ;Else, calculate the collision time
  614. X         (/
  615. X          (- 0
  616. X             (+ (sqrt discriminant)
  617. X            (+
  618. X             (* delta-x-velocity
  619. X                alpha-x)
  620. X             (* delta-y-velocity
  621. X                alpha-y))))
  622. X          (+ (square
  623. X              delta-x-velocity)
  624. X             (square
  625. X              delta-y-velocity)))))
  626. X        (if (and            ;If the balls collide in the future:
  627. X         (time-<?
  628. X          (ball-collision-time
  629. X           ball1)
  630. X          time)
  631. X         (time-<?
  632. X          (ball-collision-time
  633. X           ball2)
  634. X          time))
  635. X        time            ;Return the collision time
  636. X        '()))))))        ;Else, return that they never collide
  637. X
  638. X;;BALL-BUMPER-COLLISION-TIME returns the time at which the given ball would
  639. X;;collide with the given bumper if the ball didn't interacted with any other
  640. X;;objects, '() if never.  This is done by first calculating the time at which
  641. X;;the ball would collide with a bumper of infinite length and then checking if
  642. X;;the collision position represents a portion of the actual bumper.
  643. X;;BALL = The ball
  644. X;;BUMPER = The bumper
  645. X(define (ball-bumper-collision-time ball bumper)
  646. X  (let ((delta-x-bumper            ;Collision time with the bumper of 
  647. X     (- (bumper-x2 bumper)        ;infinite extent is calculated by 
  648. X        (bumper-x1 bumper)))    ;setting the distance between the ball
  649. X    (delta-y-bumper            ;and the bumper to be the radius of the
  650. X     (- (bumper-y2 bumper)        ;ball and solving for the time.  The
  651. X        (bumper-y1 bumper))))    ;distance is calculated by |aXb|/|a|,
  652. X    (let ((bumper-length-squared    ;where 'a' is the vector from one end
  653. X       (+ (square delta-x-bumper)    ;of the bumper to the other and 'b' is
  654. X          (square delta-y-bumper)))    ;the vector from the first end of the 
  655. X      (denominator            ;bumper to the center of the ball
  656. X       (- (* (ball-y-velocity ball)
  657. X         delta-x-bumper)
  658. X          (* (ball-x-velocity ball)
  659. X         delta-y-bumper))))
  660. X      (if (zero? denominator)        ;If the ball's motion is parallel to
  661. X                    ;the bumper:
  662. X      '()                ;Return infinity
  663. X      (let ((delta-t        ;Calculate the collision time
  664. X         (-
  665. X          (/
  666. X           (+
  667. X            (*
  668. X             (-    (ball-collision-x-position
  669. X             ball)
  670. X            (bumper-x1 bumper))
  671. X             delta-y-bumper)
  672. X            (*
  673. X             (- (ball-collision-y-position
  674. X             ball)
  675. X            (bumper-y1 bumper))
  676. X             delta-x-bumper))
  677. X           denominator)
  678. X          (/
  679. X           (* (ball-radius
  680. X               ball)
  681. X              (sqrt
  682. X               bumper-length-squared))
  683. X           (abs denominator)))))
  684. X        (if (not (positive?        ;If the ball is moving away from the
  685. X              delta-t))        ;bumper:
  686. X        '()            ;Return infinity
  687. X
  688. X
  689. X        (let ((ball-x-contact    ;Whether the ball contacts the actual
  690. X               (+ (ball-collision-x-position ;bumper of limited extent
  691. X               ball)    ;will be determined by comparing |b.a|
  692. X              (* (ball-x-velocity ;with |a|^2
  693. X                  ball)
  694. X                 delta-t)))
  695. X              (ball-y-contact
  696. X               (+ (ball-collision-y-position
  697. X               ball)
  698. X              (* (ball-y-velocity
  699. X                  ball)
  700. X                 delta-t))))
  701. X          (let ((delta-x-ball
  702. X             (- ball-x-contact
  703. X                (bumper-x1
  704. X                 bumper)))
  705. X            (delta-y-ball
  706. X             (- ball-y-contact
  707. X                (bumper-y1
  708. X                 bumper))))
  709. X            (let ((dot-product
  710. X               (+
  711. X                (* delta-x-ball
  712. X                   delta-x-bumper)
  713. X                (* delta-y-ball
  714. X                   delta-y-bumper))))
  715. X              (if (or        ;If the ball misses the bumper on 
  716. X               (negative?    ;either end:
  717. X                dot-product)
  718. X               (> dot-product
  719. X                  bumper-length-squared))
  720. X              '()        ;Return infinity
  721. X              (+ delta-t    ;Else, return the contact time
  722. X                 (ball-collision-time
  723. X                  ball))))))))))))
  724. X                   
  725. X
  726. X;;BALL-COLLISION-PROCEDURE calculates the new velocities of the given balls
  727. X;;based on their collision at the given time.  Also, tells all other balls
  728. X;;about the new trajectories of these balls so they can update their event
  729. X;;queues 
  730. X;;BALL1 = The first ball
  731. X;;BALL2 = The second ball
  732. X;;COLLISION-TIME = The collision time
  733. X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
  734. X(define (ball-collision-procedure ball1 ball2 collision-time
  735. X                  global-event-queue)
  736. X  (queue-remove                ;Remove the earliest event associated
  737. X   (ball-global-event-queue-record    ;with each ball from the global event 
  738. X    ball1))                ;queue
  739. X  (queue-remove
  740. X   (ball-global-event-queue-record
  741. X    ball2))
  742. X  (let ((ball1-collision-x-position    ;Calculate the positions of both balls
  743. X     (+ (ball-collision-x-position    ;when they collide
  744. X         ball1)
  745. X        (* (ball-x-velocity
  746. X        ball1)
  747. X           (- collision-time
  748. X          (ball-collision-time
  749. X           ball1)))))
  750. X    (ball1-collision-y-position
  751. X     (+ (ball-collision-y-position
  752. X         ball1)
  753. X        (* (ball-y-velocity
  754. X        ball1)
  755. X           (- collision-time
  756. X          (ball-collision-time
  757. X           ball1)))))
  758. X    (ball2-collision-x-position
  759. X     (+ (ball-collision-x-position
  760. X         ball2)
  761. X        (* (ball-x-velocity
  762. X        ball2)
  763. X           (- collision-time
  764. X          (ball-collision-time
  765. X           ball2)))))
  766. X    (ball2-collision-y-position
  767. X     (+ (ball-collision-y-position
  768. X         ball2)
  769. X        (* (ball-y-velocity
  770. X        ball2)
  771. X           (- collision-time
  772. X          (ball-collision-time
  773. X           ball2))))))
  774. X    (let ((delta-x            ;Calculate the displacements of the
  775. X       (- ball2-collision-x-position ;centers of the two balls
  776. X          ball1-collision-x-position))
  777. X      (delta-y
  778. X       (- ball2-collision-y-position
  779. X          ball1-collision-y-position)))
  780. X
  781. X
  782. X      (let* ((denominator        ;Calculate the angle of the line 
  783. X          (sqrt (+ (square        ;joining the centers at the collision 
  784. X            delta-x)    ;time with the x-axis  (this line is
  785. X               (square        ;the normal to the balls at the
  786. X            delta-y))))    ;collision point)
  787. X         (cos-theta            
  788. X          (/ delta-x denominator))
  789. X         (sin-theta
  790. X          (/ delta-y denominator)))
  791. X      (let ((ball1-old-normal-velocity ;Convert the velocities of the balls
  792. X         (+ (* (ball-x-velocity    ;into the coordinate system defined by 
  793. X            ball1)        ;the normal and tangential lines at 
  794. X               cos-theta)    ;the collision point
  795. X            (* (ball-y-velocity
  796. X            ball1)
  797. X               sin-theta)))
  798. X        (ball1-tang-velocity
  799. X         (- (* (ball-y-velocity
  800. X            ball1)
  801. X               cos-theta)
  802. X            (* (ball-x-velocity
  803. X            ball1)
  804. X               sin-theta)))
  805. X        (ball2-old-normal-velocity
  806. X         (+ (* (ball-x-velocity
  807. X            ball2)
  808. X               cos-theta)
  809. X            (* (ball-y-velocity
  810. X            ball2)
  811. X               sin-theta)))
  812. X        (ball2-tang-velocity
  813. X         (- (* (ball-y-velocity
  814. X            ball2)
  815. X               cos-theta)
  816. X            (* (ball-x-velocity
  817. X            ball2)
  818. X               sin-theta)))
  819. X        (mass1 (ball-mass
  820. X            ball1))
  821. X        (mass2 (ball-mass
  822. X            ball2)))
  823. X        (let ((ball1-new-normal-velocity ;Calculate the new velocities
  824. X           (/            ;following the collision (the 
  825. X            (+            ;tangential velocities are unchanged
  826. X             (*            ;because the balls are assumed to be
  827. X              (* 2        ;frictionless)
  828. X             mass2)
  829. X              ball2-old-normal-velocity)
  830. X             (*
  831. X              (- mass1 mass2)
  832. X              ball1-old-normal-velocity))
  833. X            (+ mass1 mass2)))
  834. X
  835. X
  836. X          (ball2-new-normal-velocity
  837. X           (/
  838. X            (+
  839. X             (*
  840. X              (* 2
  841. X             mass1)
  842. X              ball1-old-normal-velocity)
  843. X             (*
  844. X              (- mass2 mass1)
  845. X              ball2-old-normal-velocity))
  846. X            (+ mass1 mass2))))
  847. X          (set-ball-x-velocity!    ;Store data about the collision in the
  848. X           ball1            ;structure for each ball after 
  849. X           (- (* ball1-new-normal-velocity ;converting the information back
  850. X             cos-theta)        ;to the x,y frame
  851. X          (* ball1-tang-velocity
  852. X             sin-theta)))
  853. X          (set-ball-y-velocity!
  854. X           ball1
  855. X           (+ (* ball1-new-normal-velocity
  856. X             sin-theta)
  857. X          (* ball1-tang-velocity
  858. X             cos-theta)))
  859. X          (set-ball-x-velocity!
  860. X           ball2
  861. X           (- (* ball2-new-normal-velocity
  862. X             cos-theta)
  863. X          (* ball2-tang-velocity
  864. X             sin-theta)))
  865. X          (set-ball-y-velocity!
  866. X           ball2
  867. X           (+ (* ball2-new-normal-velocity
  868. X             sin-theta)
  869. X          (* ball2-tang-velocity
  870. X             cos-theta)))
  871. X          (set-ball-collision-time!
  872. X           ball1
  873. X           collision-time)
  874. X          (set-ball-collision-time!
  875. X           ball2
  876. X           collision-time)
  877. X          (set-ball-collision-x-position!
  878. X           ball1
  879. X           ball1-collision-x-position)
  880. X          (set-ball-collision-y-position!
  881. X           ball1
  882. X           ball1-collision-y-position)
  883. X          (set-ball-collision-x-position!
  884. X           ball2
  885. X           ball2-collision-x-position)
  886. X          (set-ball-collision-y-position!
  887. X           ball2
  888. X           ball2-collision-y-position))))))
  889. X
  890. X
  891. X  (newline)
  892. X  (display "Ball ")
  893. X  (display (ball-number ball1))
  894. X  (display " collides with ball ")
  895. X  (display (ball-number ball2))
  896. X  (display " at time ")
  897. X  (display (ball-collision-time ball1))
  898. X  (newline)
  899. X  (display "   Ball ")
  900. X  (display (ball-number ball1))
  901. X  (display " has a new velocity of ")
  902. X  (display (ball-x-velocity ball1))
  903. X  (display ",")
  904. X  (display (ball-y-velocity ball1))
  905. X  (display " starting at ")
  906. X  (display (ball-collision-x-position ball1))
  907. X  (display ",")
  908. X  (display (ball-collision-y-position ball1))
  909. X  (newline)
  910. X  (display "   Ball ")
  911. X  (display (ball-number ball2))
  912. X  (display " has a new velocity of ")
  913. X  (display (ball-x-velocity ball2))
  914. X  (display ",")
  915. X  (display (ball-y-velocity ball2))
  916. X  (display " starting at ")
  917. X  (display (ball-collision-x-position ball2))
  918. X  (display ",")
  919. X  (display (ball-collision-y-position ball2))
  920. X
  921. X  (recalculate-collisions ball1 global-event-queue)
  922. X  (recalculate-collisions ball2 global-event-queue))
  923. X
  924. X
  925. X;;BUMPER-COLLISION-PROCEDURE calculates the new velocity of the given ball
  926. X;;following its collision with the given bumper at the given time.  Also, tells
  927. X;;other balls about the new trajectory of the given ball so they can update
  928. X;;their event queues.
  929. X;;BALL = The ball
  930. X;;BUMPER = The bumper
  931. X;;COLLISION-TIME = The collision time
  932. X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
  933. X(define (bumper-collision-procedure ball bumper collision-time
  934. X                    global-event-queue)
  935. X  (queue-remove                ;Remove the earliest event associated
  936. X   (ball-global-event-queue-record    ;with the ball from the global event 
  937. X    ball))                ;queue
  938. X  (let ((delta-x-bumper            ;Compute the bumper's delta-x
  939. X     (- (bumper-x2 bumper)
  940. X        (bumper-x1 bumper)))
  941. X    (delta-y-bumper            ;delta-y
  942. X     (- (bumper-y2 bumper)
  943. X        (bumper-y1 bumper))))
  944. X    (let ((bumper-length        ;length
  945. X       (sqrt
  946. X        (+ (square
  947. X        delta-x-bumper)
  948. X           (square
  949. X        delta-y-bumper)))))
  950. X      (let ((cos-theta            ;and cosine and sine of its angle with
  951. X         (/ delta-x-bumper        ;respect to the positive x-axis
  952. X        bumper-length))
  953. X        (sin-theta
  954. X         (/ delta-y-bumper
  955. X        bumper-length))
  956. X        (x-velocity            ;Cache the ball's velocity in the x,y
  957. X         (ball-x-velocity ball))    ;frame
  958. X        (y-velocity
  959. X         (ball-y-velocity ball)))
  960. X    (let ((tang-velocity        ;Calculate the ball's velocity in the
  961. X           (+ (* x-velocity        ;bumper frame
  962. X             cos-theta)
  963. X          (* y-velocity
  964. X             sin-theta)))
  965. X          (normal-velocity
  966. X           (- (* y-velocity
  967. X             cos-theta)
  968. X          (* x-velocity
  969. X             sin-theta))))
  970. X
  971. X
  972. X      (set-ball-collision-x-position! ;Store the collision position
  973. X       ball
  974. X       (+ (ball-collision-x-position
  975. X           ball)
  976. X          (* (- collision-time
  977. X            (ball-collision-time
  978. X             ball))
  979. X         (ball-x-velocity
  980. X          ball))))
  981. X      (set-ball-collision-y-position!
  982. X       ball
  983. X       (+ (ball-collision-y-position
  984. X           ball)
  985. X          (* (- collision-time
  986. X            (ball-collision-time
  987. X             ball))
  988. X         (ball-y-velocity
  989. X          ball))))
  990. X      (set-ball-x-velocity!        ;Calculate the new velocity in the 
  991. X       ball                ;x,y frame based on the fact that 
  992. X       (+ (* tang-velocity        ;tangential velocity is unchanged and
  993. X         cos-theta)        ;the normal velocity is inverted when
  994. X          (* normal-velocity    ;the ball collides with the bumper
  995. X         sin-theta)))
  996. X      (set-ball-y-velocity!
  997. X       ball
  998. X       (- (* tang-velocity
  999. X         sin-theta)
  1000. X          (* normal-velocity
  1001. X         cos-theta)))
  1002. X      (set-ball-collision-time!
  1003. X       ball
  1004. X       collision-time)))))
  1005. X  (newline)
  1006. X  (display "Ball ")
  1007. X  (display (ball-number ball))
  1008. X  (display " collides with bumper ")
  1009. X  (display (bumper-number bumper))
  1010. X  (display " at time ")
  1011. X  (display (ball-collision-time ball))
  1012. X  (newline)
  1013. X  (display "   Ball ")
  1014. X  (display (ball-number ball))
  1015. X  (display " has a new velocity of ")
  1016. X  (display (ball-x-velocity ball))
  1017. X  (display ",")
  1018. X  (display (ball-y-velocity ball))
  1019. X  (display " starting at ")
  1020. X  (display (ball-collision-x-position ball))
  1021. X  (display ",")
  1022. X  (display (ball-collision-y-position ball))
  1023. X
  1024. X  (recalculate-collisions ball global-event-queue))
  1025. X
  1026. X
  1027. X;;RECALCULATE-COLLISIONS removes all old collisions for the given ball from
  1028. X;;all other balls' event queues and calcultes new collisions for these balls
  1029. X;;and places them on the event queues.  Also, updates the global event queue if
  1030. X;;the recalculation of the collision effects the earliest collision for any
  1031. X;;other balls.
  1032. X;;BALL = The ball whose collisions are being recalculated
  1033. X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
  1034. X(define (recalculate-collisions ball global-event-queue)
  1035. X  (clear-queue (ball-event-queue    ;Clear the queue of events for this 
  1036. X        ball))            ;ball as they have all changed
  1037. X  (let ((event-queue            ;Calculate all ball collision events
  1038. X     (ball-event-queue ball)))    ;with balls of lower number
  1039. X    (let ((ball-vector
  1040. X       (ball-ball-vector ball)))
  1041. X      (do ((i (-1+ (ball-number ball))
  1042. X          (-1+ i)))
  1043. X      ((negative? i))
  1044. X    (let ((ball2-queue-record
  1045. X           (vector-ref
  1046. X        ball-vector
  1047. X        i)))
  1048. X      (set-event-queue-record-collision-time!
  1049. X       ball2-queue-record
  1050. X       (ball-ball-collision-time
  1051. X        ball
  1052. X        (event-queue-record-object
  1053. X         ball2-queue-record)))
  1054. X      (queue-insert
  1055. X       event-queue
  1056. X       ball2-queue-record))))
  1057. X    (let ((bumper-vector        ;Calculate all bumper collision events
  1058. X       (ball-bumper-vector ball)))
  1059. X      (do ((i (-1+ (vector-length
  1060. X            bumper-vector))
  1061. X          (-1+ i)))
  1062. X      ((negative? i))
  1063. X    (let ((bumper-queue-record
  1064. X           (vector-ref
  1065. X        bumper-vector
  1066. X        i)))
  1067. X      (set-event-queue-record-collision-time!
  1068. X       bumper-queue-record
  1069. X       (ball-bumper-collision-time
  1070. X        ball
  1071. X        (event-queue-record-object
  1072. X         bumper-queue-record)))
  1073. X      (queue-insert
  1074. X       event-queue
  1075. X       bumper-queue-record))))
  1076. X
  1077. X
  1078. X    (let ((global-queue-record        ;Get the global event queue record 
  1079. X       (ball-global-event-queue-record ;for this ball
  1080. X        ball)))
  1081. X      (set-event-queue-record-collision-time! ;Set the new earliest event time
  1082. X       global-queue-record        ;for this ball
  1083. X       (if (empty-queue? event-queue)
  1084. X       '()
  1085. X       (event-queue-record-collision-time
  1086. X        (queue-smallest event-queue))))
  1087. X      (queue-insert            ;Enqueue on the global event queue
  1088. X       global-event-queue        ;the earliest event between this ball
  1089. X       global-queue-record)))        ;and any ball of lower number or any
  1090. X                    ;bumper
  1091. X  (for-each                ;For each ball on the ball list:
  1092. X   (lambda (ball2)
  1093. X     (let ((ball2-event-queue
  1094. X        (ball-event-queue ball2)))
  1095. X       (let ((alter-global-event-queue?    ;Set flag to update global event queue 
  1096. X          (and            ;if the earliest event for ball2 was
  1097. X           (not (empty-queue?    ;with the deflected ball
  1098. X             ball2-event-queue))
  1099. X           (eq? ball
  1100. X            (event-queue-record-object
  1101. X             (queue-smallest
  1102. X              ball2-event-queue)))))
  1103. X         (ball-event-queue-record    ;Get the queue record for the deflected
  1104. X          (vector-ref        ;ball for this ball
  1105. X           (ball-ball-vector
  1106. X        ball2)
  1107. X           (ball-number ball))))
  1108. X     (queue-remove            ;Remove the queue record for the 
  1109. X      ball-event-queue-record)    ;deflected ball
  1110. X     (set-event-queue-record-collision-time! ;Recalculate the collision 
  1111. X      ball-event-queue-record    ;time for this ball and the deflected
  1112. X      (ball-ball-collision-time    ;ball
  1113. X       ball
  1114. X       ball2))
  1115. X     (queue-insert            ;Enqueue the new collision event
  1116. X      ball2-event-queue
  1117. X      ball-event-queue-record)
  1118. X     (if (or alter-global-event-queue? ;If the earliest collision event for
  1119. X         (eq? ball        ;this ball has changed:
  1120. X              (event-queue-record-object
  1121. X               (queue-smallest
  1122. X            ball2-event-queue))))
  1123. X         (let ((queue-record    ;Remove the old event from the global
  1124. X            (ball-global-event-queue-record ;event queue and replace it
  1125. X             ball2)))        ;with the new event
  1126. X           (set-event-queue-record-collision-time! 
  1127. X        queue-record
  1128. X        (event-queue-record-collision-time
  1129. X         (queue-smallest
  1130. X          ball2-event-queue)))
  1131. X           (queue-remove
  1132. X        queue-record)
  1133. X           (queue-insert
  1134. X        global-event-queue
  1135. X        queue-record))))))
  1136. X   (ball-ball-list ball)))
  1137. X       
  1138. X
  1139. X;;SIMULATE performs the billiard ball simulation for the given ball list and
  1140. X;;bumper list until the specified time.  
  1141. X;;BALL-LIST = A list of balls
  1142. X;;BUMPER-LIST = A list of bumpers
  1143. X;;END-TIME = The time at which the simulation is to terminate
  1144. X(define (simulate ball-list bumper-list end-time)
  1145. X  (let ((num-of-balls            ;Cache the number of balls and bumpers
  1146. X     (length ball-list))
  1147. X    (num-of-bumpers
  1148. X     (length bumper-list))
  1149. X    (global-event-queue        ;Build the global event queue
  1150. X     (make-sorted-queue
  1151. X      collision-time-<?)))
  1152. X    (let ((complete-ball-vector        ;Build a vector for the balls
  1153. X       (make-vector
  1154. X        num-of-balls)))
  1155. X      (let loop ((ball-num 0)        ;For each ball:
  1156. X         (ball-list ball-list))
  1157. X    (if (not (null? ball-list))
  1158. X        (let ((ball (car ball-list)))
  1159. X          (set-ball-number!        ;Store the ball's number
  1160. X           ball
  1161. X           ball-num)
  1162. X          (vector-set!        ;Place it in the ball vector
  1163. X           complete-ball-vector
  1164. X           ball-num
  1165. X           ball)
  1166. X          (set-ball-ball-list!    ;Save the list of balls with ball
  1167. X           ball            ;numbers greater than the current ball
  1168. X           (cdr ball-list))
  1169. X          (display-ball-state
  1170. X           ball)
  1171. X          (loop
  1172. X           (1+ ball-num)
  1173. X           (cdr ball-list)))))
  1174. X      (let loop ((bumper-num 0)        ;For each bumper:
  1175. X         (bumper-list
  1176. X          bumper-list))
  1177. X    (if (not (null? bumper-list))
  1178. X        (sequence
  1179. X          (set-bumper-number!    ;Store the bumper's number
  1180. X           (car bumper-list)
  1181. X           bumper-num)
  1182. X          (display-bumper-state
  1183. X           (car bumper-list))
  1184. X          (loop
  1185. X           (1+ bumper-num)
  1186. X           (cdr bumper-list)))))
  1187. X
  1188. X      (do ((ball-num 0 (1+ ball-num)))    ;For each ball:
  1189. X      ((= ball-num num-of-balls))
  1190. X    (let* ((ball (vector-ref    ;Cache a reference to the ball
  1191. X              complete-ball-vector
  1192. X              ball-num))
  1193. X           (ball-vector        ;Build a vector for the queue records 
  1194. X        (make-vector        ;of balls with smaller numbers than 
  1195. X         ball-num))        ;this ball
  1196. X           (bumper-vector        ;Build a vector for the queue records
  1197. X        (make-vector        ;of bumpers
  1198. X         num-of-bumpers))
  1199. X           (event-queue        ;Build an event queue for this ball
  1200. X        (ball-event-queue
  1201. X         ball)))
  1202. X      (set-ball-ball-vector!    ;Install the vector of ball queue 
  1203. X       ball                ;records
  1204. X       ball-vector)
  1205. X      (do ((i 0 (1+ i)))        ;For each ball of smaller number than 
  1206. X          ((= i ball-num))    ;the current ball:
  1207. X        (let* ((ball2        ;Cache the ball
  1208. X            (vector-ref
  1209. X             complete-ball-vector
  1210. X             i))
  1211. X               (queue-record    ;Create a queue record for this ball
  1212. X            (make-event-queue-record ;based on the collision time 
  1213. X             '()        ;of the two balls
  1214. X             '()
  1215. X             ball2
  1216. X             (ball-ball-collision-time
  1217. X              ball
  1218. X              ball2))))
  1219. X          (vector-set!        ;Install the queue record in the ball
  1220. X           ball-vector        ;vector for this ball
  1221. X           i
  1222. X           queue-record)
  1223. X          (queue-insert        ;Insert the queue record into the event
  1224. X           event-queue        ;queue for this ball
  1225. X           queue-record)))
  1226. X
  1227. X      (set-ball-bumper-vector!    ;Install the vector of bumper queue
  1228. X       ball                ;records
  1229. X       bumper-vector)
  1230. X      (let loop ((bumper-num 0)
  1231. X             (bumper-list
  1232. X              bumper-list))
  1233. X        (if (not (null? bumper-list))
  1234. X        (let* ((bumper        ;Cache the bumper
  1235. X            (car
  1236. X             bumper-list))
  1237. X               (queue-record    ;Create a queue record for this bumper
  1238. X            (make-event-queue-record ;based on the collision time 
  1239. X             '()        ;of the current ball and this bumper
  1240. X             '()
  1241. X             bumper
  1242. X             (ball-bumper-collision-time
  1243. X              ball
  1244. X              bumper))))
  1245. X          (vector-set!        ;Install the queue record in the bumper
  1246. X           bumper-vector    ;vector for this ball
  1247. X           bumper-num
  1248. X           queue-record)
  1249. X          (queue-insert        ;Insert the queue record into the event
  1250. X           event-queue        ;queue for this ball
  1251. X           queue-record)
  1252. X          (loop
  1253. X           (1+ bumper-num)
  1254. X           (cdr bumper-list)))))
  1255. X      (let ((queue-record        ;Build a global event queue record for
  1256. X         (make-event-queue-record ;the earliest event on this ball's 
  1257. X          '()            ;event queue
  1258. X          '()
  1259. X          ball
  1260. X          (if (empty-queue?
  1261. X               event-queue)
  1262. X              '()
  1263. X              (event-queue-record-collision-time
  1264. X               (queue-smallest
  1265. X            event-queue))))))
  1266. X        (set-ball-global-event-queue-record! ;Store this queue record in 
  1267. X         ball            ;the frame for this ball
  1268. X         queue-record)
  1269. X        (queue-insert        ;Insert this queue record in the global
  1270. X         global-event-queue        ;event queue
  1271. X         queue-record)))))
  1272. X    (actually-simulate            ;Now that all of the data structures
  1273. X     global-event-queue            ;have been built, actually start the 
  1274. X     end-time)))            ;simulation
  1275. X          
  1276. X
  1277. X;;DISPLAY-BALL-STATE displays the ball number, mass, radius, position, and
  1278. X;;velocity of the given ball
  1279. X;;BALL = The ball whose state is to be displayed
  1280. X(define (display-ball-state ball)
  1281. X  (newline)
  1282. X  (display "Ball ")
  1283. X  (display (ball-number ball))
  1284. X  (display " has mass ")
  1285. X  (display (ball-mass ball))
  1286. X  (display " and radius ")
  1287. X  (display (ball-radius ball))
  1288. X  (newline)
  1289. X  (display "   Its position at time ")
  1290. X  (display (ball-collision-time ball))
  1291. X  (display " was ")
  1292. X  (display (ball-collision-x-position ball))
  1293. X  (display ",")
  1294. X  (display (ball-collision-y-position ball))
  1295. X  (display " and its velocity is ")
  1296. X  (display (ball-x-velocity ball))
  1297. X  (display ",")
  1298. X  (display (ball-y-velocity ball)))
  1299. X
  1300. X;;DISPLAY-BUMPER-STATE displays the bumper number and position of the given
  1301. X;;bumper 
  1302. X;;BUMPER = The bumper whose state is to be displayed
  1303. X(define (display-bumper-state bumper)
  1304. X  (newline)
  1305. X  (display "Bumper ")
  1306. X  (display (bumper-number bumper))
  1307. X  (display " extends from ")
  1308. X  (display (bumper-x1 bumper))
  1309. X  (display ",")
  1310. X  (display (bumper-y1 bumper))
  1311. X  (display " to ")
  1312. X  (display (bumper-x2 bumper))
  1313. X  (display ",")
  1314. X  (display (bumper-y2 bumper)))
  1315. X
  1316. X
  1317. X;;ACTUALLY-SIMULATE performs the actual billiard ball simulation
  1318. X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball.
  1319. X;;                     Contains a single event for each ball which is the
  1320. X;;                     earliest collision it would have with a ball of a
  1321. X;;                     smaller number or a bumper, if no other collisions took
  1322. X;;                     place first.
  1323. X;;END-TIME = The time at which the simulation should be terminated
  1324. X(define (actually-simulate global-event-queue end-time)
  1325. X  (letrec ((loop            
  1326. X        (lambda ()
  1327. X          (let* ((record        ;Get the globally earliest event and
  1328. X              (queue-smallest    ;its time
  1329. X               global-event-queue))
  1330. X             (collision-time
  1331. X              (event-queue-record-collision-time
  1332. X               record)))
  1333. X        (if (not        ;If this event happens before the
  1334. X             (time-<?        ;simulation termination time:
  1335. X              end-time
  1336. X              collision-time))
  1337. X            (let* ((ball    ;Get the ball involved in the event,
  1338. X                (event-queue-record-object
  1339. X                 record))
  1340. X               (ball-queue    ;the queue of events for that ball,
  1341. X                (ball-event-queue
  1342. X                 ball))
  1343. X               (other-object ;and the first object with which the 
  1344. X                (event-queue-record-object ;ball interacts
  1345. X                 (queue-smallest
  1346. X                  ball-queue))))
  1347. X              ((simulation-object-collision-procedure ;Process this
  1348. X            other-object)    ;globally earliest collision
  1349. X               ball
  1350. X               other-object
  1351. X               collision-time
  1352. X               global-event-queue)
  1353. X              (loop)))))))    ;Process the next interaction
  1354. X    (loop)))
  1355. X
  1356. X
  1357. X(require 'cscheme)
  1358. X(set! autoload-notify? #f)
  1359. X
  1360. X        (simulate
  1361. X         (list (make-ball 2 1 9 5 -1 -1)
  1362. X               (make-ball 4 2 2 5 1 -1))
  1363. X         (list (make-bumper 0 0 0 10)
  1364. X               (make-bumper 0 0 10 0)
  1365. X               (make-bumper 0 10 10 10)
  1366. X               (make-bumper 10 0 10 10))
  1367. X         100)
  1368. END_OF_tst/billiard
  1369. if test 46118 -ne `wc -c <tst/billiard`; then
  1370.     echo shar: \"tst/billiard\" unpacked with wrong size!
  1371. fi
  1372. # end of overwriting check
  1373. fi
  1374. if test -f lib/xlib/examples/properties -a "${1}" != "-c" ; then 
  1375.   echo shar: Will not over-write existing file \"lib/xlib/examples/properties\"
  1376. else
  1377. echo shar: Extracting \"lib/xlib/examples/properties\" \(969 characters\)
  1378. sed "s/^X//" >lib/xlib/examples/properties <<'END_OF_lib/xlib/examples/properties'
  1379. X;;; -*-Scheme-*-
  1380. X;;;
  1381. X;;; Display all properties of all windows (with name, type, format,
  1382. X;;; and data).
  1383. X
  1384. X(require 'xlib)
  1385. X
  1386. X(define (properties)
  1387. X  (let ((dpy (open-display)))
  1388. X    (unwind-protect
  1389. X     (let* ((w (car (query-tree (display-root-window dpy))))
  1390. X        (l (map (lambda (win) (cons win (list-properties win)))
  1391. X            (cons (display-root-window dpy) (vector->list w))))
  1392. X        (tab (lambda (obj n)
  1393. X           (let* ((s (format #f "~s" obj))
  1394. X              (n (- n (string-length s))))
  1395. X             (display s)
  1396. X             (if (positive? n)
  1397. X             (do ((i 0 (1+ i))) ((= i n)) (display #\space)))))))
  1398. X       (for-each
  1399. X    (lambda (w)
  1400. X      (format #t "Window ~s:~%" (car w))
  1401. X      (for-each
  1402. X       (lambda (p)
  1403. X         (tab (atom-name dpy p) 20)
  1404. X         (display "= ")
  1405. X         (let ((p (get-property (car w) p #f 0 20 #f)))
  1406. X           (tab (atom-name dpy (car p)) 18)
  1407. X           (tab (cadr p) 3)
  1408. X           (format #t "~s~%" (caddr p))))
  1409. X       (vector->list (cdr w)))
  1410. X      (newline))
  1411. X    l))
  1412. X     (close-display dpy))))
  1413. X
  1414. X(properties)
  1415. END_OF_lib/xlib/examples/properties
  1416. if test 969 -ne `wc -c <lib/xlib/examples/properties`; then
  1417.     echo shar: \"lib/xlib/examples/properties\" unpacked with wrong size!
  1418. fi
  1419. # end of overwriting check
  1420. fi
  1421. if test -f lib/xlib/examples/track -a "${1}" != "-c" ; then 
  1422.   echo shar: Will not over-write existing file \"lib/xlib/examples/track\"
  1423. else
  1424. echo shar: Extracting \"lib/xlib/examples/track\" \(1062 characters\)
  1425. sed "s/^X//" >lib/xlib/examples/track <<'END_OF_lib/xlib/examples/track'
  1426. X;;; -*-Scheme-*-
  1427. X
  1428. X(require 'xlib)
  1429. X
  1430. X(define (track)
  1431. X  (let* ((dpy (open-display))
  1432. X     (root (display-root-window dpy))
  1433. X     (gc (make-gcontext (window root)
  1434. X                (function 'xor)
  1435. X                (foreground (black-pixel dpy))
  1436. X                (subwindow-mode 'include-inferiors)))
  1437. X     (lx 0) (ly 0) (lw 0) (lh 0)
  1438. X     (move-outline
  1439. X      (lambda (x y w h)
  1440. X        (if (not (and (= x lx) (= y ly) (= w lw) (= h lh)))
  1441. X        (begin
  1442. X          (draw-rectangle root gc lx ly lw lh)
  1443. X          (draw-rectangle root gc x y w h)
  1444. X          (set! lx x) (set! ly y)
  1445. X          (set! lw w) (set! lh h))))))
  1446. X    (unwind-protect
  1447. X     (case (grab-pointer root #f '(pointer-motion button-press)
  1448. X             #f #f 'none 'none 'now)
  1449. X       (success
  1450. X    (with-server-grabbed dpy
  1451. X      (draw-rectangle root gc lx ly lw lh)
  1452. X      (display-flush-output dpy)
  1453. X      (handle-events dpy
  1454. X        (motion-notify
  1455. X         (lambda (event root win subwin time x y . rest)
  1456. X           (move-outline x y 300 300) #f))
  1457. X        (else (lambda args #t)))))
  1458. X       (else
  1459. X    (format #t "Not grabbed!~%")))
  1460. X     (begin
  1461. X       (draw-rectangle root gc lx ly lw lh)
  1462. X       (close-display dpy)))))
  1463. X
  1464. X(track)
  1465. END_OF_lib/xlib/examples/track
  1466. if test 1062 -ne `wc -c <lib/xlib/examples/track`; then
  1467.     echo shar: \"lib/xlib/examples/track\" unpacked with wrong size!
  1468. fi
  1469. # end of overwriting check
  1470. fi
  1471. if test -f lib/xlib/examples/picture -a "${1}" != "-c" ; then 
  1472.   echo shar: Will not over-write existing file \"lib/xlib/examples/picture\"
  1473. else
  1474. echo shar: Extracting \"lib/xlib/examples/picture\" \(2425 characters\)
  1475. sed "s/^X//" >lib/xlib/examples/picture <<'END_OF_lib/xlib/examples/picture'
  1476. X;;; -*-Scheme-*-
  1477. X
  1478. X;;; -*- Mode:Lisp; Package:XLIB; Syntax:COMMON-LISP; Base:10; Lowercase:T -*-
  1479. X
  1480. X;;; CLX - Point Graphing demo program
  1481. X
  1482. X;;; Copyright (C) 1988 Michael O. Newton (newton@csvax.caltech.edu)
  1483. X
  1484. X;;; Permission is granted to any individual or institution to use, copy,
  1485. X;;; modify, and distribute this software, provided that this complete
  1486. X;;; copyright and permission notice is maintained, intact, in all copies and
  1487. X;;; supporting documentation.
  1488. X
  1489. X;;; The author provides this software "as is" without express or
  1490. X;;; implied warranty.
  1491. X
  1492. X;;; This routine plots the recurrance
  1493. X;;;      x <- y(1+sin(0.7x)) - 1.2(|x|)^.5
  1494. X;;;      y <- .21 - x
  1495. X;;; As described in a ?? 1983 issue of the Mathematical Intelligencer
  1496. X;;; It has ONLY been tested under X.V11R2 on a Sun3 running KCL
  1497. X
  1498. X(require 'xlib)
  1499. X
  1500. X(define (picture point-count)
  1501. X  (let* ((dpy (open-display))
  1502. X     (width 600)
  1503. X     (height 600)
  1504. X     (black (black-pixel dpy))
  1505. X     (white (white-pixel dpy))
  1506. X     (root (display-root-window dpy))
  1507. X     (win (make-window (parent root) (background-pixel white)
  1508. X               (event-mask '(exposure button-press))
  1509. X               (width width) (height height)))
  1510. X     (gc (make-gcontext (window win)
  1511. X                (background white) (foreground black))))
  1512. X    (map-window win)
  1513. X    (unwind-protect
  1514. X     (handle-events dpy
  1515. X       (expose
  1516. X    (lambda ignore
  1517. X      (clear-window win)
  1518. X      (draw-points win gc point-count 0.0 0.0 (* width 0.5) (* height 0.5))
  1519. X      (draw-poly-text win gc 10 10 (translate "Click a button to exit")
  1520. X              '1-byte)
  1521. X      #f))
  1522. X       (else (lambda ignore #t)))
  1523. X     (close-display dpy))))
  1524. X
  1525. X;;; Draw points.  These should maybe be put into a an array so that they do
  1526. X;;; not have to be recomputed on exposure.  X assumes points are in the range
  1527. X;;; of width x height, with 0,0 being upper left and 0,H being lower left.
  1528. X;;;      x <- y(1+sin(0.7x)) - 1.2(|x|)^.5
  1529. X;;;      y <- .21 - x
  1530. X;;; hw and hh are half-width and half-height of screen
  1531. X
  1532. X(define (draw-points win gc count x y hw hh)
  1533. X  (if (zero? (modulo count 100))
  1534. X      (display-flush-output (window-display win)))
  1535. X  (if (not (zero? count))
  1536. X      (let ((xf (floor (* (+ 1.2 x) hw ))) ; These lines center the picture
  1537. X        (yf (floor (* (+ 0.5 y) hh ))))
  1538. X    (draw-point win gc xf yf)
  1539. X    (draw-points win gc (1- count)
  1540. X             (- (* y (1+ (sin (* 0.7 x)))) (* 1.2 (sqrt (abs x))))
  1541. X             (- 0.21 x)
  1542. X             hw hh))))
  1543. X
  1544. X(define (translate string)
  1545. X  (list->vector (map char->integer (string->list string))))
  1546. X
  1547. X(picture 10000)
  1548. END_OF_lib/xlib/examples/picture
  1549. if test 2425 -ne `wc -c <lib/xlib/examples/picture`; then
  1550.     echo shar: \"lib/xlib/examples/picture\" unpacked with wrong size!
  1551. fi
  1552. # end of overwriting check
  1553. fi
  1554. if test -f lib/xlib/examples/useful -a "${1}" != "-c" ; then 
  1555.   echo shar: Will not over-write existing file \"lib/xlib/examples/useful\"
  1556. else
  1557. echo shar: Extracting \"lib/xlib/examples/useful\" \(567 characters\)
  1558. sed "s/^X//" >lib/xlib/examples/useful <<'END_OF_lib/xlib/examples/useful'
  1559. X;;; -*-Scheme-*-
  1560. X
  1561. X(require 'xlib)
  1562. X
  1563. X(define dpy
  1564. X  (open-display))
  1565. X
  1566. X(define (f)
  1567. X  (display-wait-output dpy #t))
  1568. X
  1569. X(define root
  1570. X  (display-root-window dpy))
  1571. X
  1572. X(define cmap
  1573. X  (display-colormap dpy))
  1574. X
  1575. X(define white (white-pixel dpy))
  1576. X(define black (black-pixel dpy))
  1577. X
  1578. X(define rgb-white (query-color cmap white))
  1579. X(define rgb-black (query-color cmap black))
  1580. X
  1581. X(define win
  1582. X  (make-window (parent root)
  1583. X           (width 300) (height 300)
  1584. X           (background-pixel white)))
  1585. X
  1586. X(define gc (make-gcontext
  1587. X        (window win)
  1588. X        (background white) (foreground black)))
  1589. X
  1590. X(map-window win)
  1591. END_OF_lib/xlib/examples/useful
  1592. if test 567 -ne `wc -c <lib/xlib/examples/useful`; then
  1593.     echo shar: \"lib/xlib/examples/useful\" unpacked with wrong size!
  1594. fi
  1595. # end of overwriting check
  1596. fi
  1597. if test -f lib/xlib/pixel.c -a "${1}" != "-c" ; then 
  1598.   echo shar: Will not over-write existing file \"lib/xlib/pixel.c\"
  1599. else
  1600. echo shar: Extracting \"lib/xlib/pixel.c\" \(1332 characters\)
  1601. sed "s/^X//" >lib/xlib/pixel.c <<'END_OF_lib/xlib/pixel.c'
  1602. X#include "xlib.h"
  1603. X
  1604. XGeneric_Predicate (Pixel);
  1605. X
  1606. XGeneric_Simple_Equal (Pixel, PIXEL, pix);
  1607. X
  1608. XGeneric_Print (Pixel, "#[pixel 0x%lx]", PIXEL(x)->pix);
  1609. X
  1610. XObject Make_Pixel (val) unsigned long val; {
  1611. X    register char *p;
  1612. X    Object pix;
  1613. X
  1614. X    pix = Find_Object (T_Pixel, (GENERIC)0, Match_X_Obj, val);
  1615. X    if (Nullp (pix)) {
  1616. X    p = Get_Bytes (sizeof (struct S_Pixel));
  1617. X    SET (pix, T_Pixel, (struct S_Pixel *)p);
  1618. X    PIXEL(pix)->tag = Null;
  1619. X    PIXEL(pix)->pix = val;
  1620. X    Register_Object (pix, (GENERIC)0, (PFO)0, 0);
  1621. X    }
  1622. X    return pix;
  1623. X}
  1624. X
  1625. Xunsigned long Get_Pixel (p) Object p; {
  1626. X    Check_Type (p, T_Pixel);
  1627. X    return PIXEL(p)->pix;
  1628. X}
  1629. X
  1630. Xstatic Object P_Pixel_Value (p) Object p; {
  1631. X    return Make_Unsigned ((unsigned)Get_Pixel (p));
  1632. X}
  1633. X
  1634. Xstatic Object P_Black_Pixel (d) Object d; {
  1635. X    Check_Type (d, T_Display);
  1636. X    return Make_Pixel (BlackPixel (DISPLAY(d)->dpy,
  1637. X    DefaultScreen (DISPLAY(d)->dpy)));
  1638. X}
  1639. X
  1640. Xstatic Object P_White_Pixel (d) Object d; {
  1641. X    Check_Type (d, T_Display);
  1642. X    return Make_Pixel (WhitePixel (DISPLAY(d)->dpy, 
  1643. X    DefaultScreen (DISPLAY(d)->dpy)));
  1644. X}
  1645. X
  1646. Xinit_xlib_pixel () {
  1647. X    Generic_Define (Pixel, "pixel", "pixel?");
  1648. X    Define_Primitive (P_Pixel_Value,   "pixel-value",    1, 1, EVAL);
  1649. X    Define_Primitive (P_Black_Pixel,   "black-pixel",    1, 1, EVAL);
  1650. X    Define_Primitive (P_White_Pixel,   "white-pixel",    1, 1, EVAL);
  1651. X}
  1652. END_OF_lib/xlib/pixel.c
  1653. if test 1332 -ne `wc -c <lib/xlib/pixel.c`; then
  1654.     echo shar: \"lib/xlib/pixel.c\" unpacked with wrong size!
  1655. fi
  1656. # end of overwriting check
  1657. fi
  1658. echo shar: End of archive 9 \(of 14\).
  1659. cp /dev/null ark9isdone
  1660. MISSING=""
  1661. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1662.     if test ! -f ark${I}isdone ; then
  1663.     MISSING="${MISSING} ${I}"
  1664.     fi
  1665. done
  1666. if test "${MISSING}" = "" ; then
  1667.     echo You have unpacked all 14 archives.
  1668.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1669. else
  1670.     echo You still need to unpack the following archives:
  1671.     echo "        " ${MISSING}
  1672. fi
  1673. ##  End of shell archive.
  1674. exit 0
  1675.