mapgen.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # http://stackoverflow.com/questions/8997099/algorithm-to-generate-random-2d-polygon
  4. import os, glob, errno
  5. import math, random
  6. from PIL import Image, ImageDraw
  7. import svgwrite
  8. import datetime
  9. def generatePolygon( ctrX, ctrY, aveRadius, irregularity, spikeyness, numVerts ) :
  10. '''Start with the centre of the polygon at ctrX, ctrY,
  11. then creates the polygon by sampling points on a circle around the centre.
  12. Randon noise is added by varying the angular spacing between sequential points,
  13. and by varying the radial distance of each point from the centre.
  14. Params:
  15. ctrX, ctrY - coordinates of the "centre" of the polygon
  16. aveRadius - in px, the average radius of this polygon, this roughly controls how large the polygon is, really only useful for order of magnitude.
  17. irregularity - [0,1] indicating how much variance there is in the angular spacing of vertices. [0,1] will map to [0, 2pi/numberOfVerts]
  18. 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]
  19. numVerts - self-explanatory
  20. Returns a list of vertices, in CCW order.
  21. '''
  22. irregularity = clip( irregularity, 0,1 ) * 2*math.pi / numVerts
  23. spikeyness = clip( spikeyness, 0,1 ) * aveRadius
  24. # generate n angle steps
  25. angleSteps = []
  26. lower = (2*math.pi / numVerts) - irregularity
  27. upper = (2*math.pi / numVerts) + irregularity
  28. sum = 0
  29. for i in range(numVerts) :
  30. tmp = random.uniform(lower, upper)
  31. angleSteps.append( tmp )
  32. sum = sum + tmp
  33. # normalize the steps so that point 0 and point n+1 are the same
  34. k = sum / (2*math.pi)
  35. for i in range(numVerts) :
  36. angleSteps[i] = angleSteps[i] / k
  37. # now generate the points
  38. points = []
  39. angle = random.uniform(0, 2*math.pi)
  40. for i in range(numVerts) :
  41. r_i = clip( random.gauss(aveRadius, spikeyness), 0, 2*aveRadius )
  42. x = ctrX + r_i*math.cos(angle)
  43. y = ctrY + r_i*math.sin(angle)
  44. points.append( (int(x),int(y)) )
  45. angle = angle + angleSteps[i]
  46. return points
  47. def clip(x, min, max) :
  48. if( min > max ) : return x
  49. elif( x < min ) : return min
  50. elif( x > max ) : return max
  51. else : return x
  52. # create maps export folder
  53. base = "maps"
  54. now = datetime.datetime.now()
  55. now = now.strftime("%Y-%m-%d_%X")
  56. print(now)
  57. directory = base + "/" + now
  58. try:
  59. os.makedirs(directory)
  60. except OSError as exception:
  61. if exception.errno != errno.EEXIST:
  62. raise
  63. for i in range(0, 99):
  64. nv = random.randint(10,20)
  65. verts = generatePolygon( ctrX=500, ctrY=500, aveRadius=300, irregularity=1, spikeyness=0.15, numVerts=nv )
  66. index = str(i) if i > 9 else '0'+str(i)
  67. # ______ ________
  68. # / ___/ | / / ____/
  69. # \__ \| | / / / __
  70. # ___/ /| |/ / /_/ /
  71. # /____/ |___/\____/
  72. svg = svgwrite.Drawing(filename = directory+"/map"+index+".svg",size = ("1000px", "1000px"))
  73. # print(len(verts))
  74. for v in range(0, len(verts)):
  75. # print('---- '+str(v)+' ----')
  76. p1 = verts[v]
  77. p2 = verts[0] if v >= len(verts)-1 else verts[v+1];
  78. # print(p1)
  79. # print(p2)
  80. if random.randint(0,10) > 8:
  81. sda = "4 4"
  82. sdo = "5"
  83. else:
  84. sda = "0 0"
  85. sdo = "0"
  86. line = svg.line(p1, p2,
  87. stroke_width = "2",
  88. stroke = "black",
  89. stroke_linecap = "round",
  90. stroke_dasharray = sda,
  91. stroke_dashoffset = sdo)
  92. svg.add(line)
  93. svg.save()
  94. # __ _ __
  95. # / /_ (_) /_____ ___ ____ _____
  96. # / __ \/ / __/ __ `__ \/ __ `/ __ \
  97. # / /_/ / / /_/ / / / / / /_/ / /_/ /
  98. # /_.___/_/\__/_/ /_/ /_/\__,_/ .___/
  99. # /_/
  100. # black = (0,0,0)
  101. # white=(255,255,255)
  102. # im = Image.new('RGB', (1000, 1000), white)
  103. # imPxAccess = im.load()
  104. # draw = ImageDraw.Draw(im)
  105. # tupVerts = list(map(tuple,verts))
  106. #
  107. # # either use .polygon(), if you want to fill the area with a solid colour
  108. # # draw.polygon( tupVerts, outline=black,fill=white )
  109. #
  110. # # or .line() if you want to control the line thickness, or use both methods together!
  111. # draw.line( tupVerts+[tupVerts[0]], width=1, fill=black )
  112. #
  113. # # im.show()
  114. # im.save(directory+'/map-'+str(index)+'.bmp')
  115. # # now you can save the image (im), or do whatever else you want with it.