;; 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)])) ;; A Fractal is a self-similar struture that is either ;; -- FactalBase ;; -- list-of-Fractal ;;The base-case Sierpinski structure is a FractalBase ;; has 3 posns in clockwise order from the top: ;; top, lower right, lower left (define-struct SierpBase (top lr ll)) (define (draw-sierpBase sierpBase) (and (draw-solid-line (SierpBase-top sierpBase) (SierpBase-lr sierpBase)) (draw-solid-line (SierpBase-lr sierpBase) (SierpBase-ll sierpBase)) (draw-solid-line (SierpBase-ll sierpBase) (SierpBase-top sierpBase)))) ;; A list-of-Fractal is a list and is either ;; -- empty ;; -- (cons Fractal list-of-Fractal) ;; getMidPt: posn posn --> posn ;; Returns the mid-point between two posns. (define (getMidPt p1 p2) (make-posn (/ (+ (posn-x p1) (posn-x p2)) 2) (/ (+ (posn-y p1) (posn-y p2)) 2))) (define (make-nextSierp sierpBase) (local [(define midTopLr (getMidPt (SierpBase-top sierpBase) (SierpBase-lr sierpBase))) (define midLrLl (getMidPt (SierpBase-lr sierpBase) (SierpBase-ll sierpBase))) (define midLlTop (getMidPt (SierpBase-ll sierpBase) (SierpBase-top sierpBase)))] (list (make-SierpBase (SierpBase-top sierpBase) midTopLr midLlTop) (make-SierpBase midTopLr (SierpBase-lr sierpBase) midLrLl) (make-SierpBase midLlTop midLrLl (SierpBase-ll sierpBase))))) ;; A factory to make a fractal, which has a ;; base case function and an inductive case function. ;; The base case takes a full width and returns a base case fractal ;; fBase: width --> Fractal ;; The inductive function takes a SierpBase and returns a list of SierpBases ;; finduct: SierpBase --> list-of-Fractal (define-struct FractalFactory (fBase fInduct)) ;; Makes an equilateral triangle with a base of width. This is a base case Sierpinski gasket (define (make-FullSizeSierp width) (local [(define width_2 (/ width 2)) (define root3 (sqrt 3))] (make-SierpBase (make-posn width_2 0) (make-posn 0 (* width_2 root3)) (make-posn width (* width_2 root3))))) ;; draw-Fractal: FractalBase FractalFactory number --> boolean ;; Regular template version to draw a Sierpinski gasket of a given level (define (draw-Fractal frac fracFac level) (cond [(zero? level) ((FractalFactory-fBase fracFac) frac)] [else (map (lambda (f) (draw-Fractal f fracFac (sub1 level))) ((FractalFactory-fInduct fracFac) frac))])) ;; make-drawFractalVisitor: FractalFactory --> NVisitor ;; makes a NatNum Visitor that will draw a n'th level ;; fractal using the functions in the supplied FractalFactory ;; The parameter is a base case fractal. (define (make-drawFracVisitor fracFac) (local [(define this (make-NVisitor ;; Uses the base case function of the factory ;; to draw the given fractal (lambda (n frac) ((FractalFactory-fBase fracFac) frac)) ;; Uses the inductive case function of the factory ;; to generate the next level of the fractal (lambda (n frac) (map (lambda (f) (nExecute (sub1 n) this f)) ((FractalFactory-fInduct fracFac) frac)))))] this)) "Sierp test cases:" (define width 500) (start width width) ;; A Sierpinski gasket fractal factory (define sFac (make-FractalFactory draw-sierpBase make-nextSierp)) (define s0 (make-FullSizeSierp width)) (define result1 (draw-Fractal s0 sFac 6)) (start width width) (define result2 (nExecute 7 (make-drawFracVisitor sFac) s0))