I'd like this kind of city to be in a floodplain with a meandering river running through it, perhaps joining with another river. Accordingly I decided to start with the river and build up from there.
Random river construction is not something that is well-documented on the web. Luckily I know Dr. J. Wesley Lauer at Seattle University, who specializes in the interaction between rivers and their floodplains. He's given me a couple of leads to follow.
The simplest model of a meandering river is a sine-generated curve, also known as a meander curve. The river direction oscillates via a sine wave as a function of arc length. Scaling the direction angle results in a river that meanders more or less. Here are some examples (maximum angles of 1.0, 1.5, and 2.0 respectively):
Here's an example with a varying direction angle scale:
It's really easy to generate these. Here's some Python code I used to generate the SVG diagrams above:
from math import sin, cos
viewSizeX = 300
viewSizeY = 300
x = 0
y = 20
angle = 0
angle_inc = 0.1
dir_scale = 1.0
step_size = 4.0
points = [(x, y)]
while x < viewSizeX:
dir_angle = dir_scale * sin(angle)
dir_x = step_size * cos(dir_angle)
dir_y = step_size * sin(dir_angle)
angle += angle_inc
x += dir_x
y += dir_y
print '<?xml version="1.0" encoding="UTF-8" ?>'
print '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="%d" height="%d">' % (viewSizeX, viewSizeY)
print ' <g fill="none" stroke="blue" stroke-width="2">'
print ' <polyline points="%s"/>' % (' '.join(map(lambda p: '%g,%g' % (p, p), points)))
print ' </g>'
The next step is to replace my rather-lame first attempt at river shaping with something based on sine-generated curves. Here's what I'd be replacing:
The rivers in this version are based on some quadratic curves. The buildings are just splattered down in such a way as to not overlap; that'll be replaced with an algorithm that generates streets and city blocks and then subdivides the blocks into buildings. There's a bunch of little green lines which represent a gradient estimate, which I may use to guide some of the roads.