#!/usr/bin/python # -*- coding: utf-8 -*- # http://stackoverflow.com/questions/8997099/algorithm-to-generate-random-2d-polygon import os, glob, errno import math, random from PIL import Image, ImageDraw import svgwrite def generatePolygon( ctrX, ctrY, aveRadius, irregularity, spikeyness, numVerts ) : '''Start with the centre of the polygon at ctrX, ctrY, then creates the polygon by sampling points on a circle around the centre. Randon noise is added by varying the angular spacing between sequential points, and by varying the radial distance of each point from the centre. Params: ctrX, ctrY - coordinates of the "centre" of the polygon aveRadius - in px, the average radius of this polygon, this roughly controls how large the polygon is, really only useful for order of magnitude. irregularity - [0,1] indicating how much variance there is in the angular spacing of vertices. [0,1] will map to [0, 2pi/numberOfVerts] spikeyness - [0,1] indicating how much variance there is in each vertex from the circle of radius aveRadius. [0,1] will map to [0, aveRadius] numVerts - self-explanatory Returns a list of vertices, in CCW order. ''' irregularity = clip( irregularity, 0,1 ) * 2*math.pi / numVerts spikeyness = clip( spikeyness, 0,1 ) * aveRadius # generate n angle steps angleSteps = [] lower = (2*math.pi / numVerts) - irregularity upper = (2*math.pi / numVerts) + irregularity sum = 0 for i in range(numVerts) : tmp = random.uniform(lower, upper) angleSteps.append( tmp ) sum = sum + tmp # normalize the steps so that point 0 and point n+1 are the same k = sum / (2*math.pi) for i in range(numVerts) : angleSteps[i] = angleSteps[i] / k # now generate the points points = [] angle = random.uniform(0, 2*math.pi) for i in range(numVerts) : r_i = clip( random.gauss(aveRadius, spikeyness), 0, 2*aveRadius ) x = ctrX + r_i*math.cos(angle) y = ctrY + r_i*math.sin(angle) points.append( (int(x),int(y)) ) angle = angle + angleSteps[i] return points def clip(x, min, max) : if( min > max ) : return x elif( x < min ) : return min elif( x > max ) : return max else : return x # create maps export folder directory = "maps" try: os.makedirs(directory) except OSError as exception: if exception.errno != errno.EEXIST: raise # remove old image # os.chdir(directory) # files=glob.glob('*') # for filename in files: # os.unlink(filename) for i in range(0, 1): verts = generatePolygon( ctrX=500, ctrY=500, aveRadius=300, irregularity=1, spikeyness=0.15, numVerts=13 ) index = str(i) if i > 9 else '0'+str(i) # ______ ________ # / ___/ | / / ____/ # \__ \| | / / / __ # ___/ /| |/ / /_/ / # /____/ |___/\____/ svg = svgwrite.Drawing(filename = directory+"/map"+index+".svg",size = ("1000px", "1000px")) print(len(verts)) for v in range(0, len(verts)): print('---- '+str(v)+' ----') # p1 = verts[v] # p2 = verts[0] if v >= len(verts) else verts[v+1]; # print(p1) # print(p2) # svg.add(svg.line(p1, p2)) svg.save() # __ _ __ # / /_ (_) /_____ ___ ____ _____ # / __ \/ / __/ __ `__ \/ __ `/ __ \ # / /_/ / / /_/ / / / / / /_/ / /_/ / # /_.___/_/\__/_/ /_/ /_/\__,_/ .___/ # /_/ # black = (0,0,0) # white=(255,255,255) # im = Image.new('RGB', (1000, 1000), white) # imPxAccess = im.load() # draw = ImageDraw.Draw(im) # tupVerts = list(map(tuple,verts)) # # # either use .polygon(), if you want to fill the area with a solid colour # # draw.polygon( tupVerts, outline=black,fill=white ) # # # or .line() if you want to control the line thickness, or use both methods together! # draw.line( tupVerts+[tupVerts[0]], width=1, fill=black ) # # # im.show() # im.save(directory+'/map-'+str(index)+'.bmp') # # now you can save the image (im), or do whatever else you want with it.