Nested Squares NetLogo Model

Produced for the book series "Exercises for Artificial Intelligence";

Author: W. J. Teahan; Publisher: Ventus Publishing Aps, Denmark.

powered by NetLogo

view/download model file: Nested-Squares.nlogo

WHAT IS IT?

This model is provided as a solution for Exercise 3.6.8 for the Exercises for Artificial Intelligence book series.

The model draws nested squares. In one configuration, it will draw 6 nested squares using 6 different methods illustrating the versatility of NetLogo for drawing. In another configuration, it will draw the nested squares using the same method.

The six different methods for drawing the squares are as follows:

Type 1: Draws the square using a single turtle agent with the shape "square 2".
Type 2: Draws the square using a single turtle agent with the setxy command.
Type 3: Draws the square using a single turtle agent and the stamp command.
Type 4: Draws the square using multiple turtle agents.
Type 5: Draws the square using four turtle agents with link agents to draw the lines between them.
Type 6: Draws the square using patch agents.


WHAT IS ITS PURPOSE?

The purpose is to illustrate how versatile NetLogo is at drawing. A secondary purpose is to show how turtle, patch and link agents in NetLogo are programmed, and to illustrate the use of the turtle drawing commands. A tertiary purpose is to illustrate how patterns can emerge through the execution of relatively straightforward commands. (If further interested, the reader should research the topics of L-systems and fractals).


HOW IT WORKS

The model uses a single turtle agent for Types 1 to 3, and draws the squares by manipulating the shape and size of the turtle to animate the squares growing larger, or by moving the turtle around the outer edge of the squares using either the turtle's pen or by stamping successive locations.

The model uses multiple turtle agents for Type 4, and once drawn, these turtles remain in the same place. i.e. There are many little square turtles that are used to draw the outside of the larger squares, like square Lego bricks all placed alongside each other.

The model uses link agents between four hidden turtle agents at the four corners for Type 5.

The model uses patch agents for Type 6. Like for the Type 4 turtle agents, each patch agent is used to draw the outside of the larger squares, like square Lego bricks all placed alongside each other.


HOW TO USE IT

Press the setup button first. This will clear the environment. Then choose the type of drawing you want using the type-of-drawing chooser. If you wish to draw the nested squares using six different methods, then set this chooser to "Draw different squares" or "Types 1 to 6 repeated". Otherwise the squares will be drawn all the same using a single type as specified by the chooser.

If you wish the squares to be drawn from the inside out, then set the draw-inside-out? switch to On. The innermost-size slider value defines the size of the innermost square, and therefore the size of the hole at the centre. The number-of-squares slider value defines how many squares to draw when the type-of-drawing chooser is set to drawing the squares all the same (Types 1 to 6).

To draw the squares, press either the draw all squares once button, which will draw them once only, or if you wish them to be drawn continuously, then press the draw all squares forever button.


THE INTERFACE

The model's Interface buttons are defined as follows:

- setup: This will clear the environment.

- draw all squares once: This will draw all the nested squares once only.

- draw all squares forever: This will draw all the nested squares continuously.

- draw-innermost-square: This will draw the square in the centre, using the Type 1 method.

- draw-inner-square: This will draw the next square out from the centre, using the Type 2 method.

- draw-middle-inner-square: This will draw the next square out, using the Type 3 method.

- draw-middle-outer-square: This will draw the next square out, using the Type 4 method.

- draw-outer-square: This will draw the next square out, using the Type 5 method.

- draw-outermost-square: This will draw the outside square, using the Type 6 method.

The model's Interface sliders, chooser and switch are defined as follows:

- type-of-drawing: This defines the method used for drawing. The different types are defined as follows:
"Draw different squares": This will draw six different squares using different methods - defined as Type 1 to Type 6 (see above).
"Type 1 (draw the same squares)": This will draw the squares all the same using the Type 1 method.
"Type 2 (draw the same squares)": This will draw the squares all the same using the Type 2 method.
"Type 3 (draw the same squares)": This will draw the squares all the same using the Type 3 method.
"Type 4 (draw the same squares)": This will draw the squares all the same using the Type 4 method.
"Type 5 (draw the same squares)": This will draw the squares all the same using the Type 5 method.
"Type 6 (draw the same squares)": This will draw the squares all the same using the Type 6 method.
"Types 1 to 6 repeated": This will repeat drawing the nested squares, cycling through Types 1 to 6.

