Map Drawing NetLogo Model

Produced for the book series "Artificial Intelligence";

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

powered by NetLogo

view/download model file: Map-Drawing.nlogo

WHAT IS IT?

This model allows the user to draw a map. e.g. A map of Central Park in New York.

If you would like to load the Central Park Map shown in Chapter 9 of the Artificial Intelligence Book, first ensure you are running the model in version 4.0.4, then select the Import option from the File tab, select the Import World option, then import the Map Drawing Central Park World file: Map-Drawing-Central-Park-World.csv.

This model was created using NetLogo version 4.1. Although it works perfectly fine for creating new maps, the program hangs when you try to import the Map Drawing Central Park World using the CSV file that was exported using an earlier version of the model created using NetLogo version 4.0.4. A simple work-around to this problem is to run the model using version 4.0.4 rather than 4.1 when you want to import this map.


WHAT IS ITS PURPOSE?

The purpose of this model is to provide a facility that allows users to draw their own maps, thereby allowing them to represent knowledge about a real environment in the virtual 2D NetLogo environment. Maps can be considered a form of knowledge representation which provides a different approach with different capabilities for reasoning in comparison to the more traditional forms of knowledge representation such as first order logic and decision trees usually described in AI textbooks.

A secondary purpose is to show the different ways that objects and paths can be drawn and edited using NetLogo's features.


HOW IT WORKS

The model allows the user to place various objects such as circles, squares, triangles, trees, and persons in the environment. These objects are represented by different breeds of turtle agents.

