Fundamentals of Computer Science I (CS151.02 2007S)

Randomized Drawing

Summary: We consider ways in which we can use the random procedure to produce interesting images.

Contents:

Introduction

A number of artists, from the founders of the Dada movement to Jackson Pollock and beyond, have reveled in the images that can be created by random or unpredictable processes. The Dadaists employed random selection to write poetry and subconscious drawing to create images. Pollock threw paint with an expectation that interesting patterns would result. (And yes, those are incredible simplifications of the philosophies and techniques of these artists.)

Some Basic Procedures

We can use a number of simple techniques to generate such randomized art. What can we randomize? We can certainly choose a random color (and relatively easily), simply by choosing random red, green, and blue components.

;;; Procedure:
;;;   random-color
;;; Parameters:
;;;   (none)
;;; Purpose:
;;;   Selects and returns a random color.
;;; Produces:
;;;   color, a color.
;;; Postconditions:
;;;   It is difficult to predict color.
(define random-fgcolor
  (lambda ()
    (set-fgcolor (list (random 256) (random 256) (random 256)))))

Similarly, we can choose a random brush. The easiest way to choose a random brush is to select a random element of the brushes list.

;;; Procedure
;;;   random-brush
;;; Parameters:
;;;   (none)
;;; Purpose:
;;;   Select one of the brushes.
;;; Produces:
;;;   (nothing)
;;; Postconditions:
;;;   It is difficult to predict the brush.
(define random-brush
  (lambda ()
    (set-brush (list-ref (list-brushes) (random (length (list-brushes)))))))

However, that procedure can choose from perhaps too many brushes. We might create a similar procedure that selects from a particular list of brushes.

;;; Procedure:
;;;   randomly-select-brush
;;; Parameters:
;;;   brushes, a list of strings
;;; Purpose:
;;;   Select one of brushes.
;;; Produces:
;;;   (nothing)
;;; Preconditions:
;;;   All the strings in brushes name valid brushes.
;;; Postconditions:
;;;   The current brush is an element of brushes.
;;;   It is equally likely that each element of brushes is now the
;;;     active brush
(define randomly-select-brush
  (lambda (brushes)
    (set-brush (list-ref brushes (random (length brushes))))))

If we wanted to select one of the circle brushes, we might use

(randomly-select-brush (list "Circle (01)" "Circle (03)" "Circle (05)" "Circle (07)" "Circle (09)" "Circle (11)" "Circle (13)" "Circle (15)" "Circle (17)" "Circle (19)"))

In fact, we can rewrite random-brush using this procedure.

(define random-brush
  (lambda ()
    (randomly-select-brush (list-brushes))))

It is, of course, also possible that we'll want to randomly select from other lists (not just lists of brushes). For example, we might want randomly select a shade of brown by selecting an element of the list of blue.s Hence, we'll define a generalized random selection procedure.

;;; Procedure:
;;;   randomly-select
;;; Parameters:
;;;   values, a list
;;; Purpose:
;;;   Randomly select an element of values.
;;; Produces:
;;;   value, a value
;;; Preconditions:
;;;   values is nonempty.
;;; Postconditions:
;;;   value is an element of values.
;;;   value is equally likely to be any element of values.
(define randomly-select
  (lambda (values)
    (list-ref values (random (length values)))))

We can now select a random shade of blue with the following procedure.

;;; Procedure:
;;;   random-blue
;;; Parameters:
;;;   (none)
;;; Purpose:
;;;   Set the foreground color to an unpredictable shade of blue.
;;; Produces:
;;;   (nothing)
;;; Postconditions:
;;;   The foreground color is a shade of blue.
;;;   It is difficult to predict which shade of blue it is.
(define random-blue
  (let ((blues (list BLUE BLUE_VIOLET CADET_BLUE COBALT_BLUE 
                     CORN_FLOWER_BLUE DARK_SLATE_BLUE 
                     DEEP_MIDNIGHT_BLUE LIGHT_BLUE LIGHT_STEEL_BLUE
                     MEDIUM_BLUE MEDIUM_SLATE_BLUE MIDNIGHT_BLUE
                     NAVY_BLUE NEON_BLUE NEW_MIDNIGHT_BLUE OCEAN_BLUE
                     PALE_BLUE RICH_BLUE ROYAL_BLUE SKY_BLUE
                     SLATE_BLUE STEEL_BLUE)))
    (lambda ()
      (set-fgcolor (randomly-select blues)))))

We can also rewrite randomly-select-brush to use randomly-select. (The process of identifying common procedures and then rewriting code to use these common procedures is called refactoring and it's a good practice.)

(define randomly-select-brush
  (lambda (brushes)
    (set-brush (randomly-select brushes))))

Combining Procedures

Okay. Where are we? We have a way to randomly select colors and to randomly select brushes. Now we need ways to randomly draw things. For lines, circles, and rectangles, we can simply randomly select all of the parameters (perhaps within certain limits, such as the width and height of the image). For example, here is a procedure to draw a line between two randomly selected points.

;;; Procedure:
;;;   random-line
;;; Parameters:
;;;   image, an image
;;;   width, an integer
;;;   height, an integer
;;; Purpose:
;;;   Draw a random line in the image, assuming that its width
;;;   and height are as specified.
;;; Produces:
;;;   (nothing)
;;; Postconditions:
;;;   A new line has been added to image, using the current color
;;;   and brush.
(define random-line
  (lambda (image width height)
    (line image (random width) (random height)
                (random width) (random height))))

There are many interesting variants, such as ones that use a fixed starting point, a fixed line length, and so on and so forth.

Finally, we can write a procedure that puts it all together.

;;; Procedure:
;;;   splat
;;; Parameters:
;;;   image, an image
;;;   width, an integer
;;;   height, an integer
;;; Purpose:
;;;   Draw a line between random points, using a random color and
;;;   a random brush.
;;; Produces:
;;;   (nothing)
;;; Postconditions:
;;;   The foreground color may have changed.
;;;   The brush may have changed.
;;;   The image now contains another line.
(define splat
  (lambda (image width height)
    (set-fgcolor (random-color))
    (random-brush)
    (random-line image width height)))

 

History

 

Disclaimer: I usually create these pages on the fly, which means that I rarely proofread them and they may contain bad grammar and incorrect details. It also means that I tend to update them regularly (see the history for more details). Feel free to contact me with any suggestions for changes.

This document was generated by Siteweaver on Thu Sep 13 20:55:14 2007.
The source to the document was last modified on Mon Mar 5 12:40:22 2007.
This document may be found at http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2007S/Readings/randomized-drawing.html.

You may wish to validate this document's HTML ; Valid CSS! ; Creative Commons License

Samuel A. Rebelsky, rebelsky@grinnell.edu

Copyright © 2007 Samuel A. Rebelsky. This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.