;; Be sure to load the draw.ss teachpack! ;; TreeFractal ;; -- Line ;; -- Branch ;; A Line is a straight line ;; (make-Line posn posn) (define-struct Line (p1 p2)) ;; A Branch is a Line plus a list-of-TreeFractals ;; (make-Branch Line list-of-TreeFractal) (define-struct Branch (line loTF)) ;;A list-of-TreeFractal ;;--empty ;;--cons which has a first which is a Line and a rest, which is a list-of-TreeFractals ;; Visitor to a TreeFractal (define-struct TFVisitor (fLine fBranch)) (define (tfExecute tf visitor param) (cond [(Line? tf) ((TFVisitor-fLine visitor) tf param)] [(Branch? tf) ((TFVisitor-fBranch visitor) tf param)])) ;; make-xform: Line --> (posn --> Line) ;; creates a transformation that will translate a point referenced to (0, 1) ;; into the coordinate system defined by the given line as the unit length ;; along the y-axis. ;; The lambda takes in a point and returns a line that starts at the end of the ;; given line. (define (make-xform line) (local [(define p1x (posn-x (Line-p1 line))) (define p1y (posn-y (Line-p1 line))) (define p2x (posn-x (Line-p2 line))) (define p2y (posn-y (Line-p2 line))) (define dy (- p2y p1y)) (define dx (- p2x p1x))] (lambda (p) (local [(define x (posn-x p)) (define y (posn-y p))] (make-Line (Line-p2 line) (make-posn (+ p2x (+ (* dy x) (* dx y))) (+ p2y (- (* dy y) (* dx x))))))))) ;; defines the width and height of the canvas (define width 500) ;; defines the point at the center of the canvas (define center (make-posn (/ width 2) (/ width 2))) ;; toScreen: posn --> posn ;; translates a point in graph (mathematical)coordinates into a ;; point in the screen (how the points map to the actual screen) coordinates ;; where the origin is at the center of the canvas and positive y direction is ;; vertically up, not down. (define (toScreen p) (make-posn (+ (/ width 2) (posn-x p)) (+ (/ width 2) (- (posn-y p))))) ;; drawLine: Line color --> boolean ;; draws a line in given in graph coordinates ;; returns true if succesful ;; MODIFIED TO USE GUI-LIB.SCM (define (drawLine l color) ;; (draw-solid-line (toScreen (Line-p1 l)) (toScreen (Line-p2 l)) color)) (draw-solidline (toScreen (Line-p1 l)) (toScreen (Line-p2 l)))) ;; draws a first order branch (define (drawBranch b color) (and (drawLine (Branch-line b) color) (andmap (lambda (tf) (drawLine tf color)) (Branch-loTF b)))) ;; draws an arbitrary order TreeFractal (define drawTF (make-TFVisitor (lambda (tf color) (drawLine tf color)) (lambda (tf color) (and (drawLine (Branch-line tf) color) (andmap (lambda (tf) (tfExecute tf drawTF color)) (Branch-loTF tf)))))) ;; grows a TreeFractal based on the given list of prototype points. (define growTF (make-TFVisitor (lambda (tf refBranches) (nextBranch tf refBranches)) (lambda (tf refBranches) (make-Branch (Branch-line tf) (map (lambda (tf) (tfExecute tf growTF refBranches)) (Branch-loTF tf)))))) ;; nextBranch: Line list-of-posn --> Branch ;; Grows a Line into a Branch based on the supplied list of prototype points. (define (nextBranch line refBranches) (make-Branch line (map (make-xform line) refBranches))) ;; make-nextBranch: list-of-posn --> (Line --> Branch) ;; factory that takes a list of prototype points and returns a growing function (define (make-nextBranch refBranches) (lambda (line) (make-Branch line (map (make-xform line) refBranches)))) ;; grows a TreeFractal based on the given growing function. (define growTF2 (make-TFVisitor (lambda (tf nextBr) (nextBr tf)) (lambda (tf nextBr) (make-Branch (Branch-line tf) (map (lambda (tf) (tfExecute tf growTF2 nextBr)) (Branch-loTF tf)))))) ;; Visitor to a natural number ;; fBase: NatNum any1 --> any2 ;; fInduct: NatNum any1 --> any2 (define-struct NVisitor (fZero fNZ)) ;; accepts a visitor to a natural number. (define (nExecute n nVisitor param) (cond [(zero? n) ((NVisitor-fZero nVisitor) n param)] [else ((NVisitor-fNZ nVisitor) n param)])) ;;grows an n-level TreeFractal based on the supplied prototype list (define growNTF (make-NVisitor (lambda (n refBranches) (make-Line (make-posn 0 0) (make-posn 0 100))) (lambda (n refBranches) (tfExecute (nExecute (sub1 n) growNTF refBranches) growTF refBranches)))) ;;grows an n-level TreeFractal based on the supplied growing function (define growNTF2 (make-NVisitor (lambda (n nextBr) (make-Line (make-posn 0 0) (make-posn 0 100))) (lambda (n nextBr) (tfExecute (nExecute (sub1 n) growNTF2 nextBr) growTF2 nextBr)))) ;; make-multiNextBranch: list-of-list-of-posn --> (Line --> Branch) ;; factory that takes in a list of list of prototypes and returns a ;; growing function that will take a Line and return a Branch formed ;; by successively applying growing with all the prototype lists. (define (make-multiNextBranch loRefs) (lambda (line) (foldr (lambda (refBranches rr) (tfExecute rr growTF refBranches)) line loRefs)))