Created
May 9, 2018 11:00
-
-
Save Arth-ur/ad295b251c4664565741fb18b5ad4724 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image | |
import random | |
# size of one pixel | |
PIXEL_SIZE = 0.2 | |
# the scale is computed by dividing HEIGHT_RANGE by 128 | |
HEIGHT_RANGE = 0.4 | |
# the minimum height | |
HEIGHT_OFFSET = 0.01 | |
# should we inverse greyscale ? | |
INVERSE = False | |
# Dimensions | |
WIDTH = 16 | |
HEIGHT = 16 | |
# Top left position inside the image | |
ORIGINX = 90 | |
ORIGINY = 7 | |
# number of rocks | |
NROCKS = 50 | |
# number of pebbles | |
NPEBBLES = 50 | |
# a fraction of the area where the pebbles are located | |
PEBBLE_REGION=0.2 | |
if __name__ == '__main__': | |
# convert image to 8-bit grayscale | |
img = Image.open('noise.png').convert('L') | |
# crop image according to WIDTH and HEIGHT | |
img = img.crop((ORIGINX, ORIGINY, WIDTH + ORIGINX, HEIGHT + ORIGINY)) | |
# convert image to 2D array | |
data = list(img.getdata()) | |
# inverse grescale if needed | |
if INVERSE: | |
data = [ 128 - p for p in data] | |
# map greyscale to heights | |
heights = [p * (HEIGHT_RANGE / 128.0) for p in data] | |
# lower to map to minimum | |
min_height = min(heights) | |
heights = [height - min_height + HEIGHT_OFFSET for height in heights] | |
# create 2d heightmap | |
heightmap = [heights[offset:offset+WIDTH] | |
for offset in range(0, WIDTH*HEIGHT, WIDTH)] | |
# output map | |
for i in range(0, WIDTH): | |
for j in range(0, HEIGHT): | |
# compute coordinates | |
x = i * PIXEL_SIZE - WIDTH / 2 * PIXEL_SIZE | |
y = j * PIXEL_SIZE - WIDTH / 2 * PIXEL_SIZE | |
# retrieve height | |
height = heightmap[i][j] | |
# print obstacle | |
print('{x} {y} {sx} {sy} {sz} {d}'.format( | |
x=x, | |
y=y, | |
sx=PIXEL_SIZE, | |
sy=PIXEL_SIZE, | |
sz=height, | |
d=0.0 # infinite density | |
)) | |
# a list of tuples (x, y, z, sx, sy, sz, angle) | |
obstacles = [] | |
# add rocks | |
for i in range(0, NROCKS): | |
s = round(random.uniform(0.05, 0.2), 5) | |
while True: | |
x = round(random.uniform(-WIDTH/2.0+1, WIDTH/2.0-1) * PIXEL_SIZE, 5) | |
y = round(random.uniform(-HEIGHT/2.0+1, HEIGHT/2.0-1) * PIXEL_SIZE, 5) | |
# Safe zone | |
if abs(x) > 0.3 or abs(y) > 0.3: | |
break | |
z = max([ | |
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)], | |
heightmap[int((x + s) / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)], | |
heightmap[int((x - s) / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)], | |
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int((y + s) / PIXEL_SIZE + HEIGHT / 2.0)], | |
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int((y + s) / PIXEL_SIZE + HEIGHT / 2.0)], | |
]) + s / 2.0 - 0.1 | |
# rocks are allowed to collide with other rocks | |
# add rock to obstacles list | |
obstacles.append({'x': x, 'y': y, 'z': z, 'sx': s, 'sy': s, 'sz': s, 'a': 0.0}) | |
print('{x} {y} {z} {sx} {sy} {sz} {d}'.format( | |
x=x, | |
y=y, | |
z=z, | |
sx=s, | |
sy=s, | |
sz=s, | |
d=0.0 | |
)) | |
# add pebbles | |
for i in range(0, NPEBBLES): | |
while True: | |
s = round(random.uniform(0.02, 0.05), 5) | |
while True: | |
# pebbles are generated inside a pixel and at the center of the arena | |
xi = random.randint(int(PEBBLE_REGION*WIDTH) + 1, int((1-PEBBLE_REGION)*WIDTH-1)) | |
yi = random.randint(int(PEBBLE_REGION*HEIGHT) + 1, int((1-PEBBLE_REGION)*HEIGHT-1)) | |
x = round((xi - WIDTH/2) * PIXEL_SIZE + random.uniform(-PIXEL_SIZE/2+s, PIXEL_SIZE/2-s), 5) | |
y = round((yi - HEIGHT/2) * PIXEL_SIZE + random.uniform(-PIXEL_SIZE/2+s, PIXEL_SIZE/2-s), 5) | |
# Safe zone around robot | |
if abs(x) > 0.3 or abs(y) > 0.3: | |
break | |
z = heightmap[xi][int(yi)] + s / 2.0 | |
# pebbles are not allowed to collide with rocks or other pebbles | |
colliding = False | |
for obstacle in obstacles: | |
if ((x - obstacle['x'])**2 + (y - obstacle['y'])**2) <= (s / 2.0 + obstacle['sx'] / 2.0)**2: | |
colliding = True | |
break | |
if not colliding: break | |
# add pebbles to obstacles list | |
obstacles.append({'x': x, 'y': y, 'z': z, 'sx': s, 'sy': s, 'sz': s, 'a': 0.0}) | |
print('{x} {y} {z} {sx} {sy} {sz} {d}'.format( | |
x=x, | |
y=y, | |
z=z, | |
sx=s, | |
sy=s, | |
sz=s, | |
d=110.0 | |
)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment