Sierpinski Triangle
WHAT IS IT?
This model uses a very simple iterative approach to drawing a Sierpinski Gasket, using either a triangle or a trapezoid as the base shape.
Initially, all turtles are located on one of the vertices of the triangle or trapezoid. At each step, each turtle simply selects one of the vertices as its target point, then moves halfway to that target point and stops, stamping the patch on which it lands with the color white. This is repeated as many times as desired. Though this is not the best-known method for doing so, this very simple behavior produces the Sierpinski Gasket with the same fractal complexity (subject to limitations of screen resolution) as other methods.
HOW TO USE IT
the "Turtles per Vertex" slide is used to specify the number of turtles that will be created on each vertex of the base shape.
Use one of the first three setup buttons - "Setup Equilateral", "Setup Right", "Setup Random" - to clear the screen and create the specified number of turtles at each of the three vertices of the resulting triangle. (Because the patch size is 1 pixel X 1 pixel, and each turtle is the size of a single patch, it may be very difficult to see the three vertices.)
To start with a trapezoid, first use the "Trapezoid Top Width %" slider to control the length of the top of the trapezoid, relative to the length of the base. Then click the "Setup Trapezoid" button to clear the screen and create the turtles on the four vertices of the trapezoid.
The "Draw" button sets the turtles in motion, with each following the rules described above. The "forward" command is used for turtle motion, so the paths of the turtles can be seen on the screen. (To see them more clearly, it might be useful to decrease the value of the "Speed" slider at the top of the screen.)
The "Draw Fast" button differs from "Draw" in that the "jump" command is used for turtle motion. This results in a dramatic reduction in the time required for the Sierpinski Gasket to emerge.
THINGS TO NOTICE
When the base shape is a triangle, the dark regions that cut the white triangles into smaller and smaller triangles will be similar to the base triangle: although smaller and upside-down, the angles will be the same as those of the original, and the sides will be in the same proportions as the sides of the original triangle. This is true no matter what sort of triangle we start with.
When the base shape is a trapezoid, the dark regions are triangles which are similar to the triangle that would result if the right and left sides of the trapezoid were extended upwards to form a triangle.
When the "Draw" button is used, and the speed is decreased, the motion of the turtles as the process begins appears very uniform, very much according to a pattern. Very soon, however, the motion of each turtle appears to be entirely independent of the rest. In fact, this latter appearance is the reality from the very start: it is only because the turtles all start from three or four points, that their behavior appears synchronized at first. As the effect of choosing one vertex at random is compounded by repetition, each turtle soon follows its own distinct trajectory in the process.
There is no direct or indirect interaction between turtles in this process; thus, the complexity is not the result of a large number of turtles, but rather a large number of repetitions of the basic rules - whether that repetition is by one turtle per vertex, or by 100 turtles per vertex.
EXPLORATIONS
The "Setup Random" button works by selecting three points at random along the perimeter of a circle, and forming a triangle from those points. Thus, the resulting triangle could have almost any proportions possible in a triangle. Experiment with the "Setup Random" button, to see the results when many different triangles are used. Observe how the smaller triangles that appear have the same proportions as the original, no matter the size. (Obviously, there is a practical limit: when triangles are only one or two pixels on each side, the accuracy of representation on the screen is lost.)
Experiment with different values for the "Trapezoid Top Width %" slider, to see the different results. At what value does the Sierpinski Gasket disappear?
Try starting with different numbers of turtles per vertex. Are the results the same? Is there some magic number which seems to produce a recognizable Sierpinski Gasket in the shortest time? Is the answer the same when the "Draw Fast" button is used?
For intermediate StarLogo programmers: The current model uses the expression "0.5 * (distance-nowrap :x :y)" to control how far the turtle moves in each step. What do you think would happen if the "0.5" value were changed slightly, higher or lower? Experiment with this value (possibly by adding a new slider). Within what limits is some form or variation of the Sierpinski Gasket still visible?
For intermediate and advanced StarLogo programmers: How could the model be modified, to allow the user to click on the canvas to set the vertices of a triangle?
STARLOGO FEATURES
Rather than depending on a predetermined canvas size, the model uses "screen-width", "screen-height", "screen-half-width", and "screen-half-height" to determine the largest possible equilateral triangle, right triangle, circle (for the random triangle), and trapezoid which can fit on the canvas, with a margin of 2.5% left open around the edges.
Turtles are used to setup each vertex: stamping the patch white, placing the xcor and ycor of the vertex in a list, and hatching additional turtles (as necessary) on the vertex.
When all the vertices are in a list, the "pick" command is used to select one item from the list at random.
"towards-nowrap" and "distance-nowrap" are used to control turtle motion. Using the "-nowrap" versions of these command ensures that turtles don't wrap around the edges of the canvas, in moving towards the selected target vertex.
Turtle procedures
;; Procedure: initialize-basic
;; Called by: setup-equilateral, setup-right, setup-random, setup-trapezoid
;; procedures (observer)
;;
;; Stamps the patch white and adds the turtles coordinates to the vertices list.
;;
to initialize
setcolor blue
stamp white
setitem (who + 1) vertices (list xcor ycor)
dotimes [:ignore (turtles-per-vertex - 1)] [
hatch []
]
end
;; Procedure: draw
;; Called by: Draw button
;;
;; Select one of the vertices at random, and move halfway to that point.
;;
to draw
let [:point pick vertices]
let [:x (item 1 :point)]
let [:y (item 2 :point)]
setheading (towards-nowrap :x :y)
forward 0.5 * (distance-nowrap :x :y)
stamp white
end
;; Procedure: draw-fast
;; Called by: Fast Draw button
;;
;; Select one of the vertices at random, and move halfway to that point, using
;; the jump command.
;;
to draw-fast
let [:point pick vertices]
let [:x (item 1 :point)]
let [:y (item 2 :point)]
setheading (towards-nowrap :x :y)
jump 0.5 * (distance-nowrap :x :y)
stamp white
end
Observer procedures
globals [
vertices ; List of vertices; each element is a list of X and Y coordinates.
]
;; Procedure: setup-basic
;; Called by: setup-equilateral, setup-right, setup-random, setup-trapezoid
;; procedures (observer)
;;
;; Clear turtles and the canvas. Initialize vertices list at desired size.
;;
to setup-basic :number-vertices
clear-all
set vertices (make-list :number-vertices [])
end
;; Procedure: setup-equilateral
;; Called by: Setup Equilateral button
;;
;; Call basic-setup. Find the largest possible equilateral triangle that will
;; fit on the canvas (with 5% slack). Create and initialize three turtles on the
;; vertices of the triangle.
;;
to setup-equilateral
setup-basic 3
let [:radius
(min (1.9 * screen-half-width / (sqrt 3)) (screen-height * 19 / 30))]
create-turtles-and-do 3 [
setxy 0 (0 - :radius / 4)
forward :radius
initialize
]
end
;; Procedure: setup-right
;; Called by: Setup Right button
;;
;; Call basic-setup. Find the largest possible right triangle that will fit on
;; the canvas (with 5% slack). Create and initialize three turtles on the
;; vertices of the triangle.
;;
to setup-right
setup-basic 3
create-turtles-and-do 3 [
case who [
0 [
setxy (0.95 * screen-half-width)
(0.95 * screen-half-height)
]
1 [
setxy (0.95 * screen-half-width)
(0 - 0.95 * screen-half-height)
]
2 [
setxy (0 - 0.95 * screen-half-width)
(0 - 0.95 * screen-half-height)
]
]
initialize
]
end
;; Procedure: setup-random
;; Called by: Setup Random button
;;
;; Call basic-setup. Find the largest possible inscribed circle that will fit
;; on the canvas (with 5% slack). Create and initialize three turtles,
;; giving them a random heading and sending them to the perimeter of the circle.
;;
to setup-random
setup-basic 3
let [:radius (0.95 * min screen-half-width screen-half-height)]
create-turtles-and-do 3 [
setheading (random 360)
forward :radius
initialize
]
end
;; Procedure: setup-trapezoid
;; Called by: Setup Trapezoid button
;;
;; Call basic-setup. Create four turtles and place them on the vertices of a
;; trapezoid with a base that is the width of the canvas (with 5% slack), and
;; a top with a length which is a specified percentage of the base length.
;;
to setup-trapezoid
setup-basic 4
create-turtles-and-do 4 [
case who [
0 [
setxy (0 - 0.95 * trapezoid-top * screen-half-width / 100)
(0.95 * screen-half-height)
]
1 [
setxy (0.95 * trapezoid-top * screen-half-width / 100)
(0.95 * screen-half-height)
]
2 [
setxy (0.95 * screen-half-width)
(0 - 0.95 * screen-half-height)
]
3 [
setxy (0 - 0.95 * screen-half-width)
(0 - 0.95 * screen-half-height)
]
]
initialize
]
end
