123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #!/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
- import datetime
- 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
- base = "maps"
- now = datetime.datetime.now()
- now = now.strftime("%Y-%m-%d_%X")
- print(now)
- directory = base + "/" + now
- try:
- os.makedirs(directory)
- except OSError as exception:
- if exception.errno != errno.EEXIST:
- raise
- for i in range(0, 99):
- nv = random.randint(10,20)
- verts = generatePolygon( ctrX=500, ctrY=500, aveRadius=300, irregularity=1, spikeyness=0.15, numVerts=nv )
- 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)-1 else verts[v+1];
- # print(p1)
- # print(p2)
- if random.randint(0,10) > 8:
- sda = "4 4"
- sdo = "5"
- else:
- sda = "0 0"
- sdo = "0"
- line = svg.line(p1, p2,
- stroke_width = "2",
- stroke = "black",
- stroke_linecap = "round",
- stroke_dasharray = sda,
- stroke_dashoffset = sdo)
- svg.add(line)
- 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.
|