CSC151.01 2009F Functional Problem Solving : Assignments

Assignment 7: String Art

Due: 10:00 a.m., Wednesday, 11 November 2009

Summary: In this assignment, you will experiment with drawings in which many straight lines are used to give the appearance of curved shapes. The technique for making this drawings is based on the idea of string art.

Purposes: To give you more experience with numeric recursion. To give you an opportunity to play with interesting images.

Expected Time: Two to three hours.

Collaboration: We encourage you to work in groups of size three. You may, however, work alone or work in a group of size two or size four. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.

Submitting: Email your answer to . The title of your email should have the form CSC151.01 2009F Assignment 7: String Art and should contain your answers to all parts of the assignment. Scheme code should be in the body of the message. Do not attach any images. We should be able to regenerate any images you create just from the instructions you submit.

Warning: So that this assignment is a learning experience for everyone, I may spend class time publicly critiquing your work.


Many of you may have played with string art when you were growing up. In this technique, colored string is wrapped around pegs or notches on a board to produce geometric or other figures that give the illusion of curves, even though the string is pulled in straight lines. Our goal here is to simulate this technique using Scheme procedures.

In string art, the endpoints of the individual lines form the edges of the figure. We will limit ourselves (at first) to drawing figures whose edges are horizontal and vertical lines, that is, rows and columns. We will allow the user to specify n, the number of lines that are drawn, and use numeric recursion to draw them. The user should also be able to specify the position and size of the figure; we do this with four parameters: edge-col and edge-row, along which the ends of the lines will fall, and the width and height of the figure.

Read the following procedure. What is the base case? What is the simplification step? How are the two endpoints of each line computed?

;;; Procedure:
;;;   image-string-art!
;;; Parameters:
;;;   image, an image
;;;   n, a positive integer
;;;   edge-col, an integer
;;;   edge-row, an integer
;;;   width, an integer
;;;   height, an integer
;;; Purpose:
;;;   Draw a "string art" figure. 
;;; Produces:
;;;   [Nothing.  Called for its side effects.]
;;; Preconditions:
;;;   [No additional.]
;;; Postconditions:
;;;   n lines have been drawn.
;;;   The lines have endpoints falling along
;;;     edge-col and edge-row.
;;;   The lines are evenly spaced.
;;;   The lines cross each other.
;;;   The figure is bounded by the rectangle
;;;     (edge-col, edge-row) 
;;;     (edge-col + width, edge-row + height)
(define image-string-art!
  (lambda (image n edge-col edge-row width height)
    (let ((col-spacing (/ width (- n 1)))
          (row-spacing (/ height (- n 1))))
      (let kernel ((i 0)
                   (col edge-col)
                   (row (+ edge-row height)))
        (when (< i n)
          ; The next two lines are for testing
          ; (print (list 'from (list edge-col row) 'to (list col edge-row)))
          ; (newline)
          (image-draw-line! image
                            edge-col row
                            col edge-row)
          ;(context-update-displays!) ; for debugging
          (kernel (+ i 1)
                  (+ col col-spacing)
                  (- row row-spacing)))))))

Now, let's try the procedure out.

> (define canvas (image-new 200 200))
> (image-show canvas)
> (context-set-fgcolor! "blue")
> (context-set-brush! "Circle (01)") 
> (image-string-art! canvas 20 0 0 200 200)
> (context-update-displays!)

We can also change where the lines are drawing.

> (define canvas (image-new 200 200))
> (image-show canvas)
> (context-set-fgcolor! "red")
> (context-set-brush! "Circle (03)")
> (image-string-art! canvas 10 200 200 -200 -200)

To help you understand how the procedure works, uncomment the lines marked with comments as “for debugging”. Then try the above example again. You should be able to see the lines being drawn one by one.

Now, let's think about how to vary the parameters to the image-string-art! procedure. For each of the following, first consider what you think will happen when we make the change and then check your answer experimentally. In each case, assume that the change is from the original call to image-string-art!. You will want to clear the image or change the foreground color after each experiment so that you can see what changed.

  • What will happen if we change the edge column to a number that is between 0 and the width?
  • What will happen if we change the width to 25 and the height to 200?
  • What will happen if we use different signs for width and height?
  • What will happen if we change n to 50? to 5?


Part One: Replicating Figures

Give a set of instructions for replicating each of the following figures, each of which is on a 200x200 image. (You should be able to make the figures with appropriate calls to image-string-art!.)

Note: You do not need to worry about the precise number of lines in each figure. The general shape (and color) should be the same, but with (very) roughly the same number of lines used.

Figure 1a.

Figure 1b.

Figure 1c.

Part Two: Varying the Primary Procedure

Write your own variant or variants of image-string-art! that provide some changes in the way the string art is made. While you need not include all of the following in each of your variants, you must demonstrate each technique at least once.

  • Vary the color of each line drawn based on the iteration (that is, the value of i).
  • Vary the brush used to draw the line, (e.g., cycling from smaller to larger to smaller to larger to smaller ...)
  • Vary the lengths of the lines.
  • Use a systematic, but not constant, spacing between endpoints.

We strongly recommend that you get some simple variations working before trying something more complicated. Think about how you can make (and test!) your changes in small steps.

Include the instructions for generating image(s) that demonstrate all the techniques above.

Part Three: Your Own String Art

Write instructions to generate three interesting 512x512 images. Each image should be created using multiple calls to one of your variants of image-string-art! or related procedures. You may even want to write your own procedure that uses numeric recursion to draw multiple copies of a figure that form a larger pattern.

For each image, write a short paragraph explaining the techniques you've used to construct the image.

Important Evaluation Criteria

In assessing part one of the assignment, we will primarily emphasize your success at meeting the form of the images.

In assessing part two of the assignment, we will emphasize not only your success at incorporating the required variations, but also the creativity of the modifications you made to the code. We will consider whether these modifications were interesting and subtle, or relatively straightforward.

In assessing part three of the assignment, we will consider the depth of thought demonstrated by the code used to create the images and the clarity of the paragraphs used to describe that code.

Extra credit opportunity

In our version of image-string-art!, the two edges of the string art figure are constrained to be a horizontal line (a row) and a vertical line (a column). For extra credit, write a more general version of the image-string-art! procedure for which the two edges are two arbitrary lines. Or, develop a string art procedure for another shape such as an ellipse or parabola. You will need to choose appropriate parameters for the procedure.

Creative Commons License

Samuel A. Rebelsky,

Copyright (c) 2007-9 Janet Davis, Matthew Kluber, Samuel A. Rebelsky, and Jerod Weinman. (Selected materials copyright by John David Stone and Henry Walker and used by permission.)

This material is based upon work partially supported by the National Science Foundation under Grant No. CCLI-0633090. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.

This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License. To view a copy of this license, visit or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.