Wednesday, July 18, 2012

Erosion Algorithm



I read an article about some researchers who were trying to simulate erosion numerically a few years ago and I was somewhat disappointed by the purely random appearance of the terrains I was creating at the time so I wrote my own program for simulating erosion using Python.  This requires that you have python and PIL (Python Imaging Library) installed on your system.

The following two images illustrate before and after erosion is applied to the height map.

This results in decent erosion but the algorithm produces some sharp edges so I usually load the file into photoshop and give it some blur and adjust the contrast before rendering it.


from PIL import Image
from random import *

def erode(n=200000,nl=50,ev=.25,maxx=319,maxy=239):
    im = Image.open("gray_terrain01.png")
    
    for k in range(n):
        cx = int(uniform(1,maxx-1))
        cy = int(uniform(1,maxy-1))
        for l in range(nl):
            cv,cv,cv = im.getpixel((cx,cy))
            mini = cx
            minj = cy
            minv = cv
            #print "cent",cv
            for i in range(3):
                for j in range(3):
                    iv,iv,iv = im.getpixel((cx+i-1,cy+j-1))
                    #print iv
                    if (iv<minv):
                        mini = cx+i-1
                        minj = cy+j-1
                        minv = iv
            #print "min",mini,minj
            if (minv<cv):
                hard = (256.0-cv)/256.0
                erod_val = ev*hard
                iv = int(minv + (cv-minv)*erod_val)
                cv = int(cv - (cv-minv)*erod_val)
                #print "down",cv,
                #print "up",iv
                x = cv,cv,cv,
                y = iv,iv,iv,
                im.putpixel((cx,cy),x)
                im.putpixel((mini,minj),y)
                cx=mini
                cy=minj
            else:
                break
            if cx <= 0:
                break
            if cy <= 0:
                break
            if cx >= maxx-1:
                break
            if cy >= maxy-1:
                break
    
    im.save("eroded.png")

erode()



No comments:

Post a Comment