Created with
NetLogo version NetLogo 3.0beta2
Running with NetLogoLite.jar version 302.
NetLogo Version: NetLogo 3.0beta2
; Watershed Model and Terrain Generator
; Version 1.1.2
; James Steiner
globals
[ ; levels-changed ; obsolete, used to flag if levels changed, to notify 3d update
peak ; the highest level of all the patches
middle ; the mean of the elev and level
valley ; the lowest elev of all the patches
spread ; the difference between the valley and peak
vm ; the valley-middle line, used for coloring
pm ; the peak-middle line, used for coloring
; both of the above normally equal to spread and peak
ticks ; count of flow-frames rendered, for by-eye estimation of fram rate
]
breeds
[ backdrops ; the backdrop of the 3d inset window
nodes ; the points of the 3d rendering
]
nodes-own
[ my-patch ; the source patch linked to this node
ox oy oe ; original coordinates
px py pel ; projected coordinates
pre-hide? ; part of the projection process
]
patches-own
[ elev ; "surface" level
level ; "water" level, equals elev when dry
; may never be less than elev
volume ; level - elev, the depth of the water, or the volume of water
temp ; used for various things
temp2
temp3
water-in
water-out
neighbors-nowrap ; the neighbors, without edge-wrapping
]
to startup
; river-valley
end
to update-all
; apply color and, if required, labels
no-display ; freeze display while updating
color-all ; apply color
label-all ; apply labels
display ; refresh display
; set levels-changed 1
end
to dry-all
; resets the "water" level to the elevation
; effectively drying the landscape
ask patches
[ set level elev ]
calc-measures
update-all
end
to diffuse-elev-nowrap
ask patches
[ set level .5 * ( elev + mean values-from neighbors-nowrap [ elev ] )
]
ask patches
[ set elev level
]
end
to define-neighbors-nowrap
ask patches
[ set neighbors-nowrap neighbors in-radius-nowrap 2
]
end
to river-valley
locals
[ lump-size
num-lumps
]
; generates a passable simulation of the elevations of a river valley
; flowing north to south
clear-turtles
clear-patches
define-neighbors-nowrap
if presets?
[ set river? true
set drain? true
set erupt? false
set source-rate 2
set altitude? false
set scale .5
set shift-x .45
set shift-y .45
]
note "creating valley contours"
; impress a valley shape
; store in LEVEL
ask patches
[ do-valley
]
set valley min values-from patches [ level ]
set peak max values-from patches [ level ]
if valley = peak
[ set valley valley - 2
set peak peak + 2
]
set spread peak - valley
;adjust valley to 0 .. 1
ask patches
[ set elev ( level - valley ) / spread * screen-edge-x]
note "adding random lumps"
dry-all wait .5
set num-lumps sqrt (screen-size-x * screen-size-y) * ( 1 - lumpiness * .01 )
ask random-n-of num-lumps patches
[ set lump-size 1 + screen-edge-x * .01 * (random-float lumpiness)
without-interruption
[ ask patches in-radius-nowrap lump-size
[ set elev elev + lump-size - ( distance-nowrap myself )
]
]
]
note "tilting landscape"
dry-all wait .5
; tilt the landscape so everything runs downhill
; slope set by steepness
ask patches
[ set elev elev + (pycor / screen-edge-y ) * spread * steepness * .02 ]
note ""
dry-all
end
to normalize-elev
; set min to 0, max to 100
calc-measures
ask patches
[ ; set min to 0
set elev (elev - valley )
; set max to screen-edge-x
set elev elev * 100 / spread
]
; adjust valley, peak, spread, middle
set valley 0
set peak screen-edge-x
set spread screen-edge-x
end
to do-valley
locals
[ elev-east-west
elev-north-south
elev-meander
px%
py%
adj-px%
px-cos
sweep-width
meander-freq
pwr
]
set pwr 1
set px% pxcor / screen-edge-x ; pxcor ==> -1 .. 1
set py% 1 - ( pycor + screen-edge-y ) / screen-size-y ; pycor ==> 0 .. 1
set sweep-width .01 * meander% ; .25 + .25 * sin ( py% * 45 )
set meander-freq py% * 180 * 4
set adj-px% ( (px% + sweep-width * sin ( meander-freq ) ) )
set elev-meander (abs adj-px%)
set level elev-meander
; set elev elev * ( 1 - scale) + level * elev-meander * scale
end
to calc-measures
; caluclate peak, valley, spread
set peak max values-from patches [ elev ]
set valley min values-from patches [ elev ]
if peak = valley
[ set peak peak + 2
set valley valley - 2
]
set middle (peak + valley) * .5
set spread abs ( peak - valley )
set vm (valley + middle) * 0.5
set pm (peak + middle) * 0.5
end
to add-wall
; add wall along back / top to prevent water
; from flowing backwards wrapping from bottom, etc.
; first, caluclate peak, valley, spread
set peak max values-from patches [ elev ]
set valley min values-from patches [ elev ]
set spread abs ( peak - valley )
; use values to elevate back edge %10 of depth of model
ask patches with [ pycor = screen-edge-y ]
[ set elev peak + spread * .1 ]
; scale it up
; ask patches
; [ set elev elev * 1000 ]
dry-all
end
to add-dam
locals [ height spillway ]
; adds a dam-like structure to the map
set height 1.3 * mean values-from patches [ elev ]
set spillway elev-of patch 0 0 + ( height - elev-of patch 0 0 ) * .5
ask patches with [ pycor = 0 and abs pxcor < screen-edge-x / 2.0 and elev < height ]
[ set elev height ]
ask patch 0 0
[ set elev spillway ]
dry-all
end
to volcano
locals [ deepest peaks ]
; build an irregular, circular island
; with a shallow center lagoon
; "clear patches"
cp
clear-3d
define-neighbors-nowrap
if presets?
[ set river? false
set drain? false
set erupt? true
set source-rate 50
set altitude? true
set scale .5
set shift-x .45
set shift-y .45
]
; "create overall ring shape"
ask patches
[ ; get distance from center
; "doing math"
set temp distancexy 0 0
; sin wave, 0 at center, peak in middle, 0 at corners
set temp3 temp * 360 / 3 / screen-edge-x
; scale as distance from edge
set temp2 2 * sin ( temp * 180 / screen-edge-x ) * ( screen-edge-x - abs pxcor) / screen-edge-x * ( screen-edge-y - abs pycor) / screen-edge-y
set elev screen-size-x * sin temp3 * temp2
]
; "add random peaks and dips, repeat"
repeat screen-edge-x
[ ; "picking peak/pit location"
set elev-of patch 0 0 (- screen-size-x)
set peaks random-n-of screen-edge-x patches
; "talking to peaks"
ask peaks
[ ; "set temp"
set temp random 2 * 2 - 1 ]
; "talking to peaks"
ask peaks
[ ; "set elev"
without-interruption
[ set elev elev + screen-edge-x * temp
]
]
]
; erode, just a bit
repeat 4
[ set elev-of patch 0 0 (- screen-edge-x)
diffuse-elev-nowrap
]
; add "stress ridges"
ask patches
[ ; get distance from center
set temp distancexy 0 0
; get angle from center
ifelse temp = 0
[ set temp2 0 ]
[ set temp2 ( towardsxy 0 0 + 180 )
if temp2 > 360
[ set temp2 temp2 - 360 ]
]
; set number of ridges
set temp3 temp2 * screen-edge-x / 3
set elev elev + screen-edge-x * sin temp3 * sin temp * .2
]
dry-all
end
to rain
; add water to entire surface, using rain-rate slider
; adds depth of rain that is up to 1/10000 the height of the terrain
ask patches
[ set level level + rain-rate * spread * .0001 ]
update-all
end ; rain
to rain-hard
; adds depth of rain that is up to 1/1000 height of terrain
ask patches
[ set level level + rain-rate * spread * .001 ]
update-all
end ; rain-hard
to do-sources-and-drains
; adds water at top center of window
if river?
[ ask min-one-of patches with [ pycor = ( screen-edge-y - 1 ) ] [ elev ]
[ set level level + source-rate
]
]
if erupt?
[ ask patch 0 0
[ set level level + source-rate ]
]
if drain?
[ ; removes water from bottom
ask patches with [ pycor = (- screen-edge-y) ]
[ set level level - volume * .1
]
]
end ; do-sources-and-drains
to evaporate-all
; reduce water level by "evap rate"
; which is linear and not proportional
; as it is due to surface area, not volume
if e-rate > 0 and evap?
[ ask patches with [ level > elev ]
[ set level level - e-rate
if level < elev
[ ; don't allow level to be below elev!
set level elev
]
]
]
end ; evaporate-all
to flow-all
evaporate-all
; to reduce flow bias created by natural netlogo patch code scheduling,
; only update 1 in 5 patches every turn
ask patches with [ level > elev and random 3 = 0 ]
[ flow-ver-2 ]
ask patches [ set level level - water-out + water-in set water-out 0 set water-in 0 ]
; add water every 5 turns
;if ticks mod 5 = 0
;[
do-sources-and-drains
update-all
;]
set ticks ticks + 1
if ticks > 1000000 [ set ticks 0 ]
end
to flow-ver-1
; if any neighbors with lower level
; pick random one of neigbors with LOWEST level
; move 1/2 of difference in level to that neighbor
; (so both are at a level)
locals
[ local-min
min-level
extra
portion
max-portion
]
without-interruption
[
if level - elev > 0
; if I am wet...
[ set min-level min values-from (neighbors-nowrap) [ level ]
if level > min-level
[ set local-min random-one-of (neighbors-nowrap) with [ level = min-level ]
set extra level - min-level
ifelse extra < .001
; if less than 1/1000 unit, it all flows down
[ set portion extra
]
[ set portion extra * .5
; if portion is more than is here, just take all of it
if portion > ( level - elev )
[ set portion level - elev
]
]
; adjust the levels
set level level - portion
ask local-min
[ set level level + portion
]
]
]
]
end
to flow-ver-2
; pick random one of neigbors with LOWEST level (lower than me!)
; move "flow-rate" (50%) of difference in level to that neighbor
;
locals
[ local-min
min-level
extra
portion
max-portion
low-neighbors
count-low-neighbors
slope
]
if level - elev > 0
; if I am wet...
[ set min-level min values-from (neighbors-nowrap) [ level ]
if level > min-level
[ set local-min random-one-of (neighbors-nowrap) with [ level = min-level ]
set extra level - min-level
; set slope atan 1 extra
ifelse extra < .001
; if less than 1/1000 unit, it all flows down
[ set portion extra
]
[ set portion extra * flow-rate
; if portion is more than is here, just take all of it
if portion > ( level - elev )
[ set portion level - elev
]
]
; adjust the levels
set water-out portion
set water-in-of local-min (water-in-of local-min) + portion
]
]
end
to label-all
; are labels requested?
ifelse labels?
[ ; yes. labels are requested
; ; altitude, or water depth?
ifelse altitude?
[ ; ; altitude / surface level
ask patches
[ set plabel (int (level))
]
]
[ ; show depth
ask patches
[ set plabel (int (level - elev))
]
]
]
[ ; no labels
; does patch 1 1 have a label?
if plabel-of patch 1 1 != no-label
[ ; it does, implying that all patches have labels.
; so, clear all labels
ask patches [ set plabel no-label ]
]
; this would seem to be faster than clearing all the labels every cycle
]
end
to color-all
ifelse hide-water?
[ ; use elev, not level, for display, and don't show water colors
ifelse false-color?
[ ; color using rainbow, to show-off contours
ask patches [ set pcolor 20 + 7 * scale-color gray elev valley peak ]
]
[ ask patches [ set pcolor get-earth-color ]
]
]
[ ; use level for display, using water colors as needed.
ask patches [ set volume level - elev ]
ifelse false-color?
[ ; color using rainbow, to show off contours
ask patches [ set pcolor 20 + 7 * scale-color gray level valley peak ]
]
[ ask patches [ set pcolor get-color ]
]
]
end
to-report get-color-from [ agent ]
locals [ result ]
ask agent [ set result get-color ]
report result
end
to-report get-color ; patch procedure
ifelse volume <= 0
[ report get-earth-color ]
[ report get-water-color ]
end
to-report get-water-color ; patch procedure
locals [ scaled-color ]
ifelse altitude?
[ set scaled-color -4 + .8 * scale-color gray level valley peak ]
[ set scaled-color 4 - .8 * scale-color gray volume 0 spread ]
ifelse erupt? or volume < .01
[ report red + scaled-color ]
[ report blue + scaled-color ]
end
to-report get-earth-color ; patch procedure
ifelse elev <= vm
[ report gray - 4 + .8 * scale-color gray elev valley middle ]
[ ifelse elev <= pm
[ report green - 4 + .8 * scale-color gray elev valley peak ]
[ report brown - 4 + .8 * scale-color gray elev middle peak ]
]
end
to setup-3d
clear-turtles
; create a turtle to use as a backdrop to hide the patches
; (instead of coloring the patches black)
create-custom-backdrops 1
[ setxy 0 0
set color black + 1
set shape "box-large"
set size screen-size-x
]
; these turtles, one for each patch
; show the points of elevation
ask patches
[ ; make a node turtle
sprout 1
[ set breed nodes
set my-patch patch-here
set color pcolor
set shape "circle-large"
set size 1.0
set heading 0
set ox xcor
set oy ycor
set oe level
]
]
render-3d
end
to render-3d
locals [ insetx insety insetw inseth insett insetl insetb insetr]
if not any? backdrops [ stop ]
set insetx screen-edge-x * shift-x
set insety screen-edge-y * shift-y
set insetw screen-edge-x * scale
set inseth screen-edge-y * scale
no-display
ask backdrops
[ setxy insetx insety
set size insetw * 2.1
]
ask nodes
[ set oe level-of my-patch
set color pcolor-of my-patch
; scale elevation so screen-edge-x cubic volume fits into 1/2 screen-height
set pel ( oe - valley ) / screen-size-x * screen-edge-y - screen-edge-y * .5
; spin X
set px ox * cos spin + oy * sin spin
; spin and tilt Y
set py (oy * cos spin - ox * sin spin) * cos tilt + pel * sin tilt
; scale and adjust center
set px px * scale
set py py * scale
set pre-hide? ( abs px > insetw or abs py > inseth)
set px px + insetx
set py py + insety
set hidden? pre-hide? or ( abs px > screen-edge-x or abs py > screen-edge-y ) or (slice-on? and ox != int (screen-edge-x * slice))
setxy px py
]
display
end
to full-view
set scale 1.0
set shift-x 0
set shift-y 0
set slice 0
set tilt 90
set spin 90
set spin? false
set presets? false
end
to render-3d-no-slice
locals [ insetx insety insetw inseth insett insetl insetb insetr]
if not any? backdrops [ stop ]
set insetx screen-edge-x * shift-x
set insety screen-edge-y * shift-y
set insetw screen-edge-x * scale
set inseth screen-edge-y * scale
no-display
ask backdrops
[ setxy insetx insety
set size insetw * 2.1
]
ask nodes
[ set oe level-of my-patch
set color pcolor-of my-patch
; scale elevation so screen-edge-x cubic volume fits into 1/2 screen-height
set pel ( oe - valley ) / screen-size-x * screen-edge-y - screen-edge-y * .5
; spin X
set px ox * cos spin + oy * sin spin
; spin and tilt Y
set py (oy * cos spin - ox * sin spin) * cos tilt + pel * sin tilt
; scale and adjust center
set px px * scale
set py py * scale
set pre-hide? ( abs px > insetw or abs py > inseth)
set px px + insetx
set py py + insety
set hidden? pre-hide? or ( abs px > screen-edge-x or abs py > screen-edge-y )
setxy px py
]
if size-of one-of nodes != scale * 2 [ ask nodes [ set size scale * 2 ] ]
display
end
to clear-3d
ask backdrops [ die ]
ask nodes [ die ]
update-all
end
to note [ text ]
ask patch 0 0
[ ifelse text = ""
[ set plabel no-label ]
[ set plabel text ]
]
end
watershed-114.5
View or download the complete model file (to download: right-click, save-link-as):
-- Download watershed-114.5 --