The paths a user can draw on the map have different types. The draw-path command draws a path using the turtle draw commands (i.e. using the drawing turtle's pen via the pen-down command). As a consequence, this type of path cannot be "seen" by other agents in the environment, so the select-region command does not work on this type of path, and it cannot be erased using the erase-path if the path has been ended (for example, by the end-path command). In this case if you do not wish to erase everything by pressing the setup command, then the best strategy is to draw over the top of the path with another path of a different colour to the desired background colour.

There are two other types of paths - these are paths drawn using patch agents (using the draw-patches-path command) and using turtle agents (using the draw-turtles-path command). Unfortunately, the quality of these types of paths can be very patchy (excusing the pun). Only the turtle agents type of path can be selected, then moved or erased. The patch type of path cannot be selected unlike the path drawn using the turtle's pen described above.

The model uses drawer turtle agents for drawing the paths, tracer turtle agents for tracing them, text turtle agents for drawing the text and square-drawers for drawing a path using square turtles.


HOW TO USE IT

Press the setup button first. To place an object in the map, first select the desired object-type and object-colour, press the draw-object button, then place the object at the desired location by moving the mouse and then clicking. You can erase the object by pressing the erase-object button then clicking on it with the mouse. To move it, press the select-object button, then when it is highlighted using a halo, the object can be moved around using the mouse. The select-region button allows the user to select a region of objects to be moved around using the mouse or erased using the erase-region button.

If you wish to draw a path, there are three options: paths drawn using a turtle agent's pen, paths drawn using patch agents and paths drawn using turtle agents. The first option comes out looking smoother; the other two options can end up being patchier. When drawing the path, move the mouse to the desired location and then click and drag to draw the path.

To draw a path using a turtle agent's pen, first choose the desired path-colour and path-size, then press the draw-path button. The path cannot be erased once it has been ended either when end-path has been pressed or another object or path has been drawn elsewhere. If this is not the case, then erase-path will work by erasing each point in the path one by one. If erase-path is not successful at deleting the just-drawn path, then the only way to "remove" it is to draw over the top of it.

To draw a path using patch agents, select the desired patches-path-size, then press the draw-patches-path button.

To draw a path using turtle agents, select the desired turtles-path-size, then press the draw-turtles-path button.

Text can be added by the draw-text button. Before doing so, make sure that you type in the text you want to draw into the text input box first, then select the desired text-colour. The font size for all text is specified globally using the Settings button in the Interface.

The colour of the background for the map is specified using the background-colour chooser. The background is changed/cleared using the clear-background button. An image can be used for the background instead of a single colour by pressing the import-background button.

To save the entire map and all the settings to disk, select the File menu from the NetLogo menubar, then select Export World option. To load it back in again at a latter date, use Import World instead.


THE INTERFACE

The model's Interface buttons are defined as follows:

- setup: This clears the map and resets the background.

- draw-path: This draws a path by having a turtle agent draw with the pen down between successive points as the mouse is dragged around. The path colour is specified by the path-colour chooser, and the path size is specified using the path-size slider.

- end-path: This designates that the path is ended. A subsequent press of the erase-path button will not be successful in deleting previously drawn paths. The only way to get rid of them is to draw over the top of them with another colour.

- erase-path: This will erase the points one by one in a path that has just been drawn using the draw-path button, unless that path has been designated as complete using the end-path button, or an intervening object has been drawn (which ends the path by default).

- draw-object: This will draw an object at the location specified by the next mouse click. The object type and colour is specified by the object-type and object-colour choosers, and its size by the object-size slider.

- erase-object: This will erase the nearest object if there is one. Make sure to click on the centre of the object, otherwise it will not be erased.

- select-object: This will allow the user to drag a selected object using the mouse in order to change its position. The selected object is shown with a halo. Make sure to click on the centre of the object, otherwise a halo showing it has been selected will not appear.

- select-region: This allows the user to select a rectangular region of objects for moving around. The user clicks and drags the mouse to define the region being selected (this is shown with a red box dynamically as the mouse is dragged; all objects that can be moved in the region are also highlighted). To move the selected objects around, lift the mouse momentarily when the rectangular region is as you want it, click back inside the red rectangle then drag it to the desired location.

- erase-region: This will erase all the objects that have been selected using the select-region button.

- clear-background: This clears the existing background, and redraws it using the colour specified by the background-colour chooser.

- import-background: This allows the user to use an image file as the background.

- draw-patches-path: This draws a path using patch agents. The size of the patches is specified by the patches-path-size slider.

- draw-turtles-path: This will draw a path using turtle agents. The size of the turtles is specified by the turtles-path-size slider.

- draw-text: This draws the text specified in the text Input box on the map. The right side of the text ends up at the point the mouse is clicked. The colour of the text is specified by the text-colour chooser. The font size for all text can be changed globally by pressing the Settings button in the Interface.

The model's Interface choosers, sliders and Input box are defined as follows:

- path-colour: This sets the colour that is used to draw the path when the draw-path button is pressed.

- path-size: This sets the pen size that is used to draw the path when the draw-path button is pressed.

- object-type: This sets the type of object that is drawn when the draw-object button is pressed.

- object-colour: This sets the colour of the object that is drawn when the draw-object button is pressed.

- object-size: This sets the size of the object that is drawn when the draw-object button is pressed.

- background-colour: This sets the colour of the background that is drawn when the clear-background button is pressed.

- patches-path-size: This sets the size of the path that is drawn when the draw-patches-path button is pressed.

- turtles-path-size: This sets the size of the path that is drawn when the draw-turtles-path button is pressed.

- text: This sets the text that is drawn when the draw-text button is pressed.

- text-colour: This sets the colour of the text that is drawn when the draw-text button is pressed.


THINGS TO TRY

Try drawing your own map - perhaps of your house, apartment or flat, or of the local school. Note while you are making the map the problems that arise with representing the real world. Once finished, check how many errors there are, and how much detail has been missed off the map. A month or so latter, check again, and see how much has changed.

Try loading the Central Park map. This is done by using the NetLogo menu option for importing a world. Select the File menu from the NetLogo menubar, then select Import World option.


EXTENDING THE MODEL

This model has a long way to go before it could be used to draw more high quality maps, such as that used for orienteering. One of the main drawbacks is the poor quality of the path drawing. Can this be improved in some manner?


NETLOGO FEATURES

The Import World and Export World menu options are used to save the map to disk and re-load it.


CREDITS AND REFERENCES

This model was created by William John Teahan.

To refer to this model in publications, please use:
Map Drawing NetLogo model.
Teahan, W. J. (2010). Artificial Intelligence. Ventus Publishing Aps.


PROCEDURES

; Map Drawing model.
;
; Copyright 2010 William John Teahan. All Rights Reserved.
;
; Allows you to draw a map.
;
; Part of the code is based on the Code Examples > Mouse ... models
; provided in the NetLogo Models Library.
;
breed [drawers drawer]           ;; for drawing paths
breed [tracers tracer]           ;; for tracing the drawn paths
breed [text-drawers text-drawer] ;; for drawing text
breed [square-drawers square-drawer] ;; for drawing a path using square turtles

;; point objects follow
breed [circles circle]         ;; a circle object
breed [circle2s circle2]       ;; an empty circle object
breed [squares square]         ;; a square object
breed [square2s square2]       ;; an empty square object
breed [triangles triangle]     ;; a triangle object
breed [triangle2s triangle2]   ;; an empty triangle object
breed [trees tree]             ;; a tree object
breed [plants plant]           ;; a plant object
breed [persons person]         ;; a person object
breed [cows cow]               ;; a cow object
breed [cars car]               ;; a car object
breed [exes ex]                ;; the letter x object
breed [tanks tank]             ;; the tank object

drawers-own [path]
tracers-own [path]

breed [sides side]       ;; the four sides of the selection square

globals
[selected                ;; agentset of currently selected circles
 current-drawer]         ;; drawer used for drawing current path
   
to setup
  clear-all
  set-default-shape circles "circle"
  set-default-shape circle2s "circle 2"
  set-default-shape squares "square"
  set-default-shape square2s "square 2"
  set-default-shape triangles "triangle"
  set-default-shape triangle2s "triangle 2"
  set-default-shape trees "tree"
  set-default-shape plants "plant"
  set-default-shape persons "person"
  set-default-shape cows "cow"
  set-default-shape cars "car"
  set-default-shape exes "x"
  set-default-shape tanks "bulldozer top"
    
  set-default-shape square-drawers "square"

  set-default-shape sides "line"

  ask patches [set pcolor string-to-colour background-colour] ;; make background required colour
  
  ;; initially, no turtles are selected
  set selected no-turtles

  create-drawers 1 [ initialize-drawer ]
end

to clear-background
;; clears the background to white
  ask patches [ set pcolor string-to-colour background-colour ]
end

to import-background
;; import a background image to trace the map over
  import-pcolors-rgb user-file
end

to-report string-to-colour [colour]
  if colour = "black"   [report black]
  if colour = "white"   [report white]
  if colour = "red"     [report red]
  if colour = "blue"    [report blue]
  if colour = "sky"     [report sky]
  if colour = "brown"   [report brown]
  if colour = "green"   [report green]
  if colour = "yellow"  [report yellow]
  if colour = "gray"    [report gray]
  if colour = "magenta" [report magenta]
  report black
end

to-report new-point [x y]
;; Returns if the point (x,y) is not at the head of the path.
  if empty? path [report true]
  ;let point first path
  ;let px first point
  ;let py last point
  ;report (x != px) or (y != py)
  report (x != first first path) or (y != last first path)
end

to draw-path
;; draws a path
  if mouse-down?
  [
    if current-drawer = nobody
      [ create-drawers 1 [ initialize-drawer ]]
    show current-drawer
    ask drawer current-drawer
    [ set pen-size path-size
      set color string-to-colour path-colour
      let x mouse-xcor
      let y mouse-ycor
      setxy x y ;; go to the current mouse coordinates
      if new-point x y
        [set path fput (list x y) path] ;; adds the coordinate pair (x,y) to the front of the path
      pen-down
      display
    ]
  ]
end

to end-path
;; puts pen up to end a path
  ask drawer current-drawer [ pen-up ]
  ;; create a new drawer for next path so that we only erase back to beginning of path
  create-drawers 1 [ initialize-drawer ]
end

to draw-patches-path
;; draws a path using patches (so it can be detected by turtles)
  if mouse-down?
  [
    let x mouse-xcor
    let y mouse-ycor
    let xi (- patches-path-size)
    let yi 0
    while [xi <= patches-path-size]
      [
        set yi (- patches-path-size)
        while [yi <= patches-path-size]
          [
            if (x + xi >= min-pxcor and x + xi <= max-pxcor) and
               (y + yi >= min-pycor and y + yi <= max-pycor)
              [ ask patch (x + xi) (y + yi)
                    [ set pcolor string-to-colour path-colour ]]
            set yi yi + 1
          ]
        set xi xi + 1
      ]
    display
  ]
end

to draw-turtles-path
;; draws a path using turtles that are square (so it can be detected by turtles)
  if mouse-down?
  [
    create-square-drawers 1
      [ set size turtles-path-size
        set color string-to-colour path-colour
        set xcor mouse-xcor
        set ycor mouse-ycor ]
    display
  ]
end

to erase-path
;; draws a path
  ask drawer current-drawer
  [
    if not empty? path
    [
      set path but-first path ;; get rid of head of the path list
      if not empty? path
      [
        let point first path ; set first point from new head of the path list
        pen-erase
        setxy (first point) (last point)
        pen-down
      ]
    ]
    display
  ]
end

to initialize-drawer
  set current-drawer who
  set size 0
  hide-turtle
  set pen-size path-size
  set color string-to-colour path-colour
  set xcor mouse-xcor
  set ycor mouse-ycor
  set path []
  pen-up
end

to erase-object
  if mouse-down? [
    let candidate min-one-of turtles [distancexy mouse-xcor mouse-ycor]
    if [distancexy mouse-xcor mouse-ycor] of candidate < 3
      [ ask candidate [ die ]]
    display
  ]
end

to select-object
;; selects an object on the map and "watches" it
  if mouse-down? [
    let candidate min-one-of turtles [distancexy mouse-xcor mouse-ycor]
    if [distancexy mouse-xcor mouse-ycor] of candidate < 3 [
      ;; The WATCH primitive puts a "halo" around the watched turtle.
      watch candidate
      while [mouse-down?] [
        ;; If we don't force the display to update, the user won't
        ;; be able to see the turtle moving around.
        display
        ;; The SUBJECT primitive reports the turtle being watched.
        ask subject [ setxy mouse-xcor mouse-ycor ]
      ]
      ;; Undoes the effects of WATCH.  Can be abbreviated RP.
      reset-perspective
    ]
  ]
end

to erase-region
;; erases the selected region
  ask selected [ print who die ]
  ask sides [ die ]
  display
  set selected no-turtles
  ;;handle-select
end

to select-region
  if mouse-down? [
    ifelse selected? mouse-xcor mouse-ycor
      [ handle-drag
        deselect ]
      [ handle-select ]
  ]
end

to create-object
  set color string-to-colour object-colour
  set size object-size
  setxy mouse-xcor mouse-ycor
  while [mouse-down?] [
    ;; If we don't force the display to update, the user won't
    ;; be able to see the turtle moving around.
    display
    ;; The SUBJECT primitive reports the turtle being watched.
    setxy mouse-xcor mouse-ycor
  ]
end

to draw-object
  if mouse-down? [
    show object-type
    if object-type = "circle"     [create-circles    1 [create-object]]
    if object-type = "circle 2"   [create-circle2s   1 [create-object]]
    if object-type = "square"     [create-squares    1 [create-object]]
    if object-type = "square 2"   [create-square2s   1 [create-object]]
    if object-type = "triangle"   [create-triangles  1 [create-object]]
    if object-type = "triangle 2" [create-triangle2s 1 [create-object]]
    if object-type = "tree"       [create-trees      1 [create-object]]
    if object-type = "plant"      [create-plants     1 [create-object]]
    if object-type = "person"     [create-persons    1 [create-object]]
    if object-type = "cow"        [create-cows       1 [create-object]]
    if object-type = "car"        [create-cars       1 [create-object]]
    if object-type = "x"          [create-exes       1 [create-object]]
    if object-type = "tank"       [create-tanks      1 [create-object]]
  ]
end

to create-text
  set label-color string-to-colour text-colour
  set size 0
  set label text
  setxy mouse-xcor mouse-ycor
  while [mouse-down?] [
    display
    setxy mouse-xcor mouse-ycor
  ]
end

to draw-text
  if mouse-down? [
      create-text-drawers 1 [create-text]
  ]
end

to handle-select
  ;; remember where the mouse pointer was located when
  ;; the user pressed the mouse button
  let old-x mouse-xcor
  let old-y mouse-ycor
  while [mouse-down?] [
    select old-x old-y mouse-xcor mouse-ycor
    ;; update the view, otherwise the user can't see
    ;; what's going on
    display
  ]
  ;; if no turtles are selected, kill off
  ;; the selection square and start over
  if not any? selected [ deselect ]
end

to handle-drag
  ;; remember where the mouse pointer was located when
  ;; the user pressed the mouse button
  let old-x mouse-xcor
  let old-y mouse-ycor
  if selected? old-x old-y [
    while [mouse-down?] [
      let new-x mouse-xcor
      let new-y mouse-ycor
      ;; we need to move both the selected turtles and the sides
      ;; of the selection square by the same amount that the
      ;; mouse has moved.  we do this by subtracting the current
      ;; mouse coordinates from the previous mouse coordinates
      ;; and adding the results to the coordinates of the turtles
      ;; and sides.
      ask selected
        [ setxy xcor + new-x - old-x
                ycor + new-y - old-y ]
      ask sides
        [ setxy xcor + new-x - old-x
                ycor + new-y - old-y ]
      set old-x new-x
      set old-y new-y
      ;; update the view, otherwise the user can't see
      ;; what's going on
      display
    ]
  ]
end

to deselect
  ask sides [ die ]
  ask selected [ set color blue ]
  set selected no-turtles
end

to select [x1 y1 x2 y2]   ;; x1 y1 is initial corner and x2 y2 is current corner
  deselect  ;; kill old selection square
  make-side x1 y1 x2 y1
  make-side x1 y1 x1 y2
  make-side x1 y2 x2 y2
  make-side x2 y1 x2 y2
  set selected turtles with [selected? xcor ycor]
  ask selected [ set color red ]
end

to make-side [x1 y1 x2 y2]
  ;; for each side, one thin line shape is created at the mid point of each segment
  ;; of the bounding box and scaled to the proper length
  create-sides 1 [
    set color gray
    setxy (x1 + x2) / 2
          (y1 + y2) / 2
    facexy x1 y1
    set size 2 * distancexy x1 y1
  ]
end

;; helper procedure that determines whether a point is
;; inside the selection square
to-report selected? [x y]
  if not any? sides [ report false ]
  let y-max max [ycor] of sides   ;; largest ycor is where the top is
  let y-min min [ycor] of sides   ;; smallest ycor is where the bottom is
  let x-max max [xcor] of sides   ;; largest xcor is where the right side is
  let x-min min [xcor] of sides   ;; smallest xcor is where the left side is
  ;; report whether the input coordinates are within the square
  report x >= x-min and x <= x-max and
         y >= y-min and y <= y-max
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).  Map Drawing NetLogo model.
;   Artificial Intelligence. Ventus Publishing Aps.
;