#lang scheme (require (planet wmfarr/simple-matrix:1:1/matrix)) (define (posn-distance p1 p2) (sqrt (+ (sqr (- (vector-ref p1 0) (vector-ref p2 0))) (sqr (- (vector-ref p1 1) (vector-ref p2 1)))))) (define-struct body (layer posn radius vel data) #:transparent) (define (body-step dx) (match-lambda [(and b (struct* body ([posn posn] [vel vel]))) (struct-copy body b [posn (vector-add posn (vector-scale vel dx))])])) (define (bodies-overlap? b1 b2) (define p1 (body-posn b1)) (define p2 (body-posn b2)) (define d (posn-distance p1 p2)) (or (< d (body-radius b1)) (< d (body-radius b2)))) (define (n2-collisions collide bodies) (define layer-hash (make-hash)) (define seen?-hash (make-hash)) (for ([b (in-list bodies)]) (hash-update! layer-hash (body-layer b) (curry list* b) empty)) (for/fold ([l empty]) ([(b1-layer fbodies) (in-hash layer-hash)]) (hash-set! seen?-hash b1-layer #t) (for/fold ([l l]) ([b1 (in-list fbodies)]) (for*/fold ([l l]) ([(b2-layer lbodies) (in-hash layer-hash)] #:when (not (hash-has-key? seen?-hash b2-layer)) [b2 (in-list lbodies)] #:when (bodies-overlap? b1 b2)) (list* (collide b1 b2) l))))) (define (vector-max v1 v2) (vector (max (vector-ref v1 0) (vector-ref v2 0)) (max (vector-ref v1 1) (vector-ref v2 1)))) (define (vector-min v1 v2) (vector (min (vector-ref v1 0) (vector-ref v2 0)) (min (vector-ref v1 1) (vector-ref v2 1)))) (define (hash-collisions collide bodies) (define-values (how-many max-p min-p) (for/fold ([how-many 0] [max-p (vector -inf.0 -inf.0)] [min-p (vector +inf.0 +inf.0)]) ([b (in-list bodies)]) (define bp (body-posn b)) (values (add1 how-many) (vector-max max-p bp) (vector-min min-p bp)))) (if (zero? how-many) empty (local [(define size-p (vector-sub max-p min-p))] (printf "~S~n" size-p) (n2-collisions collide bodies)))) (define (simulate collide bodies dx) (define new-bodies (map (body-step dx) bodies)) (values new-bodies (n2-collisions collide new-bodies))) (provide/contract [struct body ([layer symbol?] [posn (vector/c number? number?)] [radius number?] [vel (vector/c number? number?)] [data any/c])] [simulate ((body? body? . -> . any/c) (listof body?) number? . -> . (values (listof body?) (listof any/c)))])