#lang racket
(require gigls/unsafe)

;;; Final Project
;;; CSC 151-01
;;; Erin Gaschott, Julia Hart, and David Cambronero

;DESIGN STATEMENT
;
; Through this project, we have decided to do a study of the interplay of color variations
; and shapes. We have decided to pursue this direction in an attempt to better understand
; the impact of color in our perception of art. To achieve this, changes in color value will
; play a key role. The image is divided into three layers: the background, the foreground
; shape, and the fractal shape. The foreground shape's color is complementary to
; that of the background and the fractal shape. It will be centered on the background,
; making the image balanced. Its symmetry will serve to create unity in the piece, as will
; the fractal shape. The latter one will be a suggestion of a rectangular shape, super-imposed on
; the foreground shape. Imposing itself on top of the foreground shape whilst contrasting its color through
; imitating the same hue as the background, the fractal shape is the emphasis of
; the composition. The colors of each one of these elements will be constructed in a manner
; that distinguishes them from each other while at the same time working together to achieve
; artistic harmony. Moreover, we believe that by using 
; three simple elements (the background, the foreground shape, and the fractal shape) paired with their modifications,
; a minimalistic approach to this art will allow the viewer to grasp more effectively the effects of the colors and
; the shapes in their perception, thereby censoring any possible distractants from the main purpose of our study.

;
;TECHNIQUE STATEMENT
; To facilitate the reading of the Technique statement, we have decided to break it down into sections:
;
;PRE-NOTES:
; The image onto which the art piece will be displayed is created through a call to (image (image-new width height))
;BACKGROUND
; In order to determine the background color, we have decided to use a combination of conditionals, predicates, and modulo.
; The (cond) procedure will pass the value of n to each of the tests until it fulfills one of these. 
; Each test has an assigned color value. Through the use of a (let) statement, the procedure is able to "rename" the
; assigned color "bg-color".In other word, If (equal? (mod n number) number) holds, then the assigned color to that test will be 
; named within the procedure "bg-color".
; Once "bg-color" is defined, the effect applied to this color is chosen through another (cond) statement that uses the same
; process. Each test has an assigned effect, if the test holds, the effect is applied to "bg-color". The possible
; effects are: SOLID COLOR, HORIZONTAL BLEND--WHITE TO COLOR, HORIZONTAL BLEND--COLOR TO WHITE, VERTICAL BLEND--WHITE TO COLOR,
; VERTICAL BLEND--COLOR TO WHITE, BLACK, WHITE, DIAGONAL BLEND 1, DIAGONAL BLEND 2, DIAGONAL BLEND 3, and DIAGONAL BLEND 4.

;Once the background color has been defined and undergone the effects, the Foreground is created.

;FOREGROUND
; In order to choose the foreground figure, the procedure uses a call to (cond). Using the same structure of
; (equal? (mod n number) number), each test has an assigned procedure that will result in specified shape. This shape is
; rendered using a call to (image-fill-selection!). The image and positions onto which the figure will be created have
; been defined already. As for the color of the resulting foreground shape, another let statement has been applied in which
; the color is defined as [shape-color (irgb-complement bg-color)]. This (shape-color) is then used as the parameter for
; (context-set-fgcolor!). Finally, a call to (image-fill-selection!) is made to finish the foreground shape.

;FRACTAL SHAPE
; To produce the third element of this image, a turtle is defined at the very beginning of the procedure. Nevertheless,
; no instructions are given to the turtle until after the foreground shape is finalized. To use the turtle, the procedure
; makes a call to (turtle-teleport!) to appropriately position the turtle as for its resulting figure to be super-imposed
; onto the foreground shape. As mentioned, the turtle's color is assigned bg-color through a call to (turtle-set-color!).
;In order for the turtle to make a rectangular-suggesting figure, the procedure calls
; an externally defined procedure named (turtle-sierpinski-rectangle!) which in turn makes a call to another externally
; defined procedure named (sierpinski-a!). The fractal level of the figure will depend on (increment (mod n 3)).
; We decided to define (Sierpinski-a!) and (turtle-sierpinski-rectangle!) outside of (image-series) because otherwise it
; the procedure's body would be very complicated to read.