- draw-inside-out?: If this is set to On, the squares will be drawn from the inside out with the innermost square drawn first, otherwise they will be drawn from the outside in. (Try changing this as the squares are being drawn).

- innermost-size: This sets the size of the innermost square. As a consequence, it also defines the size of the inner hole.

- number-of-squares: This sets the number of squares to be drawn when the type-of-drawing is not set to "Draw different squares".


THINGS TO NOTICE

Notice how the inner square (Type 2) has rounded corners. This is because it is drawn using the turtle's pen.

Notice how the middle inner square has very faint lines where the turtle squares have not overlapped with each other. To get rid of this, change "set size 1" to "set size 1.1" in the code when the first turtle is created.

Notice what happens when the innermost-size slider value is set to a large number, or the number-of-squares-the-same slider is set to a large number when the type-of-drawing chooser is not set to "Draw different squares".

Notice which methods seem to take longer than the others at drawing the squares.

Notice that the Type 1 method (using a single turtle with shape "square 2") only allows one square to be visible at any one time. Why is this? What happens when you choose Type 1 and press the draw all squares forever button?

Notice that the Type 2 (using a single agent's pen) and Type 5 methods (using four hidden turtle agents plus link agents between them) draw some of the sides of the squares in the wrong direction when the size of the side gets long (towards the edge of the world rather than towards the other corners). Why is this?

Notice that for Type 6, if you slow down the Interface speed slider, it will show the individual patches being drawn at random locations around the edge of each square.


THINGS TO TRY

Try slowing down the speed using the Interface's speed slider. You will be able to see how the different squares are drawn.

Try running this model in 3D mode for the various configurations. What happens and why?


NETLOGO FEATURES

This demonstrates how to draw using three different types of agents - turtle agents, link agents and patch agents.


EXTENDING THE MODEL

Are there further ways for drawing the squares?


RELATED MODELS

See the Nested Triangles model.


CREDITS AND REFERENCES

To refer to this model in publications, please use:

Teahan, W. J. (2010). Nested Squares NetLogo model.
Exercises for Artificial Intelligence. Ventus Publishing Aps.

PROCEDURES

; Nested Triangles model.
;
;
; Copyright 2010 William John Teahan. All Rights Reserved.
;

to setup
  ca
end

to draw-all-squares
  ca

  ifelse (type-of-drawing = "Draw different squares")
    [ draw-all-squares-differently ]
    [ ifelse (type-of-drawing != "Types 1 to 6 repeated")      
      [ draw-all-squares-the-same-single-method ]
      [ draw-all-squares-the-same-all-methods ]
    ]
end

to draw-all-squares-differently
; Draws the six nested squares six different ways.

  ifelse (draw-inside-out?)
    [
      draw-square-type-1 lime    (innermost-size)
      draw-square-type-2 orange  (innermost-size + 1)
      draw-square-type-3 yellow  (innermost-size + 3)
      draw-square-type-4 magenta (innermost-size + 5)
      draw-square-type-5 violet  (innermost-size + 8)
      draw-square-type-6 blue    (innermost-size + 11)
    ]
    [
      draw-square-type-6 blue    (innermost-size + 11)
      draw-square-type-5 violet  (innermost-size + 8)
      draw-square-type-4 magenta (innermost-size + 5)
      draw-square-type-3 yellow  (innermost-size + 3)
      draw-square-type-2 orange  (innermost-size + 1)
      draw-square-type-1 lime    (innermost-size)
    ]
end

to draw-nested-squares-all-the-same-type [drawing-type]
; Draws the Draws the nested squares using the same method.

  let size-total 0
  let size-inc 2
  if (not draw-inside-out?)
    [ ; draw squares decreasing in size
      set size-total (number-of-squares-the-same * size-inc)
      set size-inc -2
    ]

  let colour 15
  
  repeat number-of-squares-the-same
  [
    if (drawing-type = "Type 1 (draw the same squares)")
      [ draw-square-type-1 colour (innermost-size + size-total) ]
    if (drawing-type = "Type 2 (draw the same squares)")
      [ draw-square-type-2 colour (innermost-size + size-total) ]
    if (drawing-type = "Type 3 (draw the same squares)")
      [ draw-square-type-3 colour (innermost-size + size-total) ]
    if (drawing-type = "Type 4 (draw the same squares)")
      [ draw-square-type-4 colour (innermost-size + size-total) ]
    if (drawing-type = "Type 5 (draw the same squares)")
      [ draw-square-type-5 colour (innermost-size + size-total) ]
    if (drawing-type = "Type 6 (draw the same squares)")
      [ draw-square-type-6 colour (innermost-size + size-total) ]
    set colour colour + 10
    set size-total size-total + size-inc
  ]    
end

to draw-all-squares-the-same-single-method
; Draws the nested squares using the same method.

  let size-inc 0
  let colour 15
  
  draw-nested-squares-all-the-same-type type-of-drawing 
end

to draw-all-squares-the-same-all-methods
; Draws the six nested squares using same type and repeated for all six methods.

  draw-nested-squares-all-the-same-type "Type 1 (draw the same squares)"
  draw-nested-squares-all-the-same-type "Type 2 (draw the same squares)"
  draw-nested-squares-all-the-same-type "Type 3 (draw the same squares)"
  draw-nested-squares-all-the-same-type "Type 4 (draw the same squares)"
  draw-nested-squares-all-the-same-type "Type 5 (draw the same squares)"
  draw-nested-squares-all-the-same-type "Type 6 (draw the same squares)"
end

to draw-square-type-1 [colour this-size]
;; Draws the square using a single turtle agent with the shape "square 2".

  create-turtles 1
  [
    set shape "square 2"
    set size this-size
    set color colour
  ]
end

to draw-square-type-2 [colour this-size]
;; Draws the square using a single turtle agent with the setxy command.

  create-turtles 1
  [
    hide-turtle ; we do not need to see the turtle
    set color colour
    
    let halfedge int (this-size / 2)

    setxy (- halfedge) (halfedge)   ; upper left corner
    
    pen-down ; use the turtle's drawing pen to draw the square
    set pen-size 12

    setxy (halfedge) (halfedge)     ; upper right corner
    setxy (halfedge) (- halfedge)   ; lower right corner
    setxy (- halfedge) (- halfedge) ; lower left corner
    setxy (- halfedge) (halfedge)   ; upper left corner
  ]
end

to draw-line-of-turtles [colour this-turtle number x-inc y-inc stamped?]
;; Draws a line of turtles. The variable number is the number of turtles to draw.
;; The variables x-inc, and y-inc, specify whether to draw the line horizontally
;; or vertically (they control how much the x and y co-ordinates are incremented each
;; iteration). If stamped? is true, it will use a single turtle and stamp it as it is
;; drawn successively. Otherwise it will hatch multiple turtles as it goes across.

  repeat number
  [
    ask this-turtle
    [
      ifelse stamped?
      [
        stamp
        setxy (xcor + x-inc) (ycor + y-inc) ; move to next position
      ]
      [ hatch 1
        [
          set this-turtle self
          setxy (xcor + x-inc) (ycor + y-inc) ; change position for new turtle
        ]
      ]
    ]
  ]
end

to draw-square-type-3 [colour this-size]
;; Draws the square using a single turtle agent and the stamp command.

  let this-turtle nobody

  create-turtles 1
  [
    set shape "square 3"
    ; If you use the shape "square" here, then there will be gaps between each turtle's shape.
    ; The "square 3" shape is the "square" shape but edited using the Turtle Shapes Editor (in
    ; the Tools menu) so that the square fits the entire space. This will still leave faint
    ; gaps between adjacent turtles, however (which can be changed by changing the turtle's size).

    let halfedge (this-size / 2)
    setxy (- halfedge) (halfedge) ; start off at top left corner of the square 
    set this-turtle self
    set size 1 ; this results in the turtle squares not overlapping
               ; change this to 1.1 to get rid of them
    set color colour
  ]

  ; Draw the horizontal line of turtles across the top.
  draw-line-of-turtles colour this-turtle this-size  1  0 true
  ; Draw the vertical line of turtles down to the bottom right.
  draw-line-of-turtles colour this-turtle this-size  0 -1 true
  ; Draw the horizontal line of turtles across to the bottom left.
  draw-line-of-turtles colour this-turtle this-size -1  0 true
  ; Draw the vertical line of turtles back up to the top left.
  draw-line-of-turtles colour this-turtle this-size  0  1 true
end

to draw-square-type-4 [colour this-size]
;; Draws the square using multiple turtle agents.

  let this-turtle nobody
  let halfedge 0

  create-turtles 1
  [
    set this-turtle self
    set size 1 ; this results in the turtle squares not overlapping
               ; change this to 1.1 to get rid of them
    set color colour
    set shape "square 3"
    ; If you use the shape "square" here, then there will be gaps between each turtle's shape.
    ; The "square 3" shape is the "square" shape but edited using the Turtle Shapes Editor (in
    ; the Tools menu) so that the square fits the entire space.

    set halfedge (this-size / 2)
    setxy (- halfedge) (halfedge) ; start off at top left corner of the square 
  ]

  ; Draw the horizontal line of turtles across the top.
  ask this-turtle [ setxy (- halfedge) (halfedge) ]  ; start off line at top left corner of the square 
  draw-line-of-turtles colour this-turtle this-size  1  0 false
  ; Draw the vertical line of turtles down to the bottom right.
  ask this-turtle [ setxy (halfedge) (halfedge) ]    ; start off line at top right corner of the square 
  draw-line-of-turtles colour this-turtle this-size  0 -1 false
  ; Draw the horizontal line of turtles across to the bottom left.
  ask this-turtle [ setxy (halfedge) (- halfedge) ]  ; start off line at bottom right corner of the square 
  draw-line-of-turtles colour this-turtle this-size -1  0 false
  ; Draw the vertical line of turtles back up to the top left.
  ask this-turtle [ setxy (- halfedge) (- halfedge) ]; start off line at bottom left corner of the square 
  draw-line-of-turtles colour this-turtle this-size  0  1 false
end

to draw-square-type-5 [colour this-size]
;; Draws the square using four turtle agents with link agents to draw the lines between them.

  let halfedge int (this-size / 2)
  let t1 nobody
  let t2 nobody
  let t3 nobody
  let t4 nobody
  
  create-turtles 1
  [
    hide-turtle ; we do not need to see the turtle
    setxy (- halfedge) (halfedge)   ; upper left corner
    set t1 self
  ]

  create-turtles 1
  [
    hide-turtle ; we do not need to see the turtle
    setxy (halfedge) (halfedge)     ; upper right corner
    set t2 self
  ]

  create-turtles 1
  [
    hide-turtle ; we do not need to see the turtle
    setxy (halfedge) (- halfedge)   ; lower right corner
    set t3 self
  ]

  create-turtles 1
  [
    hide-turtle ; we do not need to see the turtle
    setxy (- halfedge) (- halfedge) ; lower left corner
    set t4 self
  ]

  ask t1
  [ create-link-with t2 [ set thickness 1 set color colour ]]
  ask t2
  [ create-link-with t3 [ set thickness 1 set color colour ]]
  ask t3
  [ create-link-with t4 [ set thickness 1 set color colour ]]
  ask t4
  [ create-link-with t1 [ set thickness 1 set color colour ]]
   
end

to draw-square-type-6 [colour this-size]
;; Draws the square using patch agents.
;; This procedure is based on Uri Wilensky's code provided by the Box Drawing Example in NetLogo
;; Models Library.

  let halfedge int (this-size / 2)
  ask patches
  [
    if (pxcor = (- halfedge) and pycor >= (- halfedge) and pycor <= (0 + halfedge) )
      [set pcolor colour] ;; ... draws left edge
    if ( pxcor = (0 + halfedge) and pycor >= (- halfedge) and pycor <= (0 + halfedge) )
      [set pcolor colour] ;; ... draws right edge
    if ( pycor = (- halfedge) and pxcor >= (- halfedge) and pxcor <= (0 + halfedge) )
      [set pcolor colour] ;; ... draws bottom edge
    if ( pycor = (0 + halfedge) and pxcor >= (- halfedge) and pxcor <= (0 + halfedge) )
      [set pcolor colour] ;; ... draws upper edge
    ]
end

;
; Copyright 2010 by William John Teahan.  All rights reserved.
;
; Permission to use, modify or redistribute this model is hereby granted,
; provided that both of the following requirements are followed:
; a) this copyright notice is included.
; b) this model will not be redistributed for profit without permission
;    from William John Teahan.
; Contact William John Teahan for appropriate licenses for redistribution for
; profit.
;
; To refer to this model in publications, please use:
;
; Teahan, W. J. (2010).  Nested Squares NetLogo model.
;   Artificial Intelligence. Ventus Publishing Aps
;