;; 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)) ;; FractalBase?: Fractal --> boolean ;; Type-checker for a base case fractal ;; Need to augment this code if more base case types are added. (define (FractalBase? fractal) (SierpBase? fractal)) ;; A list-of-Fractal is a list and is either ;; -- empty ;; -- (cons Sierp list-of-Fractal) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions for creating Sierpinski gaskets. ;; 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))))) ;; 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))) ;; make-nextSierp: SierpBase --> list-of-Fractal ;; Takes a SierpBase and returns a list-of-Fractal filled with 3 SierpBases ;; where the SierpBases are formed from the vertices of the input ;; SierpBase and the mid-points of its sides. ;; The 3 SierpBases are in clockwise order from the top of the input SierpBase. (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))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fractal Visitor Framework ;; A visitor to a Frac tal ;; fBase: FracBase any1 --> any2 ;; fInduct: list-of-Frac any1 --> any2 (define-struct FractalVisitor (fBase fInduct)) ;; fracExecute: Fractal FracVisitor any1 --> any2 ;; Accepts the FractalVisitor on the Fractal, ;; calling the appropriate case of the visitor. (define (fracExecute frac fVisitor param) (cond [(FractalBase? frac) ((FractalVisitor-fBase fVisitor) frac param)] [(list? frac) ((FractalVisitor-fInduct fVisitor) frac param)])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; NatNum Visitor Framework ;; Not used in this file, but provided as an example. ;; 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)] [(positive? n) ((NVisitor-fNZ nVisitor) n param)])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Sierpinski drawing ;; draw-sierpBase: SierpBase --> boolean ;; Draws a SierpBase on the output canvas. (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)))) (define drawSierpVisitor (make-FractalVisitor (lambda (sierpBase param) (draw-sierpBase sierpBase)) (lambda (seirpInd param) (map (lambda (s) (fracExecute s drawSierpVisitor param)) seirpInd)))) (define nextSierpVisitor (make-FractalVisitor (lambda (sierpBase param) (make-nextSierp sierpBase)) (lambda (sierpInd param) (map (lambda (s) (fracExecute s nextSierpVisitor param)) sierpInd)))) ;; creates an n'th level Sierpinski gasket (define nextNSierpVisitor (make-NVisitor ;; makes a full size triangle (lambda (n param) (make-FullSizeSierp width)) ;; Grows the recursive result. (lambda (n param) (fracExecute (nExecute (sub1 n) nextNSierpVisitor param) nextSierpVisitor param)))) ;; Factory for making fractals (define-struct FractalFactory (baseVal indVisitor)) (define (make-SierpFactory width) (make-FractalFactory (make-FullSizeSierp width) nextSierpVisitor)) ;; creates an n'th level Fractal (define nextNFractalVisitor (make-NVisitor ;; makes a full size triangle (lambda (n factory) (FractalFactory-baseVal factory)) ;; Grows the recursive result. (lambda (n factory) (fracExecute (nExecute (sub1 n) nextNFractalVisitor factory) (FractalFactory-indVisitor factory) factory)))) "Sierp test cases:" (define width 500) (define s1 (make-FullSizeSierp width)) (define s1_next (make-nextSierp s1)) ;;(draw-sierpBase s1) ;;(map draw-sierpBase s1_next) ;;(fracExecute s1 drawSierpVisitor null) ;;(fracExecute s1_next drawSierpVisitor null) ;;(fracExecute s1 nextSierpVisitor null) ;;(fracExecute s1_next nextSierpVisitor null) (define s3 (fracExecute (fracExecute s1_next nextSierpVisitor null) nextSierpVisitor null)) (start width width) (define result1 (fracExecute s3 drawSierpVisitor null)) (start width width) (define result2 (fracExecute (nExecute 7 nextNSierpVisitor null) drawSierpVisitor null)) (start width width) (define result3 (fracExecute (nExecute 7 nextNFractalVisitor (make-SierpFactory width)) drawSierpVisitor null))