;Final notes:
;There is a possibility of 1,155 different images with this algorithm because (* 7 11 5 3).




;;; Procedure:
;;;   image-series
;;; Parameters:
;;;   n, an integer
;;;   width, a positive integer
;;;   height, a positive integer
;;; Purpose:
;;;   Produces an interesting image that changes depending on n.
;;; Produces:
;;;   image, an image
;;; Preconditions:
;;;   [No additional]
;;; Postconditions:
;;;   The image produced is one of 1,155 unique options depending on the value
;;;    of n.
;;;   The image, including all elements, will be scaled to width and height.
(define image-series
  (lambda (n width height)
    (let*
        ([bg-color (cond
                     [(equal? (mod n 5) 0) (irgb 255 0 0)]
                     [(equal? (mod n 5) 1) (irgb 255 165 0)]
                     [(equal? (mod n 5) 2) (irgb 0 128 0)]
                     [(equal? (mod n 5) 3) (irgb 0 0 255)]
                     [else (irgb 128 0 128)])]
         [shape-color (irgb-complement bg-color)]
         [image (image-new width height)]
;Setting Background color as Blends (or not)
      [canvas
       (cond
        ;Solid color
        [(equal? (mod n 11) 0)
         (image-compute
          (lambda (col row)
            bg-color)
          width height)]
        ;horizontal Blend, White to Color
        [(equal? (mod n 11) 1)
         (image-compute
          (lambda (col row)
                  (irgb (+ 256 (* col (/ (- (irgb-red bg-color) 256) width)))
                        (+ 256 (* col (/ (- (irgb-green bg-color) 256) width)))
                        (+ 256 (* col (/ (- (irgb-blue bg-color) 256) width)))))
          width height)]
        ;Horizontal Blend, Color to White
        [(equal? (mod n 11) 2)
         (image-compute
          (lambda (col row)
                  (irgb (+ (irgb-red bg-color) (* col (/ (- 256 (irgb-red bg-color)) width)))
                        (+ (irgb-green bg-color) (* col (/ (- 256 (irgb-green bg-color)) width)))
                        (+ (irgb-blue bg-color) (* col (/ (- 256 (irgb-blue bg-color)) width)))))
          width height)]
        ;Vertical Blend, White to Color
        [(equal? (mod n 11) 3)
         (image-compute
          (lambda (col row)
                  (irgb (+ 256 (* row (/ (- (irgb-red bg-color) 256) height)))
                        (+ 256 (* row (/ (- (irgb-green bg-color) 256) height)))
                        (+ 256 (* row (/ (- (irgb-blue bg-color) 256) height)))))
          width height)]
        ;Vertical Blend, Color to White
        [(equal? (mod n 11) 4)
         (image-compute
          (lambda (col row)
                  (irgb (+ (irgb-red bg-color) (* row (/ (- 256 (irgb-red bg-color)) height)))
                        (+ (irgb-green bg-color) (* row (/ (- 256 (irgb-green bg-color)) height)))
                        (+ (irgb-blue bg-color) (* row (/ (- 256 (irgb-blue bg-color)) height)))))
          width height)]
        ;Black
        [(equal? (mod n 11) 5)
         (image-compute
          (lambda (col row)
            0)
          width height)]
        ;White
        [(equal? (mod n 11) 6)
         (image-compute
          (lambda (col row)
           (irgb 255 255 255))
          width height)]
        ;Diagonal Blend 1
        [(equal? (mod n 11) 7)
         (image-compute
          (lambda (col row)
                  (irgb (+ (irgb-red bg-color) (* row (/ (- 256 (irgb-red bg-color)) height)))
                        (+ (irgb-green bg-color) (* col (/ (- 256 (irgb-green bg-color)) width)))
                        (+ (irgb-blue bg-color) (* row (/ (- 256 (irgb-blue bg-color)) height)))))
          width height)]
        ;Diagonal Blend 2
        [(equal? (mod n 11) 8)
         (image-compute
          (lambda (col row)
                  (irgb (+ (irgb-red bg-color) (* row (/ (- 256 (irgb-red bg-color)) height)))
                        (+ (irgb-green bg-color) (* col (/ (- 256 (irgb-green bg-color)) width)))
                        (+ (irgb-blue bg-color) (* col (/ (- 256 (irgb-blue bg-color)) width)))))
          width height)]
        ;Diagonal Blend 3
        [(equal? (mod n 11) 9)
         (image-compute
          (lambda (col row)
                  (irgb (+ (irgb-red bg-color) (* col (/ (- 256 (irgb-red bg-color)) width)))
                        (+ (irgb-green bg-color) (* row (/ (- 256 (irgb-green bg-color)) height)))
                        (+ (irgb-blue bg-color) (* row (/ (- 256 (irgb-blue bg-color)) height)))))
          width height)]
        ;Diagonal Blend 4
        [else
         (image-compute
          (lambda (col row)
            (irgb (+ (irgb-red bg-color) (* row (/ (- 256 (irgb-red bg-color)) height)))
                  (+ (irgb-green bg-color) (* row (/ (- 256 (irgb-green bg-color)) height)))
                  (+ (irgb-blue bg-color) (* col (/ (- 256 (irgb-blue bg-color)) width)))))
          width height)])]
      [turtle (turtle-new canvas)])
;Creating Foreground Shape
      (cond
        ;Triangle
        [(equal? (mod n 7) 0)
         (image-select-polygon! canvas REPLACE (position-new (* .5 width) (* .1 height))
                                (position-new (* .1 width) (* .9 height))
                                (position-new (* .9 width) (* .9 height)))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
        ;Rectange
        [(equal? (mod n 7) 1)
         (image-select-rectangle! canvas REPLACE (* .1 width) (* .1 height) (* .8 width) (* .8 height))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
        ;Pentagon
        [(equal? (mod n 7) 2)
         (image-select-polygon! canvas REPLACE (position-new (* .5 width) (* .1 height))
                                (position-new (* .9 width) (* .45 height))
                                (position-new (* .75 width) (* .9 height))
                                (position-new (* .25 width) (* .9 height))
                                (position-new (* .1 width) (* .45 height)))                   
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
        ;Hexagon
        [(equal? (mod n 7) 3)
         (image-select-polygon! canvas REPLACE (position-new (* .3 width) (* .1 height))
                                (position-new (* .7 width) (* .1 height))
                                (position-new (* .9 width) (* .5 height))
                                (position-new (* .7 width) (* .9 height))
                                (position-new (* .3 width) (* .9 height))
                                (position-new (* .1 width) (* .5 height)))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
        ;Heptagon
        [(equal? (mod n 7) 4)
         (image-select-polygon! canvas REPLACE (position-new (* .5 width) (* .1 height))
                                (position-new (* .8 width) (* .3 height))
                                (position-new (* .9 width) (* .6 height))
                                (position-new (* .7 width) (* .9 height))
                                (position-new (* .3 width) (* .9 height))
                                (position-new (* .1 width) (* .6 height))
                                (position-new (* .2 width) (* .3 height)))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
        ;Octogon
         [(equal? (mod n 7) 5)
         (image-select-polygon! canvas REPLACE (position-new (* .3 width) (* .1 height))
                                (position-new (* .7 width) (* .1 height))
                                (position-new (* .9 width) (* .3 height))
                                (position-new (* .9 width) (* .7 height))
                                (position-new (* .7 width) (* .9 height))
                                (position-new (* .3 width) (* .9 height))
                                (position-new (* .1 width) (* .7 height))
                                (position-new (* .1 width) (* .3 height)))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)]
         ;Nonogon
          [(equal? (mod n 7) 6)
         (image-select-polygon! canvas REPLACE (position-new (* .5 width) (* .1 height))
                                (position-new (* .8 width) (* .2 height))
                                (position-new (* .9 width) (* .45 height))
                                (position-new (* .85 width) (* .7 height))
                                (position-new (* .65 width) (* .9 height))
                                (position-new (* .35 width) (* .9 height))
                                (position-new (* .15 width) (* .7 height))
                                (position-new (* .1 width) (* .45 height))
                                (position-new (* .2 width) (* .2 height)))
         (context-set-fgcolor! shape-color)
         (image-fill-selection! canvas)])
      (image-select-nothing! canvas)
      (turtle-teleport! turtle (* .25 width) (* .25 height))
      (turtle-set-color! turtle bg-color)
      (turtle-sierpinski-rectangle! turtle (* .5 width) (* .5 height) (increment (mod n 3)))
      (image-show canvas))))



;;; Procedure:
;;;   sierpinski-a!
;;; Parameters:
;;;   turtle, a turtle
;;;   distance, a positive integer
;;;   n, a positive integer
;;; Purpose:
;;;   Produces a sierpinski fractal of n levels
;;; Produces:
;;;   [Nothing, called for side effects]
;;; Preconditions:
;;;   Must be called in conjunction with (image-show)
;;; Postconditions:
;;;   The sierpinski fractal is drawn by turtle, of the specified distance
;;;    and of n levels.

;We have taken this procedure from http://www.cs.grinnell.edu/~weinman/courses/CSC151/2014S/assignments/polygons-and-fractals.html
(define sierpinski-a!  
  (lambda (turtle distance n)
   (cond [(equal? n 0)
          (turtle-forward! turtle distance)]
         [else
          (turtle-turn! turtle 60)
          (sierpinski-b! turtle (/ distance 2) (- n 1))
          (turtle-turn! turtle -60)
          (sierpinski-a! turtle (/ distance 2) (- n 1))
          (turtle-turn! turtle -60)
          (sierpinski-b! turtle (/ distance 2) (- n 1))
          (turtle-turn! turtle 60)])))

;;; Procedure:
;;;   sierpinski-b!
;;; Parameters:
;;;   turtle, a turtle
;;;   distance, a positive integer
;;;   n, a positive integer
;;; Purpose:
;;;   Produces a sierpinski fractal of n levels
;;; Produces:
;;;   [Nothing, called for side effects]
;;; Preconditions:
;;;   Must be called in conjunction with (image-show)
;;; Postconditions:
;;;   The sierpinski fractal is drawn by turtle, of the specified distance
;;;    and of n levels.

;We have taken this procedure from http://www.cs.grinnell.edu/~weinman/courses/CSC151/2014S/assignments/polygons-and-fractals.html

(define sierpinski-b!
  (lambda (turtle distance n)
    (cond [(equal? n 0)
           (turtle-forward! turtle distance)]
          [else
           (turtle-turn! turtle -60)
           (sierpinski-a! turtle (/ distance 2) (- n 1))
           (turtle-turn! turtle 60)
           (sierpinski-b! turtle (/ distance 2) (- n 1))
           (turtle-turn! turtle 60)
           (sierpinski-a! turtle (/ distance 2) (- n 1))
           (turtle-turn! turtle -60)])))


;;; Procedure:
;;;   turtle-sierpinski-rectangle!
;;; Parameters:
;;;   turtle, a turtle
;;;   width, a positive integer
;;;   height, a positive integer
;;;   n, a positive integer
;;; Purpose:
;;;   Produces a shape drawn with a series of sierpinski fractals.
;;; Produces:
;;;   [nothing, called for side effects]
;;; Preconditions:
;;;   Must be called in conjunction with
;;; Postconditions:
;;;   The sierpinski rectangle-like figure is drawn by turtle, of the specified width
;;;    and height, and of n fractal levels.

;This is a modified version of David Cambronero's (turtle-sierpinski-polygon!) from his Assignment 7.
(define turtle-sierpinski-rectangle!
  (λ (turtle width height n)
    (repeat 2 (λ ()
    (sierpinski-a! turtle width n)
    (turtle-turn! turtle 90)
    (sierpinski-a! turtle height n)
    (turtle-turn! turtle 90)))))