terrain-workshop_2009


Information

Created with NetLogo version NetLogo 4.0.4
Running with NetLogoLite.jar version 404.


WHAT IS IT?


-------
This model produces simulated terrain using a variety of algorithms

HOW IT WORKS


--------

HOW TO USE IT


---------
Set the required parameters, click the buttons.

THINGS TO NOTICE


------------
Midpoint Displacement:
Notice how fast it is. This is because the implementation avoids use of ASK PATCHES and MOD, and instead directly creates agentsets of patches from the previous iterations patches.

THINGS TO TRY


---------

EXTENDING THE MODEL


---------------

NETLOGO FEATURES


------------
at-points
patch-set

RELATED MODELS


----------
watershed-model ;; also has a terrain generator, though it's rather primitive, special purpose, and silly.

CREDITS AND REFERENCES


------------------
http://www.lighthouse3d.com/opengl/terrain/index.php3?mpd
http://www.lighthouse3d.com/opengl/terrain/index.php?mpd2
http://en.wikipedia.org/wiki/Diamond-square_algorithm
http://www.gameprogrammer.com/fractal.html#diamond

Procedures

NetLogo Version: NetLogo 4.0.4


globals
[ 
]


patches-own
[ v ;; elevation
  _v ;; floor of elevation * scalar
]

to startup setup end

to setup
   ca
   display-message
   [ "Welcome to the Terrain Generator Workshop"
     ""
     "Featuring an assortment of simulated terrain generators"
     ""
     "Press the generator button to generate a sample"
   ]
end



to go
   setup-terrain-midpoint-displacement-fractal smoothness  
end
   
to setup-terrain
   cp ct
end

