;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;

;;  EXAMPLE USING PATH GROUPS AND VECTORS 

;;

;; To draw more complex images effiecently a number of

;; graphics paths can be drawn in a single operation.

;; It is also possible to move a group of paths in a single 

;; operation.

;;

;; This example makes use of several vector functions for

;; more efficient vector operation: 

;; vector= vector-rand vector- vector* 

;;

;; There are a number of further efficiencies that we

;; could add to this code: 

;; firstly, xpoints and ypoints could be declared globally

;; and reused instead of reallocating new vectors every time

;; loop is applied. 

;; 

;; vectors also allow for recycling of

;; elements (using vector-recycle), which can substantially reduce 

;; garbage collection, although be careful that each vector element

;; contains a unique scheme object reference or you will get unexpected 

;; results. you should be safe if you always allocate new vectors using 

;; make-vector-with-proc and (random). 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


; set up graphics including vectors for paths, points, colours, styes etc.

(define canvas (gfx:make-canvas))

(gfx:clear-canvas (now) canvas '(0 0 0 1)) ; black background 


(define nodes 200) ; number of squares to animate 

(define size 5) ; square size 


; setup paths at random coordinates between 100,100 and 200,200

(define paths (make-vector-with-proc nodes

                                     (lambda (i)

                                        (gfx:make-square (random 100 200)

                                                       (random 100 200)

                                                       size))))

; defaults for drawing path group

(define widths (make-vector nodes 1.0))

(define styles (make-vector nodes *gfx:stroke-path*)) ; stroke only 


; setup default colours 

(define fills (make-vector (* nodes 4))) ; we are not going to fill 

(define strokes (make-vector (* nodes 4)))

(math:vector= strokes 1.0 (list 0 nodes 4)) ; set red to 1.0 

(math:vector-rand strokes (list 1 nodes 4)) ; randomize green 

(math:vector= strokes 0.0 (list 2 nodes 4)) ; set blue to 0.0 

(math:vector= strokes 0.3 (list 3 nodes 4)) ; set alpha to 0.3 


; main animation loop

; NOTE: we could declare xpoints and ypoints globally and

; resuse these each time through loop in order to avoid

; constantly reallocating vector memory 

(define loop

   (lambda (time)

      (let ((xpoints (make-vector nodes))

            (ypoints (make-vector nodes)))

         (math:vector-rand xpoints) 

         (math:vector- xpoints 0.5) 

         (math:vector* xpoints 20.0)

         (math:vector-rand ypoints)

         (math:vector- ypoints 0.5)

         (math:vector* ypoints 20.0)

         (gfx:move-group time paths xpoints ypoints)

         (gfx:draw-group (+ time 5) canvas paths strokes fills widths styles)

         (callback (+ time 500) 'loop (+ time 2000)))))


; start 

(loop (now))