home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-09-23 | 57.0 KB | 1,675 lines |
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v08i057: Elk (Extension Language Toolkit) part 09 of 14
- Reply-To: net@tub.UUCP (Oliver Laumann)
-
- Posting-number: Volume 8, Issue 57
- Submitted-by: net@tub.UUCP (Oliver Laumann)
- Archive-name: elk/part09
-
- [Let this be a lesson to submitters: this was submitted as uuencoded,
- compressed files. I lost the source information while unpacking it; this
- is the best approximation I could come up with. ++bsa]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 14)."
- # Contents: tst/billiard lib/xlib/examples/properties
- # lib/xlib/examples/track lib/xlib/examples/picture
- # lib/xlib/examples/useful lib/xlib/pixel.c
- # Wrapped by net@tub on Sun Sep 17 17:32:32 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f tst/billiard -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"tst/billiard\"
- else
- echo shar: Extracting \"tst/billiard\" \(46118 characters\)
- sed "s/^X//" >tst/billiard <<'END_OF_tst/billiard'
- X;;;
- X;;; BILLIARD.SCM: This file contains code for a very simple billiard ball
- X;;; simulator. The simulation takes place in two dimensions.
- X;;; The balls are really disks in that their height is not taken
- X;;; into account. All interactions are assumed to be
- X;;; frictionless so spin in irrelevant and not accounted for.
- X;;; (See section on limitations.)
- X;;;
- X;;; NOTES: A simulation is initiated by creating a number of balls and bumpers
- X;;; and and specifying a duration for the simulation. For each ball,
- X;;; its mass, radius, initial position, and initial velocity must be
- X;;; specified. For each bumper, the location of its two ends must be
- X;;; specified. (Bumpers are assumed to have zero width.)
- X;;;
- X;;; A sample run might be started as follows:
- X;;; (simulate
- X;;; (list (make-ball 2 1 9 5 -1 -1)
- X;;; (make-ball 4 2 2 5 1 -1))
- X;;; (list (make-bumper 0 0 0 10)
- X;;; (make-bumper 0 0 10 0)
- X;;; (make-bumper 0 10 10 10)
- X;;; (make-bumper 10 0 10 10))
- X;;; 30)
- X;;;
- X;;; It would create one billiard ball of mass 2 and radius 1 at position
- X;;; (9, 5) with initial velocity (-1, -1) and a second ball of mass 4
- X;;; and radius 2 at position (2, 5) with initial velocity (1, -1). The
- X;;; table would be a 10X10 square. (See diagram below)
- X;;;
- X;;; +---------------------------+
- X;;; | |
- X;;; | |
- X;;; | XXXX |
- X;;; | XXXXXXXX XX |
- X;;; |XXXXXX4XXXXX XXX2XX|
- X;;; | XXXXXXXX /XX |
- X;;; | XXXX \ |
- X;;; | |
- X;;; | |
- X;;; +---------------------------+
- X;;;
- X;;; LIMITATIONS: This simulator does not handle 3 body problems correctly. If
- X;;; 3 objects interact at one time, only the interactions of 2 of
- X;;; the bodies will be accounted for. This can lead to strange
- X;;; effects like balls tunneling through walls and other balls.
- X;;; It is also possible to get balls bouncing inside of each
- X;;; other in this way.
- X;;;
- X
- X
- X;;MAKE-QUEUE-RECORD returns a queue record with the given next, previous, and
- X;;value values
- X;;NEXT = The next record pointer
- X;;PREV = The previous record pointer
- X;;REST = A list of values for any optional fields (this can be used for
- X;; creating structure inheritance)
- X(define-macro (make-queue-record next prev . rest)
- X `(vector ,next ,prev ,@rest))
- X
- X;;QUEUE-RECORD-NEXT returns the next field of the given queue record
- X;;QUEUE-RECORD = The queue record whose next field is to be returned
- X(define-macro (queue-record-next queue-record)
- X `(vector-ref ,queue-record 0))
- X
- X;;SET-QUEUE-RECORD-NEXT! sets the next field of the given queue record
- X;;QUEUE-RECORD = The queue record whose next field is to be set
- X;;VALUE = The value to which the next field is to be set
- X(define-macro (set-queue-record-next! queue-record value)
- X `(vector-set! ,queue-record 0 ,value))
- X
- X;;QUEUE-RECORD-PREV returns the prev field of the given queue record
- X;;QUEUE-RECORD = The queue record whose prev field is to be returned
- X(define-macro (queue-record-prev queue-record)
- X `(vector-ref ,queue-record 1))
- X
- X;;SET-QUEUE-RECORD-PREV! sets the prev field of the given queue record
- X;;QUEUE-RECORD = The queue record whose prev field is to be set
- X;;VALUE = The value to which the prev field is to be set
- X(define-macro (set-queue-record-prev! queue-record value)
- X `(vector-set! ,queue-record 1 ,value))
- X
- X;;QUEUE-RECORD-LEN returns the length of a queue record which has no optional
- X;;fields
- X(define-macro (queue-record-len) 2)
- X
- X;;QUEUE-HEAD returns a dummy record at the end of the queue with the record
- X;;with the smallest key.
- X;;QUEUE = the queue whose head record is to be returned
- X(define-macro (queue-head queue)
- X `(vector-ref ,queue 0))
- X
- X;;QUEUE-TAIL returns a dummy record at the end of the queue with the record
- X;;with the largest key.
- X;;QUEUE = the queue whose tail record is to be returned
- X(define-macro (queue-tail queue)
- X `(vector-ref ,queue 1))
- X
- X;;QUEUE-<? returns the less-than comparitor to be used in sorting
- X;;records into the queue
- X;;QUEUE = The queue whose comparitor is to be returned
- X(define-macro (queue-<? queue)
- X `(vector-ref ,queue 2))
- X
- X
- X;;MAKE-SORTED-QUEUE returns a queue object. A queue header is a vector which
- X;;contains a head pointer, a tail pointer, and a less-than comparitor.
- X;;QUEUE-<? = A predicate for sorting queue items
- X(define (make-sorted-queue queue-<?)
- X (let ((queue
- X (vector
- X (make-queue-record ;The queue head record has no initial
- X '() ;next, previous, or value values
- X '())
- X (make-queue-record ;The queue tail record has no intial
- X '() ;next, previous, or value values
- X '())
- X queue-<?)))
- X (set-queue-record-next!
- X (queue-head queue)
- X (queue-tail queue))
- X (set-queue-record-prev!
- X (queue-tail queue)
- X (queue-head queue))
- X queue))
- X
- X;;MAKE-EVENT-QUEUE-RECORD returns an event queue record with the given next,
- X;;previous, object, and collision-time values
- X;;NEXT = The next record pointer
- X;;PREV = The previous record pointer
- X;;OBJECT = The simulation object associated with this record
- X;;COLLISION-TIME = The collision time for this object
- X(define-macro (make-event-queue-record next prev object collision-time)
- X `(make-queue-record ,next ,prev ,object ,collision-time))
- X
- X;;EVENT-QUEUE-RECORD-OBJECT returns the object associated with the given record
- X;;QUEUE-RECORD = The queue record whose object field is to be returned
- X(define-macro (event-queue-record-object queue-record)
- X `(vector-ref ,queue-record ,(queue-record-len)))
- X
- X;;EVENT-QUEUE-COLLISION-TIME returns the collision time associated with the
- X;;given queue record
- X;;QUEUE-RECORD = The queue record whose collision time field is to be returned
- X(define-macro (event-queue-record-collision-time queue-record)
- X `(vector-ref ,queue-record ,(1+ (queue-record-len))))
- X
- X;;SET-EVENT-QUEUE-COLLISION-TIME! sets the collision time associated with the
- X;;given queue record
- X;;QUEUE-RECORD = The queue record whose collision time field is to be returned
- X;;VALUE = The value to which it is to be set
- X(define-macro (set-event-queue-record-collision-time! queue-record value)
- X `(vector-set! ,queue-record ,(1+ (queue-record-len)) ,value))
- X
- X
- X;;QUEUE-INSERT inserts the given record in the given queue based on its value
- X;;QUEUE = The queue into which the record is to be inserted
- X;;QUEUE-RECORD = The record to be inserted in the queue
- X(define (queue-insert queue queue-record)
- X (define (actual-insert insert-record next-record)
- X (if (or ;If the insert position has been found
- X (eq? next-record ;or the end on the queue has been
- X (queue-tail queue)) ;reached
- X ((queue-<? queue)
- X insert-record
- X next-record))
- X (sequence ;Link the insert record into the queue
- X (set-queue-record-next! ;just prior to next-record
- X (queue-record-prev
- X next-record)
- X insert-record)
- X (set-queue-record-prev!
- X insert-record
- X (queue-record-prev
- X next-record))
- X (set-queue-record-next!
- X insert-record
- X next-record)
- X (set-queue-record-prev!
- X next-record
- X insert-record))
- X (actual-insert ;Else, continue searching for the
- X insert-record ;insert position
- X (queue-record-next
- X next-record))))
- X (actual-insert ;Search for the correct position to
- X queue-record ;perform the insert starting at the
- X (queue-record-next ;queue head and perform the insert
- X (queue-head queue)))) ;once this position has been found
- X
- X;;QUEUE-REMOVE removes the given queue record from its queue
- X;;QUEUE-RECORD = The record to be removed from the queue
- X(define (queue-remove queue-record)
- X (set-queue-record-next!
- X (queue-record-prev
- X queue-record)
- X (queue-record-next
- X queue-record))
- X (set-queue-record-prev!
- X (queue-record-next
- X queue-record)
- X (queue-record-prev
- X queue-record)))
- X
- X;;QUEUE-SMALLEST returns the queue record with the smallest key on the given
- X;;queue
- X;;QUEUE = The queue from which the smallest record is to be extracted
- X(define (queue-smallest queue)
- X (queue-record-next
- X (queue-head queue)))
- X
- X
- X;;CLEAR-QUEUE! clears the given queue by destructively removing all the records
- X;;QUEUE = The queue to be cleared
- X(define (clear-queue queue)
- X (set-queue-record-next!
- X (queue-head queue)
- X (queue-tail queue))
- X (set-queue-record-prev!
- X (queue-tail queue)
- X (queue-head queue)))
- X
- X;;EMPTY-QUEUE? returns true if the given queue is empty
- X;;QUEUE = The queue to be tested for emptiness
- X(define (empty-queue? queue)
- X (eq? (queue-record-next
- X (queue-head queue))
- X (queue-tail queue)))
- X
- X
- X;;MAKE-SIMULATION-OBJECT returns a simulation object containing the given
- X;;fields
- X;;COLLISION-PROCEDURE = A function for processing information about a potential
- X;; collision between this object and some ball
- X;;REST = A list of values for any optional fields (this can be used for
- X;; creating structure inheritance)
- X(define-macro (make-simulation-object collision-procedure . rest)
- X `(vector ,collision-procedure ,@rest))
- X
- X;;SIMULATION-OBJECT-COLLLISION-PROCEDURE returns the collision procedure for
- X;;the given simulation object
- X;;OBJECT = The object whose collision procedure is to be returned
- X(define-macro (simulation-object-collision-procedure object)
- X `(vector-ref ,object 0))
- X
- X;;SIMULATION-OBJECT-LEN returns the length of a simulation object which has no
- X;;optional fields
- X(define-macro (simulation-object-len) 1)
- X
- X
- X;;ACTUAL-MAKE-BALL returns a ball object
- X;;BALL-NUMBER = An index into the ball vector for this ball
- X;;MASS = The ball's mass
- X;;RADIUS = The ball's radius
- X;;PX = The x-coordinate of the ball's initial position
- X;;PY = The y-coordinate of the ball's initial position
- X;;VX = The x-coordinate of the ball's initial velocity
- X;;VY = The y-coordinate of the ball's initial velocity
- X(define-macro (actual-make-ball ball-number mass radius px py vx vy)
- X `(make-simulation-object
- X ball-collision-procedure ;The collision procedure for a ball
- X ,ball-number
- X ,mass
- X ,radius
- X (make-sorted-queue ;The event queue
- X collision-time-<?)
- X 0 ;Time of last collision
- X ,px ;Position of last collision
- X ,py ; "
- X ,vx ;Velocity following last colliosion
- X ,vy ; "
- X '() ;No vector of queue records for ball's
- X ;with smaller numbers
- X '() ;No vector of queue records for bumpers
- X '() ;No list of balls with larger numbers
- X '())) ;No global event queue record, yet
- X
- X(define (make-ball mass radius px py vx vy)
- X (actual-make-ball '() mass radius px py vx vy))
- X
- X;;BALL-NUMBER returns the index of the given ball
- X;;BALL = The ball whose index is to be returned
- X(define-macro (ball-number ball)
- X `(vector-ref ,ball ,(simulation-object-len)))
- X
- X;;SET-BALL-NUMBER! set the index of the given ball to the given value
- X;;BALL = The ball whose index is to be set
- X;;VALUE = The value to which it is to be set
- X(define-macro (set-ball-number! ball value)
- X `(vector-set! ,ball ,(simulation-object-len) ,value))
- X
- X;;BALL-MASS returns the mass of the given ball
- X;;BALL = The ball whose mass is to be returned
- X(define-macro (ball-mass ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 1)))
- X
- X;;BALL-RADIUS returns the radius of the given ball
- X;;BALL = The ball whose radius is to be returned
- X(define-macro (ball-radius ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 2)))
- X
- X;;BALL-EVENT-QUEUE returns the sort queue of collision events for the given
- X;;ball
- X;;BALL = The ball whose event is to be returned
- X(define-macro (ball-event-queue ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 3)))
- X
- X;;BALL-COLLISION-TIME returns the time of the last collision for the given ball
- X;;BALL = The ball whose collision time is to be returned
- X(define-macro (ball-collision-time ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 4)))
- X
- X
- X;;SET-BALL-COLLISION-TIME! sets the time of the last collision for the given
- X;;ball
- X;;BALL = The ball whose collision time is to be set
- X;;VALUE = The value to which the ball's collision time is to be set
- X(define-macro (set-ball-collision-time! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 4) ,value))
- X
- X;;BALL-COLLISION-X-POSITION returns the x-coordinate of the position of the
- X;;last collision for the given ball
- X;;BALL = The ball whose collision position is to be returned
- X(define-macro (ball-collision-x-position ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 5)))
- X
- X;;SET-BALL-COLLISION-X-POSITION! sets the x-coordinate of the position of the
- X;;last collision for the given ball
- X;;BALL = The ball whose collision position is to be set
- X;;VALUE = The value to which the ball's collision position is to be set
- X(define-macro (set-ball-collision-x-position! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 5) ,value))
- X
- X;;BALL-COLLISION-Y-POSITION returns the y-coordinate of the position of the
- X;;last collision for the given ball
- X;;BALL = The ball whose collision position is to be returned
- X(define-macro (ball-collision-y-position ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 6)))
- X
- X;;SET-BALL-COLLISION-Y-POSITION! sets the y-coordinate of the position of the
- X;;last collision for the given ball
- X;;BALL = The ball whose collision position is to be set
- X;;VALUE = The value to which the ball's collision position is to be set
- X(define-macro (set-ball-collision-y-position! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 6) ,value))
- X
- X;;BALL-X-VELOCITY returns the x-coordinate of the velocity of the given ball
- X;;following its last collision
- X;;BALL = The ball whose velocity is to be returned
- X(define-macro (ball-x-velocity ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 7)))
- X
- X;;SET-BALL-X-VELOCITY! sets the x-coordinate of the velocity of the given ball
- X;;BALL = The ball whose velocity is to be set
- X;;VALUE = The value to which the ball's velocity is to be set
- X(define-macro (set-ball-x-velocity! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 7) ,value))
- X
- X;;BALL-Y-VELOCITY returns the y-coordinate of the velocity of the given ball
- X;;following its last collision
- X;;BALL = The ball whose velocity is to be returned
- X(define-macro (ball-y-velocity ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 8)))
- X
- X;;SET-BALL-Y-VELOCITY! sets the y-coordinate of the velocity of the given ball
- X;;BALL = The ball whose velocity is to be set
- X;;VALUE = The value to which the ball's velocity is to be set
- X(define-macro (set-ball-y-velocity! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 8) ,value))
- X
- X
- X;;BALL-BALL-VECTOR returns the vector of queue records for balls with smaller
- X;;ball numbers
- X;;BALL = The ball whose ball vector is to be returned
- X(define-macro (ball-ball-vector ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 9)))
- X
- X;;SET-BALL-BALL-VECTOR! sets the vector of queue records for balls with smaller
- X;;ball numbers
- X;;BALL = The ball whose ball vector is to be set
- X;;VALUE = The vector to which the field is to be set
- X(define-macro (set-ball-ball-vector! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 9) ,value))
- X
- X;;BALL-BUMPER-VECTOR returns the vector of queue records for bumpers
- X;;BALL = The ball whose bumper vector is to be returned
- X(define-macro (ball-bumper-vector ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 10)))
- X
- X;;SET-BALL-BUMPER-VECTOR! sets the vector of queue records for bumpers
- X;;BALL = The ball whose bumper vector is to be set
- X;;VALUE = The vector to which the field is to be set
- X(define-macro (set-ball-bumper-vector! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 10) ,value))
- X
- X;;BALL-BALL-LIST returns a list of balls with larger ball numbers than the
- X;;given ball
- X;;BALL = The ball whose ball list is to be returned
- X(define-macro (ball-ball-list ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 11)))
- X
- X;;SET-BALL-BALL-LIST! sets the list of balls with larger ball numbers than the
- X;;given ball
- X;;BALL = The ball whose ball list is to be set
- X;;VALUE = The value to which the ball list is to be set
- X(define-macro (set-ball-ball-list! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 11) ,value))
- X
- X;;BALL-GLOBAL-EVENT-QUEUE-RECORD returns the global event queue record for the
- X;;given ball
- X;;BALL = The ball whose global event queue record is to be returned
- X(define-macro (ball-global-event-queue-record ball)
- X `(vector-ref ,ball ,(+ (simulation-object-len) 12)))
- X
- X;;SET-BALL-GLOBAL-EVENT-QUEUE-RECORD! set the global event queue record for the
- X;;given ball to the given value
- X;;BALL = The ball whose global event queue record is to be set
- X;;VALUE = The value to which the global event queue record field is to be set
- X(define-macro (set-ball-global-event-queue-record! ball value)
- X `(vector-set! ,ball ,(+ (simulation-object-len) 12) ,value))
- X
- X
- X
- X;;ACTUAL-MAKE-BUMPER returns a bumper object
- X;;BUMPER-NUMBER = An index into the bumper vector for this bumper
- X;;X1 = The x-coordiante of one end of the bumper
- X;;Y1 = The y-coordiante of one end of the bumper
- X;;X2 = The x-coordiante of the other end of the bumper
- X;;Y2 = The y-coordiante of the other end of the bumper
- X(define-macro (actual-make-bumper bumper-number x1 y1 x2 y2)
- X `(make-simulation-object
- X bumper-collision-procedure ;The collision procedure for a bumper
- X ,bumper-number
- X ,x1 ;The bumper endpoints
- X ,y1
- X ,x2
- X ,y2))
- X
- X(define (make-bumper x1 y1 x2 y2)
- X (actual-make-bumper '() x1 y1 x2 y2))
- X
- X;;BUMPER-NUMBER returns the index of the given bumper
- X;;BUMPER = The bumper whose index is to be returned
- X(define-macro (bumper-number bumper)
- X `(vector-ref ,bumper ,(simulation-object-len)))
- X
- X;;SET-BUMPER-NUMBER! set the index of the given bumper to the given value
- X;;BUMPER = The bumper whose index is to be set
- X;;VALUE = The value to which it is to be set
- X(define-macro (set-bumper-number! bumper value)
- X `(vector-set! ,bumper ,(simulation-object-len) ,value))
- X
- X;;BUMPER-X1 returns the x-coordinate of one end of the given bumber
- X;;BUMPER = the bumper whose x-coordinate is to be returned
- X(define-macro (bumper-x1 bumper)
- X `(vector-ref ,bumper ,(1+ (simulation-object-len))))
- X
- X;;SET-BUMPER-X1! sets the x-coordinate of one end of the given bumber
- X;;BUMPER = the bumper whose x-coordinate is to be set
- X;;VALUE = The value to which the bumpers x-coordinate is to be set
- X(define-macro (set-bumper-x1! bumper value)
- X `(vector-set! ,bumper ,(1+ (simulation-object-len)) ,value))
- X
- X;;BUMPER-Y1 returns the y-coordinate of one end of the given bumber
- X;;BUMPER = the bumper whose y-coordinate is to be returned
- X(define-macro (bumper-y1 bumper)
- X `(vector-ref ,bumper ,(+ (simulation-object-len) 2)))
- X
- X;;SET-BUMPER-Y1! sets the y-coordinate of one end of the given bumber
- X;;BUMPER = the bumper whose y-coordinate is to be set
- X;;VALUE = The value to which the bumpers y-coordinate is to be set
- X(define-macro (set-bumper-y1! bumper value)
- X `(vector-set! ,bumper ,(+ (simulation-object-len) 2) ,value))
- X
- X;;BUMPER-X2 returns the x-coordinate of the other end of the given bumber
- X;;BUMPER = the bumper whose x-coordinate is to be returned
- X(define-macro (bumper-x2 bumper)
- X `(vector-ref ,bumper ,(+ (simulation-object-len) 3)))
- X
- X;;SET-BUMPER-X2! sets the x-coordinate of the other end of the given bumber
- X;;BUMPER = the bumper whose x-coordinate is to be set
- X;;VALUE = The value to which the bumpers x-coordinate is to be set
- X(define-macro (set-bumper-x2! bumper value)
- X `(vector-set! ,bumper ,(+ (simulation-object-len) 3) ,value))
- X
- X
- X;;BUMPER-Y2 returns the y-coordinate of the other end of the given bumber
- X;;BUMPER = the bumper whose y-coordinate is to be returned
- X(define-macro (bumper-y2 bumper)
- X `(vector-ref ,bumper ,(+ (simulation-object-len) 4)))
- X
- X;;SET-BUMPER-Y2! sets the y-coordinate of the other end of the given bumber
- X;;BUMPER = the bumper whose y-coordinate is to be set
- X;;VALUE = The value to which the bumpers y-coordinate is to be set
- X(define-macro (set-bumper-y2! bumper value)
- X `(vector-set! ,bumper ,(+ (simulation-object-len) 4) ,value))
- X
- X;;COLLISION-TIME-<? is a predicate which returns true if the first event queueu
- X;;record represents a collision that will take place at an earlier time than
- X;;the one for the second event queue record
- X;;EVENT-QUEUE-RECORD1 = The first event queue record
- X;;EVENT-QUEUE-RECORD2 = The second event queue record
- X(define (collision-time-<? event-queue-record1 event-queue-record2)
- X (time-<?
- X (event-queue-record-collision-time
- X event-queue-record1)
- X (event-queue-record-collision-time
- X event-queue-record2)))
- X
- X;;TIME-<? is a predicate which returns true if the first time is smaller than
- X;;the second. '() represents a time infinitly large.
- X(define (time-<? time1 time2)
- X (if (null? time1)
- X #f
- X (if (null? time2)
- X #t
- X (< time1 time2))))
- X
- X;;SQUARE returns the square of its argument
- X(define (square x)
- X (* x x))
- X
- X
- X;;BALL-BALL-COLLISION-TIME returns the time at which the two given balls would
- X;;collide if neither interacted with any other objects, '() if never. This
- X;;calculation is performed by setting the distance between the balls to the sum
- X;;of their radi and solving for the contact time.
- X;;BALL1 = The first ball
- X;;BALL2 = The second ball
- X(define (ball-ball-collision-time ball1 ball2)
- X (let ((delta-x-velocity ;Cache the difference in the ball's
- X ( - (ball-x-velocity ball2) ;velocities,
- X (ball-x-velocity ball1)))
- X (delta-y-velocity
- X ( - (ball-y-velocity ball2)
- X (ball-y-velocity ball1)))
- X (radius-sum ;the sum of their radi,
- X (+ (ball-radius ball1)
- X (ball-radius ball2)))
- X (alpha-x ;and common subexpressions in the time
- X (- ;equation
- X (- (ball-collision-x-position
- X ball2)
- X (ball-collision-x-position
- X ball1))
- X (-
- X (* (ball-x-velocity ball2)
- X (ball-collision-time
- X ball2))
- X (* (ball-x-velocity ball1)
- X (ball-collision-time
- X ball1)))))
- X (alpha-y
- X (-
- X (- (ball-collision-y-position
- X ball2)
- X (ball-collision-y-position
- X ball1))
- X (-
- X (* (ball-y-velocity ball2)
- X (ball-collision-time
- X ball2))
- X (* (ball-y-velocity ball1)
- X (ball-collision-time
- X ball1))))))
- X (let* ((delta-velocity-magnitude-squared
- X (+ (square
- X delta-x-velocity)
- X (square
- X delta-y-velocity)))
- X (discriminant
- X (- (* (square radius-sum)
- X delta-velocity-magnitude-squared)
- X (square
- X (- (* delta-y-velocity
- X alpha-x)
- X (* delta-x-velocity
- X alpha-y))))))
- X
- X
- X (if (or (negative? discriminant) ;If the balls don't colloide:
- X (zero?
- X delta-velocity-magnitude-squared))
- X '() ;Return infinity
- X (let ((time ;Else, calculate the collision time
- X (/
- X (- 0
- X (+ (sqrt discriminant)
- X (+
- X (* delta-x-velocity
- X alpha-x)
- X (* delta-y-velocity
- X alpha-y))))
- X (+ (square
- X delta-x-velocity)
- X (square
- X delta-y-velocity)))))
- X (if (and ;If the balls collide in the future:
- X (time-<?
- X (ball-collision-time
- X ball1)
- X time)
- X (time-<?
- X (ball-collision-time
- X ball2)
- X time))
- X time ;Return the collision time
- X '())))))) ;Else, return that they never collide
- X
- X;;BALL-BUMPER-COLLISION-TIME returns the time at which the given ball would
- X;;collide with the given bumper if the ball didn't interacted with any other
- X;;objects, '() if never. This is done by first calculating the time at which
- X;;the ball would collide with a bumper of infinite length and then checking if
- X;;the collision position represents a portion of the actual bumper.
- X;;BALL = The ball
- X;;BUMPER = The bumper
- X(define (ball-bumper-collision-time ball bumper)
- X (let ((delta-x-bumper ;Collision time with the bumper of
- X (- (bumper-x2 bumper) ;infinite extent is calculated by
- X (bumper-x1 bumper))) ;setting the distance between the ball
- X (delta-y-bumper ;and the bumper to be the radius of the
- X (- (bumper-y2 bumper) ;ball and solving for the time. The
- X (bumper-y1 bumper)))) ;distance is calculated by |aXb|/|a|,
- X (let ((bumper-length-squared ;where 'a' is the vector from one end
- X (+ (square delta-x-bumper) ;of the bumper to the other and 'b' is
- X (square delta-y-bumper))) ;the vector from the first end of the
- X (denominator ;bumper to the center of the ball
- X (- (* (ball-y-velocity ball)
- X delta-x-bumper)
- X (* (ball-x-velocity ball)
- X delta-y-bumper))))
- X (if (zero? denominator) ;If the ball's motion is parallel to
- X ;the bumper:
- X '() ;Return infinity
- X (let ((delta-t ;Calculate the collision time
- X (-
- X (/
- X (+
- X (*
- X (- (ball-collision-x-position
- X ball)
- X (bumper-x1 bumper))
- X delta-y-bumper)
- X (*
- X (- (ball-collision-y-position
- X ball)
- X (bumper-y1 bumper))
- X delta-x-bumper))
- X denominator)
- X (/
- X (* (ball-radius
- X ball)
- X (sqrt
- X bumper-length-squared))
- X (abs denominator)))))
- X (if (not (positive? ;If the ball is moving away from the
- X delta-t)) ;bumper:
- X '() ;Return infinity
- X
- X
- X (let ((ball-x-contact ;Whether the ball contacts the actual
- X (+ (ball-collision-x-position ;bumper of limited extent
- X ball) ;will be determined by comparing |b.a|
- X (* (ball-x-velocity ;with |a|^2
- X ball)
- X delta-t)))
- X (ball-y-contact
- X (+ (ball-collision-y-position
- X ball)
- X (* (ball-y-velocity
- X ball)
- X delta-t))))
- X (let ((delta-x-ball
- X (- ball-x-contact
- X (bumper-x1
- X bumper)))
- X (delta-y-ball
- X (- ball-y-contact
- X (bumper-y1
- X bumper))))
- X (let ((dot-product
- X (+
- X (* delta-x-ball
- X delta-x-bumper)
- X (* delta-y-ball
- X delta-y-bumper))))
- X (if (or ;If the ball misses the bumper on
- X (negative? ;either end:
- X dot-product)
- X (> dot-product
- X bumper-length-squared))
- X '() ;Return infinity
- X (+ delta-t ;Else, return the contact time
- X (ball-collision-time
- X ball))))))))))))
- X
- X
- X;;BALL-COLLISION-PROCEDURE calculates the new velocities of the given balls
- X;;based on their collision at the given time. Also, tells all other balls
- X;;about the new trajectories of these balls so they can update their event
- X;;queues
- X;;BALL1 = The first ball
- X;;BALL2 = The second ball
- X;;COLLISION-TIME = The collision time
- X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
- X(define (ball-collision-procedure ball1 ball2 collision-time
- X global-event-queue)
- X (queue-remove ;Remove the earliest event associated
- X (ball-global-event-queue-record ;with each ball from the global event
- X ball1)) ;queue
- X (queue-remove
- X (ball-global-event-queue-record
- X ball2))
- X (let ((ball1-collision-x-position ;Calculate the positions of both balls
- X (+ (ball-collision-x-position ;when they collide
- X ball1)
- X (* (ball-x-velocity
- X ball1)
- X (- collision-time
- X (ball-collision-time
- X ball1)))))
- X (ball1-collision-y-position
- X (+ (ball-collision-y-position
- X ball1)
- X (* (ball-y-velocity
- X ball1)
- X (- collision-time
- X (ball-collision-time
- X ball1)))))
- X (ball2-collision-x-position
- X (+ (ball-collision-x-position
- X ball2)
- X (* (ball-x-velocity
- X ball2)
- X (- collision-time
- X (ball-collision-time
- X ball2)))))
- X (ball2-collision-y-position
- X (+ (ball-collision-y-position
- X ball2)
- X (* (ball-y-velocity
- X ball2)
- X (- collision-time
- X (ball-collision-time
- X ball2))))))
- X (let ((delta-x ;Calculate the displacements of the
- X (- ball2-collision-x-position ;centers of the two balls
- X ball1-collision-x-position))
- X (delta-y
- X (- ball2-collision-y-position
- X ball1-collision-y-position)))
- X
- X
- X (let* ((denominator ;Calculate the angle of the line
- X (sqrt (+ (square ;joining the centers at the collision
- X delta-x) ;time with the x-axis (this line is
- X (square ;the normal to the balls at the
- X delta-y)))) ;collision point)
- X (cos-theta
- X (/ delta-x denominator))
- X (sin-theta
- X (/ delta-y denominator)))
- X (let ((ball1-old-normal-velocity ;Convert the velocities of the balls
- X (+ (* (ball-x-velocity ;into the coordinate system defined by
- X ball1) ;the normal and tangential lines at
- X cos-theta) ;the collision point
- X (* (ball-y-velocity
- X ball1)
- X sin-theta)))
- X (ball1-tang-velocity
- X (- (* (ball-y-velocity
- X ball1)
- X cos-theta)
- X (* (ball-x-velocity
- X ball1)
- X sin-theta)))
- X (ball2-old-normal-velocity
- X (+ (* (ball-x-velocity
- X ball2)
- X cos-theta)
- X (* (ball-y-velocity
- X ball2)
- X sin-theta)))
- X (ball2-tang-velocity
- X (- (* (ball-y-velocity
- X ball2)
- X cos-theta)
- X (* (ball-x-velocity
- X ball2)
- X sin-theta)))
- X (mass1 (ball-mass
- X ball1))
- X (mass2 (ball-mass
- X ball2)))
- X (let ((ball1-new-normal-velocity ;Calculate the new velocities
- X (/ ;following the collision (the
- X (+ ;tangential velocities are unchanged
- X (* ;because the balls are assumed to be
- X (* 2 ;frictionless)
- X mass2)
- X ball2-old-normal-velocity)
- X (*
- X (- mass1 mass2)
- X ball1-old-normal-velocity))
- X (+ mass1 mass2)))
- X
- X
- X (ball2-new-normal-velocity
- X (/
- X (+
- X (*
- X (* 2
- X mass1)
- X ball1-old-normal-velocity)
- X (*
- X (- mass2 mass1)
- X ball2-old-normal-velocity))
- X (+ mass1 mass2))))
- X (set-ball-x-velocity! ;Store data about the collision in the
- X ball1 ;structure for each ball after
- X (- (* ball1-new-normal-velocity ;converting the information back
- X cos-theta) ;to the x,y frame
- X (* ball1-tang-velocity
- X sin-theta)))
- X (set-ball-y-velocity!
- X ball1
- X (+ (* ball1-new-normal-velocity
- X sin-theta)
- X (* ball1-tang-velocity
- X cos-theta)))
- X (set-ball-x-velocity!
- X ball2
- X (- (* ball2-new-normal-velocity
- X cos-theta)
- X (* ball2-tang-velocity
- X sin-theta)))
- X (set-ball-y-velocity!
- X ball2
- X (+ (* ball2-new-normal-velocity
- X sin-theta)
- X (* ball2-tang-velocity
- X cos-theta)))
- X (set-ball-collision-time!
- X ball1
- X collision-time)
- X (set-ball-collision-time!
- X ball2
- X collision-time)
- X (set-ball-collision-x-position!
- X ball1
- X ball1-collision-x-position)
- X (set-ball-collision-y-position!
- X ball1
- X ball1-collision-y-position)
- X (set-ball-collision-x-position!
- X ball2
- X ball2-collision-x-position)
- X (set-ball-collision-y-position!
- X ball2
- X ball2-collision-y-position))))))
- X
- X
- X (newline)
- X (display "Ball ")
- X (display (ball-number ball1))
- X (display " collides with ball ")
- X (display (ball-number ball2))
- X (display " at time ")
- X (display (ball-collision-time ball1))
- X (newline)
- X (display " Ball ")
- X (display (ball-number ball1))
- X (display " has a new velocity of ")
- X (display (ball-x-velocity ball1))
- X (display ",")
- X (display (ball-y-velocity ball1))
- X (display " starting at ")
- X (display (ball-collision-x-position ball1))
- X (display ",")
- X (display (ball-collision-y-position ball1))
- X (newline)
- X (display " Ball ")
- X (display (ball-number ball2))
- X (display " has a new velocity of ")
- X (display (ball-x-velocity ball2))
- X (display ",")
- X (display (ball-y-velocity ball2))
- X (display " starting at ")
- X (display (ball-collision-x-position ball2))
- X (display ",")
- X (display (ball-collision-y-position ball2))
- X
- X (recalculate-collisions ball1 global-event-queue)
- X (recalculate-collisions ball2 global-event-queue))
- X
- X
- X;;BUMPER-COLLISION-PROCEDURE calculates the new velocity of the given ball
- X;;following its collision with the given bumper at the given time. Also, tells
- X;;other balls about the new trajectory of the given ball so they can update
- X;;their event queues.
- X;;BALL = The ball
- X;;BUMPER = The bumper
- X;;COLLISION-TIME = The collision time
- X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
- X(define (bumper-collision-procedure ball bumper collision-time
- X global-event-queue)
- X (queue-remove ;Remove the earliest event associated
- X (ball-global-event-queue-record ;with the ball from the global event
- X ball)) ;queue
- X (let ((delta-x-bumper ;Compute the bumper's delta-x
- X (- (bumper-x2 bumper)
- X (bumper-x1 bumper)))
- X (delta-y-bumper ;delta-y
- X (- (bumper-y2 bumper)
- X (bumper-y1 bumper))))
- X (let ((bumper-length ;length
- X (sqrt
- X (+ (square
- X delta-x-bumper)
- X (square
- X delta-y-bumper)))))
- X (let ((cos-theta ;and cosine and sine of its angle with
- X (/ delta-x-bumper ;respect to the positive x-axis
- X bumper-length))
- X (sin-theta
- X (/ delta-y-bumper
- X bumper-length))
- X (x-velocity ;Cache the ball's velocity in the x,y
- X (ball-x-velocity ball)) ;frame
- X (y-velocity
- X (ball-y-velocity ball)))
- X (let ((tang-velocity ;Calculate the ball's velocity in the
- X (+ (* x-velocity ;bumper frame
- X cos-theta)
- X (* y-velocity
- X sin-theta)))
- X (normal-velocity
- X (- (* y-velocity
- X cos-theta)
- X (* x-velocity
- X sin-theta))))
- X
- X
- X (set-ball-collision-x-position! ;Store the collision position
- X ball
- X (+ (ball-collision-x-position
- X ball)
- X (* (- collision-time
- X (ball-collision-time
- X ball))
- X (ball-x-velocity
- X ball))))
- X (set-ball-collision-y-position!
- X ball
- X (+ (ball-collision-y-position
- X ball)
- X (* (- collision-time
- X (ball-collision-time
- X ball))
- X (ball-y-velocity
- X ball))))
- X (set-ball-x-velocity! ;Calculate the new velocity in the
- X ball ;x,y frame based on the fact that
- X (+ (* tang-velocity ;tangential velocity is unchanged and
- X cos-theta) ;the normal velocity is inverted when
- X (* normal-velocity ;the ball collides with the bumper
- X sin-theta)))
- X (set-ball-y-velocity!
- X ball
- X (- (* tang-velocity
- X sin-theta)
- X (* normal-velocity
- X cos-theta)))
- X (set-ball-collision-time!
- X ball
- X collision-time)))))
- X (newline)
- X (display "Ball ")
- X (display (ball-number ball))
- X (display " collides with bumper ")
- X (display (bumper-number bumper))
- X (display " at time ")
- X (display (ball-collision-time ball))
- X (newline)
- X (display " Ball ")
- X (display (ball-number ball))
- X (display " has a new velocity of ")
- X (display (ball-x-velocity ball))
- X (display ",")
- X (display (ball-y-velocity ball))
- X (display " starting at ")
- X (display (ball-collision-x-position ball))
- X (display ",")
- X (display (ball-collision-y-position ball))
- X
- X (recalculate-collisions ball global-event-queue))
- X
- X
- X;;RECALCULATE-COLLISIONS removes all old collisions for the given ball from
- X;;all other balls' event queues and calcultes new collisions for these balls
- X;;and places them on the event queues. Also, updates the global event queue if
- X;;the recalculation of the collision effects the earliest collision for any
- X;;other balls.
- X;;BALL = The ball whose collisions are being recalculated
- X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball
- X(define (recalculate-collisions ball global-event-queue)
- X (clear-queue (ball-event-queue ;Clear the queue of events for this
- X ball)) ;ball as they have all changed
- X (let ((event-queue ;Calculate all ball collision events
- X (ball-event-queue ball))) ;with balls of lower number
- X (let ((ball-vector
- X (ball-ball-vector ball)))
- X (do ((i (-1+ (ball-number ball))
- X (-1+ i)))
- X ((negative? i))
- X (let ((ball2-queue-record
- X (vector-ref
- X ball-vector
- X i)))
- X (set-event-queue-record-collision-time!
- X ball2-queue-record
- X (ball-ball-collision-time
- X ball
- X (event-queue-record-object
- X ball2-queue-record)))
- X (queue-insert
- X event-queue
- X ball2-queue-record))))
- X (let ((bumper-vector ;Calculate all bumper collision events
- X (ball-bumper-vector ball)))
- X (do ((i (-1+ (vector-length
- X bumper-vector))
- X (-1+ i)))
- X ((negative? i))
- X (let ((bumper-queue-record
- X (vector-ref
- X bumper-vector
- X i)))
- X (set-event-queue-record-collision-time!
- X bumper-queue-record
- X (ball-bumper-collision-time
- X ball
- X (event-queue-record-object
- X bumper-queue-record)))
- X (queue-insert
- X event-queue
- X bumper-queue-record))))
- X
- X
- X (let ((global-queue-record ;Get the global event queue record
- X (ball-global-event-queue-record ;for this ball
- X ball)))
- X (set-event-queue-record-collision-time! ;Set the new earliest event time
- X global-queue-record ;for this ball
- X (if (empty-queue? event-queue)
- X '()
- X (event-queue-record-collision-time
- X (queue-smallest event-queue))))
- X (queue-insert ;Enqueue on the global event queue
- X global-event-queue ;the earliest event between this ball
- X global-queue-record))) ;and any ball of lower number or any
- X ;bumper
- X (for-each ;For each ball on the ball list:
- X (lambda (ball2)
- X (let ((ball2-event-queue
- X (ball-event-queue ball2)))
- X (let ((alter-global-event-queue? ;Set flag to update global event queue
- X (and ;if the earliest event for ball2 was
- X (not (empty-queue? ;with the deflected ball
- X ball2-event-queue))
- X (eq? ball
- X (event-queue-record-object
- X (queue-smallest
- X ball2-event-queue)))))
- X (ball-event-queue-record ;Get the queue record for the deflected
- X (vector-ref ;ball for this ball
- X (ball-ball-vector
- X ball2)
- X (ball-number ball))))
- X (queue-remove ;Remove the queue record for the
- X ball-event-queue-record) ;deflected ball
- X (set-event-queue-record-collision-time! ;Recalculate the collision
- X ball-event-queue-record ;time for this ball and the deflected
- X (ball-ball-collision-time ;ball
- X ball
- X ball2))
- X (queue-insert ;Enqueue the new collision event
- X ball2-event-queue
- X ball-event-queue-record)
- X (if (or alter-global-event-queue? ;If the earliest collision event for
- X (eq? ball ;this ball has changed:
- X (event-queue-record-object
- X (queue-smallest
- X ball2-event-queue))))
- X (let ((queue-record ;Remove the old event from the global
- X (ball-global-event-queue-record ;event queue and replace it
- X ball2))) ;with the new event
- X (set-event-queue-record-collision-time!
- X queue-record
- X (event-queue-record-collision-time
- X (queue-smallest
- X ball2-event-queue)))
- X (queue-remove
- X queue-record)
- X (queue-insert
- X global-event-queue
- X queue-record))))))
- X (ball-ball-list ball)))
- X
- X
- X;;SIMULATE performs the billiard ball simulation for the given ball list and
- X;;bumper list until the specified time.
- X;;BALL-LIST = A list of balls
- X;;BUMPER-LIST = A list of bumpers
- X;;END-TIME = The time at which the simulation is to terminate
- X(define (simulate ball-list bumper-list end-time)
- X (let ((num-of-balls ;Cache the number of balls and bumpers
- X (length ball-list))
- X (num-of-bumpers
- X (length bumper-list))
- X (global-event-queue ;Build the global event queue
- X (make-sorted-queue
- X collision-time-<?)))
- X (let ((complete-ball-vector ;Build a vector for the balls
- X (make-vector
- X num-of-balls)))
- X (let loop ((ball-num 0) ;For each ball:
- X (ball-list ball-list))
- X (if (not (null? ball-list))
- X (let ((ball (car ball-list)))
- X (set-ball-number! ;Store the ball's number
- X ball
- X ball-num)
- X (vector-set! ;Place it in the ball vector
- X complete-ball-vector
- X ball-num
- X ball)
- X (set-ball-ball-list! ;Save the list of balls with ball
- X ball ;numbers greater than the current ball
- X (cdr ball-list))
- X (display-ball-state
- X ball)
- X (loop
- X (1+ ball-num)
- X (cdr ball-list)))))
- X (let loop ((bumper-num 0) ;For each bumper:
- X (bumper-list
- X bumper-list))
- X (if (not (null? bumper-list))
- X (sequence
- X (set-bumper-number! ;Store the bumper's number
- X (car bumper-list)
- X bumper-num)
- X (display-bumper-state
- X (car bumper-list))
- X (loop
- X (1+ bumper-num)
- X (cdr bumper-list)))))
- X
- X (do ((ball-num 0 (1+ ball-num))) ;For each ball:
- X ((= ball-num num-of-balls))
- X (let* ((ball (vector-ref ;Cache a reference to the ball
- X complete-ball-vector
- X ball-num))
- X (ball-vector ;Build a vector for the queue records
- X (make-vector ;of balls with smaller numbers than
- X ball-num)) ;this ball
- X (bumper-vector ;Build a vector for the queue records
- X (make-vector ;of bumpers
- X num-of-bumpers))
- X (event-queue ;Build an event queue for this ball
- X (ball-event-queue
- X ball)))
- X (set-ball-ball-vector! ;Install the vector of ball queue
- X ball ;records
- X ball-vector)
- X (do ((i 0 (1+ i))) ;For each ball of smaller number than
- X ((= i ball-num)) ;the current ball:
- X (let* ((ball2 ;Cache the ball
- X (vector-ref
- X complete-ball-vector
- X i))
- X (queue-record ;Create a queue record for this ball
- X (make-event-queue-record ;based on the collision time
- X '() ;of the two balls
- X '()
- X ball2
- X (ball-ball-collision-time
- X ball
- X ball2))))
- X (vector-set! ;Install the queue record in the ball
- X ball-vector ;vector for this ball
- X i
- X queue-record)
- X (queue-insert ;Insert the queue record into the event
- X event-queue ;queue for this ball
- X queue-record)))
- X
- X (set-ball-bumper-vector! ;Install the vector of bumper queue
- X ball ;records
- X bumper-vector)
- X (let loop ((bumper-num 0)
- X (bumper-list
- X bumper-list))
- X (if (not (null? bumper-list))
- X (let* ((bumper ;Cache the bumper
- X (car
- X bumper-list))
- X (queue-record ;Create a queue record for this bumper
- X (make-event-queue-record ;based on the collision time
- X '() ;of the current ball and this bumper
- X '()
- X bumper
- X (ball-bumper-collision-time
- X ball
- X bumper))))
- X (vector-set! ;Install the queue record in the bumper
- X bumper-vector ;vector for this ball
- X bumper-num
- X queue-record)
- X (queue-insert ;Insert the queue record into the event
- X event-queue ;queue for this ball
- X queue-record)
- X (loop
- X (1+ bumper-num)
- X (cdr bumper-list)))))
- X (let ((queue-record ;Build a global event queue record for
- X (make-event-queue-record ;the earliest event on this ball's
- X '() ;event queue
- X '()
- X ball
- X (if (empty-queue?
- X event-queue)
- X '()
- X (event-queue-record-collision-time
- X (queue-smallest
- X event-queue))))))
- X (set-ball-global-event-queue-record! ;Store this queue record in
- X ball ;the frame for this ball
- X queue-record)
- X (queue-insert ;Insert this queue record in the global
- X global-event-queue ;event queue
- X queue-record)))))
- X (actually-simulate ;Now that all of the data structures
- X global-event-queue ;have been built, actually start the
- X end-time))) ;simulation
- X
- X
- X;;DISPLAY-BALL-STATE displays the ball number, mass, radius, position, and
- X;;velocity of the given ball
- X;;BALL = The ball whose state is to be displayed
- X(define (display-ball-state ball)
- X (newline)
- X (display "Ball ")
- X (display (ball-number ball))
- X (display " has mass ")
- X (display (ball-mass ball))
- X (display " and radius ")
- X (display (ball-radius ball))
- X (newline)
- X (display " Its position at time ")
- X (display (ball-collision-time ball))
- X (display " was ")
- X (display (ball-collision-x-position ball))
- X (display ",")
- X (display (ball-collision-y-position ball))
- X (display " and its velocity is ")
- X (display (ball-x-velocity ball))
- X (display ",")
- X (display (ball-y-velocity ball)))
- X
- X;;DISPLAY-BUMPER-STATE displays the bumper number and position of the given
- X;;bumper
- X;;BUMPER = The bumper whose state is to be displayed
- X(define (display-bumper-state bumper)
- X (newline)
- X (display "Bumper ")
- X (display (bumper-number bumper))
- X (display " extends from ")
- X (display (bumper-x1 bumper))
- X (display ",")
- X (display (bumper-y1 bumper))
- X (display " to ")
- X (display (bumper-x2 bumper))
- X (display ",")
- X (display (bumper-y2 bumper)))
- X
- X
- X;;ACTUALLY-SIMULATE performs the actual billiard ball simulation
- X;;GLOBAL-EVENT-QUEUE = The global queue of earliest events for each ball.
- X;; Contains a single event for each ball which is the
- X;; earliest collision it would have with a ball of a
- X;; smaller number or a bumper, if no other collisions took
- X;; place first.
- X;;END-TIME = The time at which the simulation should be terminated
- X(define (actually-simulate global-event-queue end-time)
- X (letrec ((loop
- X (lambda ()
- X (let* ((record ;Get the globally earliest event and
- X (queue-smallest ;its time
- X global-event-queue))
- X (collision-time
- X (event-queue-record-collision-time
- X record)))
- X (if (not ;If this event happens before the
- X (time-<? ;simulation termination time:
- X end-time
- X collision-time))
- X (let* ((ball ;Get the ball involved in the event,
- X (event-queue-record-object
- X record))
- X (ball-queue ;the queue of events for that ball,
- X (ball-event-queue
- X ball))
- X (other-object ;and the first object with which the
- X (event-queue-record-object ;ball interacts
- X (queue-smallest
- X ball-queue))))
- X ((simulation-object-collision-procedure ;Process this
- X other-object) ;globally earliest collision
- X ball
- X other-object
- X collision-time
- X global-event-queue)
- X (loop))))))) ;Process the next interaction
- X (loop)))
- X
- X
- X(require 'cscheme)
- X(set! autoload-notify? #f)
- X
- X (simulate
- X (list (make-ball 2 1 9 5 -1 -1)
- X (make-ball 4 2 2 5 1 -1))
- X (list (make-bumper 0 0 0 10)
- X (make-bumper 0 0 10 0)
- X (make-bumper 0 10 10 10)
- X (make-bumper 10 0 10 10))
- X 100)
- END_OF_tst/billiard
- if test 46118 -ne `wc -c <tst/billiard`; then
- echo shar: \"tst/billiard\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f lib/xlib/examples/properties -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"lib/xlib/examples/properties\"
- else
- echo shar: Extracting \"lib/xlib/examples/properties\" \(969 characters\)
- sed "s/^X//" >lib/xlib/examples/properties <<'END_OF_lib/xlib/examples/properties'
- X;;; -*-Scheme-*-
- X;;;
- X;;; Display all properties of all windows (with name, type, format,
- X;;; and data).
- X
- X(require 'xlib)
- X
- X(define (properties)
- X (let ((dpy (open-display)))
- X (unwind-protect
- X (let* ((w (car (query-tree (display-root-window dpy))))
- X (l (map (lambda (win) (cons win (list-properties win)))
- X (cons (display-root-window dpy) (vector->list w))))
- X (tab (lambda (obj n)
- X (let* ((s (format #f "~s" obj))
- X (n (- n (string-length s))))
- X (display s)
- X (if (positive? n)
- X (do ((i 0 (1+ i))) ((= i n)) (display #\space)))))))
- X (for-each
- X (lambda (w)
- X (format #t "Window ~s:~%" (car w))
- X (for-each
- X (lambda (p)
- X (tab (atom-name dpy p) 20)
- X (display "= ")
- X (let ((p (get-property (car w) p #f 0 20 #f)))
- X (tab (atom-name dpy (car p)) 18)
- X (tab (cadr p) 3)
- X (format #t "~s~%" (caddr p))))
- X (vector->list (cdr w)))
- X (newline))
- X l))
- X (close-display dpy))))
- X
- X(properties)
- END_OF_lib/xlib/examples/properties
- if test 969 -ne `wc -c <lib/xlib/examples/properties`; then
- echo shar: \"lib/xlib/examples/properties\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f lib/xlib/examples/track -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"lib/xlib/examples/track\"
- else
- echo shar: Extracting \"lib/xlib/examples/track\" \(1062 characters\)
- sed "s/^X//" >lib/xlib/examples/track <<'END_OF_lib/xlib/examples/track'
- X;;; -*-Scheme-*-
- X
- X(require 'xlib)
- X
- X(define (track)
- X (let* ((dpy (open-display))
- X (root (display-root-window dpy))
- X (gc (make-gcontext (window root)
- X (function 'xor)
- X (foreground (black-pixel dpy))
- X (subwindow-mode 'include-inferiors)))
- X (lx 0) (ly 0) (lw 0) (lh 0)
- X (move-outline
- X (lambda (x y w h)
- X (if (not (and (= x lx) (= y ly) (= w lw) (= h lh)))
- X (begin
- X (draw-rectangle root gc lx ly lw lh)
- X (draw-rectangle root gc x y w h)
- X (set! lx x) (set! ly y)
- X (set! lw w) (set! lh h))))))
- X (unwind-protect
- X (case (grab-pointer root #f '(pointer-motion button-press)
- X #f #f 'none 'none 'now)
- X (success
- X (with-server-grabbed dpy
- X (draw-rectangle root gc lx ly lw lh)
- X (display-flush-output dpy)
- X (handle-events dpy
- X (motion-notify
- X (lambda (event root win subwin time x y . rest)
- X (move-outline x y 300 300) #f))
- X (else (lambda args #t)))))
- X (else
- X (format #t "Not grabbed!~%")))
- X (begin
- X (draw-rectangle root gc lx ly lw lh)
- X (close-display dpy)))))
- X
- X(track)
- END_OF_lib/xlib/examples/track
- if test 1062 -ne `wc -c <lib/xlib/examples/track`; then
- echo shar: \"lib/xlib/examples/track\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f lib/xlib/examples/picture -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"lib/xlib/examples/picture\"
- else
- echo shar: Extracting \"lib/xlib/examples/picture\" \(2425 characters\)
- sed "s/^X//" >lib/xlib/examples/picture <<'END_OF_lib/xlib/examples/picture'
- X;;; -*-Scheme-*-
- X
- X;;; -*- Mode:Lisp; Package:XLIB; Syntax:COMMON-LISP; Base:10; Lowercase:T -*-
- X
- X;;; CLX - Point Graphing demo program
- X
- X;;; Copyright (C) 1988 Michael O. Newton (newton@csvax.caltech.edu)
- X
- X;;; Permission is granted to any individual or institution to use, copy,
- X;;; modify, and distribute this software, provided that this complete
- X;;; copyright and permission notice is maintained, intact, in all copies and
- X;;; supporting documentation.
- X
- X;;; The author provides this software "as is" without express or
- X;;; implied warranty.
- X
- X;;; This routine plots the recurrance
- X;;; x <- y(1+sin(0.7x)) - 1.2(|x|)^.5
- X;;; y <- .21 - x
- X;;; As described in a ?? 1983 issue of the Mathematical Intelligencer
- X;;; It has ONLY been tested under X.V11R2 on a Sun3 running KCL
- X
- X(require 'xlib)
- X
- X(define (picture point-count)
- X (let* ((dpy (open-display))
- X (width 600)
- X (height 600)
- X (black (black-pixel dpy))
- X (white (white-pixel dpy))
- X (root (display-root-window dpy))
- X (win (make-window (parent root) (background-pixel white)
- X (event-mask '(exposure button-press))
- X (width width) (height height)))
- X (gc (make-gcontext (window win)
- X (background white) (foreground black))))
- X (map-window win)
- X (unwind-protect
- X (handle-events dpy
- X (expose
- X (lambda ignore
- X (clear-window win)
- X (draw-points win gc point-count 0.0 0.0 (* width 0.5) (* height 0.5))
- X (draw-poly-text win gc 10 10 (translate "Click a button to exit")
- X '1-byte)
- X #f))
- X (else (lambda ignore #t)))
- X (close-display dpy))))
- X
- X;;; Draw points. These should maybe be put into a an array so that they do
- X;;; not have to be recomputed on exposure. X assumes points are in the range
- X;;; of width x height, with 0,0 being upper left and 0,H being lower left.
- X;;; x <- y(1+sin(0.7x)) - 1.2(|x|)^.5
- X;;; y <- .21 - x
- X;;; hw and hh are half-width and half-height of screen
- X
- X(define (draw-points win gc count x y hw hh)
- X (if (zero? (modulo count 100))
- X (display-flush-output (window-display win)))
- X (if (not (zero? count))
- X (let ((xf (floor (* (+ 1.2 x) hw ))) ; These lines center the picture
- X (yf (floor (* (+ 0.5 y) hh ))))
- X (draw-point win gc xf yf)
- X (draw-points win gc (1- count)
- X (- (* y (1+ (sin (* 0.7 x)))) (* 1.2 (sqrt (abs x))))
- X (- 0.21 x)
- X hw hh))))
- X
- X(define (translate string)
- X (list->vector (map char->integer (string->list string))))
- X
- X(picture 10000)
- END_OF_lib/xlib/examples/picture
- if test 2425 -ne `wc -c <lib/xlib/examples/picture`; then
- echo shar: \"lib/xlib/examples/picture\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f lib/xlib/examples/useful -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"lib/xlib/examples/useful\"
- else
- echo shar: Extracting \"lib/xlib/examples/useful\" \(567 characters\)
- sed "s/^X//" >lib/xlib/examples/useful <<'END_OF_lib/xlib/examples/useful'
- X;;; -*-Scheme-*-
- X
- X(require 'xlib)
- X
- X(define dpy
- X (open-display))
- X
- X(define (f)
- X (display-wait-output dpy #t))
- X
- X(define root
- X (display-root-window dpy))
- X
- X(define cmap
- X (display-colormap dpy))
- X
- X(define white (white-pixel dpy))
- X(define black (black-pixel dpy))
- X
- X(define rgb-white (query-color cmap white))
- X(define rgb-black (query-color cmap black))
- X
- X(define win
- X (make-window (parent root)
- X (width 300) (height 300)
- X (background-pixel white)))
- X
- X(define gc (make-gcontext
- X (window win)
- X (background white) (foreground black)))
- X
- X(map-window win)
- END_OF_lib/xlib/examples/useful
- if test 567 -ne `wc -c <lib/xlib/examples/useful`; then
- echo shar: \"lib/xlib/examples/useful\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f lib/xlib/pixel.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"lib/xlib/pixel.c\"
- else
- echo shar: Extracting \"lib/xlib/pixel.c\" \(1332 characters\)
- sed "s/^X//" >lib/xlib/pixel.c <<'END_OF_lib/xlib/pixel.c'
- X#include "xlib.h"
- X
- XGeneric_Predicate (Pixel);
- X
- XGeneric_Simple_Equal (Pixel, PIXEL, pix);
- X
- XGeneric_Print (Pixel, "#[pixel 0x%lx]", PIXEL(x)->pix);
- X
- XObject Make_Pixel (val) unsigned long val; {
- X register char *p;
- X Object pix;
- X
- X pix = Find_Object (T_Pixel, (GENERIC)0, Match_X_Obj, val);
- X if (Nullp (pix)) {
- X p = Get_Bytes (sizeof (struct S_Pixel));
- X SET (pix, T_Pixel, (struct S_Pixel *)p);
- X PIXEL(pix)->tag = Null;
- X PIXEL(pix)->pix = val;
- X Register_Object (pix, (GENERIC)0, (PFO)0, 0);
- X }
- X return pix;
- X}
- X
- Xunsigned long Get_Pixel (p) Object p; {
- X Check_Type (p, T_Pixel);
- X return PIXEL(p)->pix;
- X}
- X
- Xstatic Object P_Pixel_Value (p) Object p; {
- X return Make_Unsigned ((unsigned)Get_Pixel (p));
- X}
- X
- Xstatic Object P_Black_Pixel (d) Object d; {
- X Check_Type (d, T_Display);
- X return Make_Pixel (BlackPixel (DISPLAY(d)->dpy,
- X DefaultScreen (DISPLAY(d)->dpy)));
- X}
- X
- Xstatic Object P_White_Pixel (d) Object d; {
- X Check_Type (d, T_Display);
- X return Make_Pixel (WhitePixel (DISPLAY(d)->dpy,
- X DefaultScreen (DISPLAY(d)->dpy)));
- X}
- X
- Xinit_xlib_pixel () {
- X Generic_Define (Pixel, "pixel", "pixel?");
- X Define_Primitive (P_Pixel_Value, "pixel-value", 1, 1, EVAL);
- X Define_Primitive (P_Black_Pixel, "black-pixel", 1, 1, EVAL);
- X Define_Primitive (P_White_Pixel, "white-pixel", 1, 1, EVAL);
- X}
- END_OF_lib/xlib/pixel.c
- if test 1332 -ne `wc -c <lib/xlib/pixel.c`; then
- echo shar: \"lib/xlib/pixel.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 9 \(of 14\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-