to setup-terrain-midpoint-displacement-fractal [ #roughness ]
   ;; note that, unlike other implementations found on the web
   ;; this implementation does NOT require the field to be square, nor
   ;; does it require the field grid to be sized at (1 + 2^n)
   ;; i.e. it world for any size gird of any ratio.
   ;; this is because it dynamically finds the minimum power of two needed
   ;; to correctly populate the provided grid.
     
   let time0 timer
  
   setup-terrain
   
   let r #roughness
   let md 1
   let rr 2 ^ (- r)
   ;; which dimention is smaller?
   let dim min (list world-width world-height)
   ;; use that dimension to figure out the initial gap to use
   let g 2 ^ ( floor (log (dim ) 2) - 1 )
   let diamond-set 0
   let square-set 0
   
   ask patches [ set v 0 ]
   
   set diamond-set (patch-set patch 0 0)
   
   repeat floor log world-width 2
   [ 
    set square-set (patch-set [my-parent-corners g] of diamond-set)

    ask square-set
    [ set v v + plus-or-minus md + mean [ v ] of my-parent-corners g
    ]
 
    set diamond-set (patch-set [ my-parent-points g ] of square-set)
   
    ask diamond-set
    [ set v v + plus-or-minus md  + mean [ v ] of my-parent-points g
    ]

    set g g / 2
    set md md * rr
  ]
     
  let time1 timer
  let timespan floor (time1 - time0)
  if timespan < 1 [ set timespan "< 1" ]
  print (word "MDF terrain generated for " count patches " patches in " timespan " seconds.")
  
  compress
  color-default  
end

to setup-terrain-bespoke-atoll [  ]
   setup-terrain
   
   let deepest 0
   let peaks 0
  
   ; build an irregular, circular island
   ; with a shallow center lagoon
   
   cp
      
   ; create overall ring shape
   ask patches
   [ let temp distancexy 0 0 
     ; sin wave, 0 at center, peak in middle, 0 at corners
     let temp3 temp * 360 / 3 / 100
     ; scale as distance from edge
     let temp2  2 * sin ( temp * 180 / max-pxcor ) * ( max-pxcor - abs pxcor) / max-pxcor * ( max-pycor - abs pycor) / max-pycor
     set v world-width * sin temp3 * temp2
   ]
 
   
   ;  add random peaks and dips, repeat
   repeat max-pxcor
   [ ; "picking peak/pit location"
     ask patch 0 0 [ set v (- world-width) ]
     set peaks n-of max-pxcor patches
     ; "talking to peaks"
     ask peaks
     [ set v v + max-pxcor * random 2 * 2 - 1
     ]
   ]
   ;; 
   ; erode, just a bit
   repeat 4
   [ ask patch 0 0 [ set v min-pxcor ]
     diffuse v .8
   ]
   
   

   ; add "stress ridges"
  ask patches
  [ ; get distance from center
    let temp distancexy 0 0
    let temp2 0
    ; get angle from center
    ifelse temp = 0
    [ set temp 1
      set temp2 0
    ]
    [ set temp2 ( towardsxy 0 0 + 180 ) 
      if temp2 > 360
      [ set temp2 temp2 - 360 ]
    ]
    ; set number of ridges
    let temp3 temp2 * 50
    set v v + (max-pxcor * sin temp3 + sin temp * .2 )/ temp
  ]   
  
  ;; apply non-linear scaling of v
  ask patches
  [ set v v * v ]
  
  compress
  color-default 
end


to-report my-parent-corners [ g ]
   let -g (- g)
   report patches at-points (list (list -g g) (list g g) (list g -g) (list -g -g ) )
   ;; to-do: maybe pre-calculate the at-points lists for each generation
   ;; save some time over generating them over and over
end

to-report my-parent-points [ g ]
   let -g (- g)
   report patches at-points (list (list 0 -g ) (list g 0) (list 0 g) (list -g 0) )
end   

to-report plus-or-minus [ n ]
   report n - 2 * random-float n
end

to setup-terrain-circles [ #number #connect ]
   setup-terrain
   
   let mr world-width * #connect
   let mrd mr / #number * .9
   let r 0
   let h 0
   let a 0
   let pm 1
   
   let candidates [ patches in-radius (world-width * (.75 - #connect)) ] of patch 0 0
   ask n-of #number candidates
   [ set r (.1 + random-float .5) * mr
     set h (.1 + random-float 1) * mr
     if subtract? [ set pm (((random 2)* 2)- 1) ]
     set a 180 / r ;
     ask patches in-radius r
     [ set v v + pm * h * cos ( .5 * a * distance myself ) ]
     set mr mr - mrd
   ]
   compress
   
   color-default
end


to setup-terrain-line-dropper [ #number #roundness ]
   setup-terrain
   ;; this has got to be super naive.
   ;; that is, there has to be a better way to decide on what side
   ;; of a line a point lies.
   
   ;; pick a center point and an angle
   ;; if the difference tween the angle and the heading from this point
   ;; to the center point is > 0 (and less than 180, natch)
   ;; then increment this patch
   ;; i.e. elevate patches on only one side of the line
   
   repeat #number
   [ let center one-of patches
     let angle random 360
     let inc .5 *  random-float 1
     let curve .5 * world-width * .1 * .5 * (#roundness + random-float #roundness)
     ask center [ set v v - inc ]
     ask patches with [ self != center ]
     [ ;; depending on which side of the line this patch falls...
       ifelse subtract-headings angle towards center > 0 
       [ let dist-from-line (distance center * sin (180 -  (angle - towards center ) ) )
         let inc' inc
         ;; calculate a smooth transition from one plane to the other
         if dist-from-line <= curve
         [ set inc' inc' * cos (( (curve - dist-from-line) / curve ) * 180  ) ]  
         set v v + inc'
       ]
       [ set v v - inc
       ]
     ]
  ]
   compress
   color-default
end

to setup-terrain-sin-wave-overlay [ #number  #max-frequency ]
   setup-terrain
   repeat #number ;; apply this number of waves to the view
   [ let freq random-float #max-frequency
     let amp random-float 1
     let offset random-float 1 * freq
     let angle random-float 360
     let wx sin angle
     let wy (- cos angle)
     ask patches [ set v v + amp * (sin (offset + freq * (pxcor * wx + pycor * wy))) ]
     ;; uncomment the below lines to see the application of each layer
     ; color-sample 
     ; display
     ; wait .1     
   ]
   compress
   color-default
 end

to setup-terrain-particle-deposition [ #iterations  ]
   setup-terrain
   
   let sp patch 0 0
   repeat #islands
   [
   
   let md 1 ; #max-displacement
   let od md
   ; let r #roughness
   let md-d 1 / #iterations
   
   let p sp
   let op p
   
   repeat #iterations
   [ ask p
     [ set p one-of neighbors4
       ; set v v + random-float md
     ]
     while [ is-patch? p ]
     [ ask p
       [ set op p
         ; set v v + random-float md
         set p one-of neighbors4 with [ v < [ v ] of myself and atan 1 (v - [v] of myself) > 45 ]
       ]
     ]
     ask op [ set v v + random-float md ]
     set p op ; op
     set md md - md-d
   ]
     set sp one-of patches 
     
   ]
   
    
   compress
   color-default  
end


   
   

;;_,-'-._,-'-._,-'-._,-'-._,-'-._,-'-._,-'-.
;; COMMONI PROCEDURES
;;_,-'-._,-'-._,-'-._,-'-._,-'-._,-'-._,-'-.

to color-default 
   ifelse default = 4 [ color-monochrome map-color ][
   ifelse default = 3 [ color-false-color-contour map-color ][
   ifelse default = 2 [ color-cartegraphic-contour ][
   ifelse default = 1 [ color-contours divisions ][
                        color-contours-mono divisions map-color
   ]]]]
end   

to compress
   let new-max 9.9
   let minv min [ v] of patches
   let maxv max [ v ] of patches
   let spanv maxv - minv
   if-else spanv != 0 
   [ 
     let s new-max / spanv
   
     ask patches [ set v (v - minv) * s ]
   ]
   [ ask patches [ set v 0 ]
   ]
end     

to color-mono-simple [ #color ]
   ask patches [ set pcolor v - 5 + #color ]
end   

to color-monochrome [ #color ]
   ;; assumes v has been scaled to 0.0...9.9
   ;; color the patches using V as the brightness, using the given color
   ask patches
   [ let pc v - gray + #color
     if-else shaded? 
     [ set pc scale-color #color (2.5 + .5 * v) 0 9.9 
       let s patch-at 1 -1 
       if is-patch? s
       [ if-else [ v] of s < v
         [ set pc max (list (pc - 2) (pc - (pc mod 10))) ]
         [ set pc min (list (pc + 2) (9.9 + pc - (pc mod 10))) ]
       ]
     ]
     [ ]
     set pcolor pc
   ]
end

to color-contours [ #div ]
   ask patches [ set _v  floor( #div * v) ]
   
   ask patches
   [ let n count neighbors with [ _v = [ _v ] of myself ]
     if n < 1 [ set n 1 ]
     set pcolor scale-color _v  n 0 8 ]
end   

to color-contours-mono [ #div #color ]
   ask patches [ set _v floor ( #div * v ) ]
   ask patches
   [ let n 1.2 * count neighbors with [ _v = [ _v ] of myself ]
     if n < 1 [ set n 1 ]
     set pcolor scale-color #color n  0 8
   ]
end 

to color-false-color-contour [ #div ]
   ;; color the patches as a false-color contour map
   ;; color slider determines the number of colors in the map
      
   ifelse graduated?
   [ let $div 10 * (#div - 1 ) / 9.9
     ask patches [ set pcolor 5 +  int(v * $div) ] ]
   [ ask patches [ set pcolor 5 + 10 * int(v * #div) ] ]
   
   display
end


to color-no-scale [ #color ]
   ;; color the patches using V as the brightness, using the given color
   ;; does not assume v has been scaled
   
   let minv min [ v] of patches
   let maxv max [ v ] of patches
   let spanv maxv - minv
   
   let cs spanv * .1
   let mins minv - cs
   let maxs maxv + cs
   
   ;; default: V = brightness
   ask patches [ set pcolor scale-color #color v minv maxv ] 
end

to color-cartegraphic-contour
   ;; color the patches using typical terrain map colors
      
   ;; default: V = brightness
   ask patches
   [ ifelse v < 3 [ set pcolor scale-color blue  v  0 4 ][
     ifelse v < 4 [ set pcolor scale-color yellow (- v) -4.5 -2.5 ][
     ifelse v < 6 [ set pcolor scale-color lime  v 0  12 ][
     ifelse v < 8 [ set pcolor scale-color green  v 4  12 ][
     ifelse v < 9 [ set pcolor scale-color brown  v 6 12 ][
                     set pcolor scale-color gray   v 5 9.9
     ]]]]]
   ]
end

to setup-3d-vis
   if is-applet?
   [ user-message "Note, this feature does not work in applet mode.\n\nPlease run the model directly, to use the 3d Viewer."
     stop
   ]
   
   let alt world-width * .1
   
   if count turtles != count patches
   [ ct
     foreach reverse sort patches
     [ ask ? [ sprout 1
       [ set shape "line"
         __set-line-thickness 2
         set heading 0
     ] ] ]
   ]
   ask turtles
   [ set size v * alt
     set color pcolor
   ]
end

to clear-3d-vis
   ask turtles [ die ]
   user-message "If it is open, please close the 3d vis window."
end





;;_,-'-._,-'-._,-'-._,-'-._,-'-._,-'-._,-'-.
;; UTILITY PROCEDURES
;;_,-'-._,-'-._,-'-._,-'-._,-'-._,-'-._,-'-.

to display-message [ message-list ]
   let pr (max-pycor - 4 ) 
   foreach message-list
   [ ask patch max-pxcor pr
     [ set plabel ?
       set plabel-color white
     ]
     set pr pr - 3
   ]
end

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download terrain-workshop_2009 --