دمج فرع التتبع عن بعد "المنبع/الرئيسي" في الملف الرئيسي

This commit is contained in:
AKreuzer
2024-06-15 23:01:59 +02:00
25 changed files with 1468 additions and 44 deletions

925
House.py Normal file
View File

@@ -0,0 +1,925 @@
from time import sleep
from gdpc import Editor, Block, geometry
import numpy as np
import math
import matplotlib.pyplot as plt
class House:
def __init__(self, editor, coordinates_min, coordinates_max, direction, list_block):
self.editor = editor
self.coordinates_min = coordinates_min
self.coordinates_max = coordinates_max
self.skeleton = []
size = [(coordinates_max[i] - coordinates_min[i]) + 10 for i in range(3)]
self.grid3d = np.zeros(size, dtype=[('bool', bool), ('int', int)])
self.nbEtage = (coordinates_max[1] - coordinates_min[1]) // 5
self.direction = direction
self.entranceWall = None
self.blocks = list_block
self.entranceCo = None
self.wall = Block(list_block["wall"])
self.roof = Block(list_block["roof"])
self.roof_slab = Block(list_block["roof_slab"])
self.door = Block(list_block["door"])
self.window = Block(list_block["window"])
self.entrance = Block(list_block["entrance"])
self.stairs = Block(list_block["stairs"])
self.celling = Block(list_block["celling"])
self.floor = Block(list_block["floor"])
self.celling_slab = Block(list_block["celling_slab"])
self.gardenOutline = Block(list_block["garden_outline"])
self.garden_floor = Block(list_block["garden_floor"])
def createHouseSkeleton(self):
self.delete()
x_min, y_min, z_min = self.coordinates_min
x_max, y_max, z_max = self.coordinates_max
perimeter_width = x_max - x_min
perimeter_depth = z_max - z_min
x_min += 1
z_min += 1
x_max -= 1
z_max -= 1
x = np.random.randint(x_min+1 , x_max-1)
z = np.random.randint(z_min+1 , z_max-1 )
width = perimeter_width // 2
depth = perimeter_depth // 2
height = y_max - y_min
if x + width-1 > x_max-1:
x = x_max - width-1
if z + depth-1 > z_max-1:
z = z_max - depth-1
x_plan3d = x - x_min
z_plan3d = z - z_min
for i in range(0, width-1):
for j in range(0, depth-1):
self.editor.placeBlock((x + i, y_min, z + j), self.floor)
self.grid3d[x_plan3d+i,0,z_plan3d+j] = True,1
self.skeleton.append((x, z, width-1, depth-1, height))
print("Coordinates of the corners: ", (x, z), (x, z+depth-1), (x+width-1, z), (x+width-1, z+depth-1))
x_min -= 1
x_max -= 1
z_min += 1
z_max += 1
for _ in range(3):
print("Rectangle n°", _+1, "en cours de création")
for a in range(100000):
new_width = np.random.randint(5, width-2)
new_depth = np.random.randint(5, depth-2)
new_x = np.random.randint(max(x_min+1, x - new_width ), min(x_max-new_width - 1, x + width ))
new_z = np.random.randint(max(z_min+1, z - new_depth), min(z_max-new_depth - 1, z + depth ))
new_x_plan3d = new_x - x_min -1
new_z_plan3d = new_z - z_min +1
adjacent_blocks = 0
for i in range(new_x_plan3d, new_x_plan3d + new_width):
for j in range(new_z_plan3d, new_z_plan3d + new_depth):
if self.grid3d[i-1,0,j]['bool'] and self.grid3d[i-1,0,j]['int']==1 or self.grid3d[i+1,0,j]['bool'] and self.grid3d[i+1,0,j]['int']==1 or self.grid3d[i,0,j-1]['bool'] and self.grid3d[i,0,j-1]['int']==1 or self.grid3d[i,0,j+1]['bool'] and self.grid3d[i,0,j+1]['int']==1:
adjacent_blocks += 1
if adjacent_blocks < 3:
continue
if not np.any(self.grid3d[new_x_plan3d:new_x_plan3d+new_width,0, new_z_plan3d:new_z_plan3d+new_depth]['bool']):
new_x_plan3d = new_x - x_min
new_z_plan3d = new_z - z_min
for i in range(0, new_width):
for j in range(0, new_depth):
self.grid3d[new_x_plan3d + i,0, new_z_plan3d + j] = True,2
if i == 0 or i == new_width-1 or j == 0 or j == new_depth-1:
continue
else:
self.editor.placeBlock((new_x + i, y_min, new_z + j), self.floor)
self.skeleton.append((new_x, new_z, new_width, new_depth, height))
break
else:
print("Failed to place rectangle after 1000 attempts.")
def delete(self):
for x in range(self.coordinates_min[0], self.coordinates_max[0]):
for y in range(self.coordinates_min[1], self.coordinates_max[1]+10):
for z in range(self.coordinates_min[2], self.coordinates_max[2]):
self.editor.placeBlock((x, y, z), Block("air"))
def putWallOnSkeleton(self):
for k in range(len(self.skeleton)):
x, z, width, depth, height = self.skeleton[k]
if k!= 0:
x+=1
z+=1
width-=2
depth-=2
x_plan3d = x - self.coordinates_min[0]
z_plan3d = z - self.coordinates_min[2]
for i in range(-1, width+1):
for j in range(-1, depth+1):
for y in range(0, height):
if i == -1 or i == width or j == -1 or j == depth:
if not (self.grid3d[x_plan3d + i,y, z_plan3d + j]['bool']) and not (self.grid3d[x_plan3d + i,y, z_plan3d + j]['int'] == 1) or (self.grid3d[x_plan3d + i,y, z_plan3d + j]['bool'] and self.grid3d[x_plan3d + i,y, z_plan3d + j]['int'] == 2) or y==0:
self.editor.placeBlock((x + i, self.coordinates_min[1] + y, z + j), self.wall)
self.grid3d[ x_plan3d+i, y, z_plan3d+j] = True
def getAdjacentWalls(self):
main_rect = self.skeleton[0]
x_main, z_main, width_main, depth_main, heigt_main = main_rect
adjacent_walls = []
width_main-=1
depth_main-=1
for k in range(1, len(self.skeleton)):
x, z, width, depth, heigt = self.skeleton[k]
walls = [(x, z, x + width-1, z), (x, z, x, z + depth-1), (x, z + depth-1, x + width-1, z + depth-1), (x + width-1, z, x + width-1, z + depth-1)]
for wall in walls:
x1, z1, x2, z2 = wall
if (x_main <= x1 <= x_main + width_main or x_main <= x2 <= x_main + width_main) and (z_main - 1 == z1 or z_main + depth_main + 1 == z1):
x1 = max(x1, x_main-1)
x2 = min(x2, x_main + width_main+1)
if abs(x2 - x1) > 1:
adjacent_walls.append((x1, z1, x2, z2))
elif (z_main <= z1 <= z_main + depth_main or z_main <= z2 <= z_main + depth_main) and (x_main - 1 == x1 or x_main + width_main + 1 == x1):
z1 = max(z1, z_main-1)
z2 = min(z2, z_main + depth_main+1)
if abs(z2 - z1) > 1:
adjacent_walls.append((x1, z1, x2, z2))
return adjacent_walls
def placeDoor(self):
walls = self.getAdjacentWalls()
for wall in walls:
for i in range(self.nbEtage):
x_min, z_min, x_max, z_max = wall
if x_min == x_max:
width = z_max - z_min
if width % 2 != 0:
door_pos = width // 2
for y in range(self.coordinates_min[1]+1+i*4, self.coordinates_min[1]+3+i*4):
self.editor.placeBlock((x_min, y, z_min + door_pos), Block("air"))
self.editor.placeBlock((x_min, y, z_min + door_pos+1), Block("air"))
else:
door_pos = width // 2
for y in range(self.coordinates_min[1]+1+i*4 , self.coordinates_min[1]+3+i*4):
self.editor.placeBlock((x_min, y, z_min + door_pos), Block("air"))
else:
width = x_max - x_min
if width % 2 != 0:
door_pos = width // 2
for y in range(self.coordinates_min[1]+1+i*4, self.coordinates_min[1]+3+i*4):
self.editor.placeBlock((x_min + door_pos, y, z_min), Block("air"))
self.editor.placeBlock((x_min + door_pos+1, y, z_min), Block("air"))
else:
door_pos = width // 2
for y in range(self.coordinates_min[1]+1+i*4, self.coordinates_min[1]+3+i*4):
self.editor.placeBlock((x_min + door_pos, y, z_min), Block("air"))
def placeRoof(self):
for k in range(len(self.skeleton)-1, -1, -1):
x, z, width, depth, height = self.skeleton[k]
if k!= 0:
x+=1
z+=1
width-=2
depth-=2
if width < depth:
if width <=5:
n = 1
elif width <=10:
n = 2
else:
n = 3
else:
if depth <=5:
n = 1
elif depth <=10:
n = 2
else:
n = 3
else:
if width < depth:
n = width // 4
else:
n = depth // 4
x_plan3d = x - self.coordinates_min[0]
z_plan3d = z - self.coordinates_min[2]
print(width, depth, n)
if width < depth:
if n>1:
for k in range(n-1):
for i in range(-1, depth+1):
for y in range(-1, width//2+1):
self.editor.placeBlock((x + i, self.coordinates_max[1]+k, z+y+k+3), self.roof)
self.editor.placeBlock((x + i, self.coordinates_max[1]+k, z+depth-y-4-k), self.roof)
if width%2 == 0:
for i in range(-1, depth+1):
self.editor.placeBlock((x+width//2+1, self.coordinates_max[1]+n-1, z+i), self.roof)
for i in range(-1,depth+1):
self.editor.placeBlock((x+width//2, self.coordinates_max[1]+n-1, z+i), self.roof)
else:
if n>1:
for k in range(n-1):
for i in range(-1, width+1):
for y in range(-1, depth//2+1):
self.editor.placeBlock((x + i, self.coordinates_max[1]+k, z+y+k+2), self.roof)
self.editor.placeBlock((x + i, self.coordinates_max[1]+k, z+depth-y-3-k), self.roof)
if depth%2 == 0:
for i in range(-1, width+1):
self.editor.placeBlock((x+i, self.coordinates_max[1]+n-1, z+depth//2+1), self.roof)
for i in range(-1,width+1):
self.editor.placeBlock((x+i, self.coordinates_max[1]+n-1, z+depth//2), self.roof)
print('-----------------------------------')
for i in range(-1, width+1):
for j in range(-1, depth+1):
if width<depth:
if width%2 != 0:
if (i == width//2 ):
self.editor.placeBlock((x + i, self.coordinates_max[1]+n, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i, height+n, z_plan3d+j] = True
if j== -1 :
if not self.grid3d[ x_plan3d+i, height+n, z_plan3d+j-1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+n, z + j-1), Block(self.blocks["celling_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i, height+n, z_plan3d+j-1] = True
if not self.grid3d[ x_plan3d+i, height+n-1, z_plan3d+j-1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+n-1, z + j-1), Block(self.blocks["celling_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+i, height+n-1, z_plan3d+j-1] = True
elif j == depth:
if not self.grid3d[ x_plan3d+i, height+n, z_plan3d+j+1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+n, z + j+1), Block(self.blocks["celling_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i, height+n, z_plan3d+j+1] = True
if not self.grid3d[ x_plan3d+i, height+n-1, z_plan3d+j+1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+n-1, z + j+1), Block(self.blocks["celling_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+i, height+n-1, z_plan3d+j+1] = True
else:
if depth%2 != 0:
if (j == depth//2 ):
self.editor.placeBlock((x + i, self.coordinates_max[1]+n, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i, height+n, z_plan3d+j] = True
if i== -1 :
if not self.grid3d[ x_plan3d+i-1, height+n, z_plan3d+j]:
self.editor.placeBlock((x + i-1, self.coordinates_max[1]+n, z + j), Block(self.blocks["celling_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i-1, height+n, z_plan3d+j] = True
if not self.grid3d[ x_plan3d+i-1, height+n-1, z_plan3d+j]:
self.editor.placeBlock((x + i-1, self.coordinates_max[1]+n-1, z + j), Block(self.blocks["celling_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+i-1, height+n-1, z_plan3d+j] = True
elif i == width:
if not self.grid3d[ x_plan3d+i+1, height+n, z_plan3d+j]:
self.editor.placeBlock((x + i+1, self.coordinates_max[1]+n, z + j), Block(self.blocks["celling_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+i+1, height+n, z_plan3d+j] = True
if not self.grid3d[ x_plan3d+i+1, height+n-1, z_plan3d+j]:
self.editor.placeBlock((x + i+1, self.coordinates_max[1]+n-1, z + j), Block(self.blocks["celling_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+i+1, height+n-1, z_plan3d+j] = True
if width<depth:
h = 0
for i in range(-1, width//2):
for j in range(-1, depth+1):
if i != -1:
if h % 1 == 0:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"top"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j] = True
if j == -1 :
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j -1), self.celling)
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j -1), self.celling)
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j-1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j-1] = True
elif j == depth:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j +1), self.celling)
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j +1), self.celling)
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j+1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j+1] = True
else:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + i, self.coordinates_max[1]+h-0.5, z + j), self.roof)
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h-0.5, z + j), self.roof)
self.grid3d[ x_plan3d+ i, round(height+h+0.5), z_plan3d+ j] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h+0.5), z_plan3d+ j] = True
self.grid3d[ x_plan3d+ i, round(height+h-0.5), z_plan3d+ j] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h-0.5), z_plan3d+ j] = True
if j == -1 :
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j -1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j -1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + i, self.coordinates_max[1]+h-1, z + j -1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h-1, z + j -1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+ i, round(height+h-1), z_plan3d+ j-1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h-1), z_plan3d+ j-1] = True
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j-1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j-1] = True
elif j == depth:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j +1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j +1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + i, self.coordinates_max[1]+h-1, z + j +1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h-1, z + j +1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+ i, round(height+h-1), z_plan3d+ j+1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h-1), z_plan3d+ j+1] = True
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j+1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j+1] = True
else:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.grid3d[ x_plan3d+ i, round(height+h), z_plan3d+ j] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h), z_plan3d+ j] = True
if j == -1 :
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j -1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j -1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
if not self.grid3d[ x_plan3d+i, height+h-1, z_plan3d+j-1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h-1, z + j -1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+i, height+h-1, z_plan3d+j-1] = True
if not self.grid3d[ x_plan3d+width-1-i, height+h-1, z_plan3d+j-1]:
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h-1, z + j -1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+width-1-i, height+h-1, z_plan3d+j-1] = True
self.grid3d[ x_plan3d+ i, round(height+h-1), z_plan3d+ j-1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h-1), z_plan3d+ j-1] = True
elif j == depth:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h, z + j +1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h, z + j +1), Block(self.blocks["celling_slab"], {"type": "bottom"}))
if not self.grid3d[ x_plan3d+i, height+h-1, z_plan3d+j+1]:
self.editor.placeBlock((x + i, self.coordinates_max[1]+h-1, z + j +1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+i, height+h-1, z_plan3d+j+1] = True
if not self.grid3d[ x_plan3d+width-1-i, height+h-1, z_plan3d+j+1]:
self.editor.placeBlock((x + width-1-i, self.coordinates_max[1]+h-1, z + j +1), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ x_plan3d+width-1-i, height+h-1, z_plan3d+j+1] = True
self.grid3d[ x_plan3d+ i, round(height+h-1), z_plan3d+ j+1] = True
self.grid3d[ x_plan3d+ width-1-i, round(height+h-1), z_plan3d+ j+1] = True
if i != -1:
h += 0.5
else:
h = 0
for i in range(-1, depth//2):
for j in range(-1, width+1):
if i != -1:
if h % 1 == 0:
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + i), Block(self.blocks["roof_slab"],{"type":"top"}))
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + depth-1-i), Block(self.blocks["roof_slab"],{"type":"top"}))
self.grid3d[ x_plan3d+j, round(height+h), z_plan3d+ i] = True
self.grid3d[ x_plan3d+j, round(height+h), z_plan3d+ depth-1-i] = True
if j == -1 :
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + i ), self.celling)
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + depth-1-i ), self.celling)
self.grid3d[ x_plan3d+j-1, round(height+h), z_plan3d+ i] = True
self.grid3d[ x_plan3d+j-1, round(height+h), z_plan3d+ depth-1-i] = True
elif j == width:
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + i ), self.celling)
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + depth-1-i ), self.celling)
self.grid3d[ x_plan3d+j+1, round(height+h), z_plan3d+ i] = True
self.grid3d[ x_plan3d+j+1, round(height+h), z_plan3d+ depth-1-i] = True
else:
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + i), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + depth-1-i), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + j, self.coordinates_max[1]+h-0.5, z + i), self.roof)
self.editor.placeBlock((x + j, self.coordinates_max[1]+h-0.5, z + depth-1-i), self.roof)
self.grid3d[ j, round(height+h+0.5), i] = True
self.grid3d[ j, round(height+h+0.5), depth-1-i] = True
self.grid3d[ j, round(height+h-0.5), i] = True
self.grid3d[ j, round(height+h-0.5), depth-1-i] = True
if j == -1 :
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h-1, z + i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h-1, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
self.grid3d[ j, round(height+h-1), i] = True
self.grid3d[ j, round(height+h-1), depth-1-i] = True
elif j == width:
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h-1, z + i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h-1, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
self.grid3d[ j, round(height+h-1), i] = True
self.grid3d[ j, round(height+h-1), depth-1-i] = True
else:
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + i), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.editor.placeBlock((x + j, self.coordinates_max[1]+h, z + depth-1-i), Block(self.blocks["roof_slab"],{"type":"bottom"}))
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
if j == -1 :
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
if not self.grid3d[ j, height+h-1, i]:
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h-1, z + i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, height+h-1, i] = True
if not self.grid3d[ j, height+h-1, depth-1-i]:
self.editor.placeBlock((x + j -1, self.coordinates_max[1]+h-1, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, height+h-1, depth-1-i] = True
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
elif j == width:
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "bottom"}))
if not self.grid3d[ j, height+h-1, i]:
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h-1, z + i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, height+h-1, i] = True
if not self.grid3d[ j, height+h-1, depth-1-i]:
self.editor.placeBlock((x + j +1, self.coordinates_max[1]+h-1, z + depth-1-i ), Block(self.blocks["celling_slab"], {"type": "top"}))
self.grid3d[ j, height+h-1, depth-1-i] = True
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
self.grid3d[ j, round(height+h), i] = True
self.grid3d[ j, round(height+h), depth-1-i] = True
if i != -1:
h += 0.5
QUARTZ_SLAB = Block(self.blocks["celling_slab"], {"type": "top"})
for i in range(-2, width+2):
for j in range(-2, depth+2):
if i == -2 or i == width+1 or j == -2 or j == depth+1:
if not self.grid3d[x_plan3d+i, height-1, z_plan3d+j]['bool']:
if width<depth:
if i == -2 or i == width+1:
self.editor.placeBlock((x + i, self.coordinates_max[1]-1, z + j), QUARTZ_SLAB)
else:
if j == -2 or j == depth+1:
self.editor.placeBlock((x + i, self.coordinates_max[1]-1, z + j), QUARTZ_SLAB)
def putCelling(self):
for k in range(0, len(self.skeleton)):
x, z, width, depth, height = self.skeleton[k]
if k!= 0:
x+=1
z+=1
width-=2
depth-=2
x_plan3d = x - self.coordinates_min[0]
z_plan3d = z - self.coordinates_min[2]
for y in range(1,self.nbEtage+1):
for i in range(0, width):
for j in range(0, depth):
self.editor.placeBlock((x + i, self.coordinates_min[1] +4*y, z + j), self.celling)
self.grid3d[ x_plan3d+i, 4*y, z_plan3d+j] = True
def getAllExterneWalls(self):
walls = []
adjacent_walls = self.getAdjacentWalls()
for k in range(0, len(self.skeleton)):
x, z, width, depth, height = self.skeleton[k]
if k == 0:
x -= 1
z -= 1
width += 2
depth += 2
walls.append((x, z, x + width - 1, z))
walls.append((x, z, x, z + depth - 1))
walls.append((x, z + depth - 1, x + width - 1, z + depth - 1))
walls.append((x + width - 1, z, x + width - 1, z + depth - 1))
walls_to_keep = []
for wall in walls:
remove_wall = False
for adj_wall in adjacent_walls:
if self.isInsideWall(wall, adj_wall):
remove_wall = True
break
if not remove_wall:
walls_to_keep.append(wall)
return walls_to_keep
def isInsideWall(self, big_wall, small_wall):
x1, z1, x2, z2 = big_wall
x3, z3, x4, z4 = small_wall
if x1 == x2 == x3 == x4:
return x1 == x3 and z1 <= z3 and z4 <= z2
elif z1 == z2 == z3 == z4:
return z1 == z3 and x1 <= x3 and x4 <= x2
def placeWindowOnWall(self,wall,axis, is_x):
for l in range(self.nbEtage):
if axis%2==0:
if axis == 4:
if is_x:
self.editor.placeBlock((wall[0]+2, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
self.editor.placeBlock((wall[0]+3, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
else:
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+3), self.window)
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+2), self.window)
else:
for i in range(0, math.ceil(axis/4)):
if is_x:
self.editor.placeBlock((wall[0]+1+i*4, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
self.editor.placeBlock((wall[0]+2+i*4, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
else:
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+1+i*4), self.window)
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+2+i*4), self.window)
else:
if axis<=5:
for i in range(0, axis):
if is_x:
self.editor.placeBlock((wall[0]+1+i, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
else:
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+1+i), self.window)
else:
for i in range(0, math.ceil(axis/2)):
if is_x:
self.editor.placeBlock((wall[0]+i*2+1, self.coordinates_min[1] + 2+l*4, wall[1]), self.window)
else:
self.editor.placeBlock((wall[0], self.coordinates_min[1] + 2+l*4, wall[1]+i*2+1), self.window)
def placeWindow(self):
walls = self.getAllExterneWalls()
for wall in walls:
x1, z1, x2, z2 = wall
x = abs(x2-x1) -1
z = abs(z2-z1) -1
if x1 == x2:
self.placeWindowOnWall(wall, z, False)
elif z1 == z2:
self.placeWindowOnWall(wall, x, True)
def placeStairs(self):
x, z, width, depth, height = self.skeleton[0]
x_moy = x + width//2
z_moy = z + depth//2
slab_up = Block(self.blocks["stairs_slab"], { "type": "top"})
slab_down = Block(self.blocks["stairs_slab"], { "type": "bottom"})
for i in range(0, self.nbEtage-1):
for k in range(3):
for l in range(3):
self.editor.placeBlock((x_moy-1+k, self.coordinates_min[1] + 4*(i+1), z_moy-1+l),Block("air"))
for j in range(1, 5):
self.editor.placeBlock((x_moy, self.coordinates_min[1] + 4*i+j, z_moy), self.floor)
self.editor.placeBlock((x_moy-1, self.coordinates_min[1] +1+ 4*i, z_moy-1), slab_down)
self.editor.placeBlock((x_moy, self.coordinates_min[1] +1+ 4*i, z_moy-1), slab_up)
self.editor.placeBlock((x_moy+1, self.coordinates_min[1] +2+ 4*i, z_moy-1), slab_down)
self.editor.placeBlock((x_moy+1, self.coordinates_min[1] +2+ 4*i, z_moy), slab_up)
self.editor.placeBlock((x_moy+1, self.coordinates_min[1] +3+ 4*i, z_moy+1), slab_down)
self.editor.placeBlock((x_moy, self.coordinates_min[1] +3+ 4*i, z_moy+1), slab_up)
self.editor.placeBlock((x_moy-1, self.coordinates_min[1] +4+ 4*i, z_moy+1), slab_down)
self.editor.placeBlock((x_moy-1, self.coordinates_min[1] +4+ 4*i, z_moy), slab_up)
def WallFacingDirection(self):
if self.direction == "N":
closest_wall = min(self.skeleton, key=lambda wall: wall[1])
wall = (closest_wall[0], closest_wall[1], closest_wall[0] + closest_wall[2], closest_wall[1])
elif self.direction == "S":
closest_wall = max(self.skeleton, key=lambda wall: wall[1] + wall[3])
wall = (closest_wall[0], closest_wall[1] + closest_wall[3], closest_wall[0] + closest_wall[2], closest_wall[1] + closest_wall[3])
elif self.direction == "E":
closest_wall = max(self.skeleton, key=lambda wall: wall[0] + wall[2])
wall = (closest_wall[0] + closest_wall[2], closest_wall[1], closest_wall[0] + closest_wall[2], closest_wall[1] + closest_wall[3])
elif self.direction == "W":
closest_wall = min(self.skeleton, key=lambda wall: wall[0])
wall = (closest_wall[0], closest_wall[1], closest_wall[0], closest_wall[1] + closest_wall[3])
else:
return []
if closest_wall != self.skeleton[0]:
if wall[0] == wall[2]:
wall = (wall[0]-1, wall[1]+1, wall[2]-1, wall[3]-2)
elif wall[1] == wall[3]:
wall = (wall[0]+1, wall[1]-1, wall[2]-2, wall[3]-1)
else:
if wall[0] == wall[2]:
if self.direction == "W":
wall = (wall[0]-2, wall[1], wall[2]-2, wall[3])
else:
wall = (wall[0], wall[1]+1, wall[2], wall[3]-2)
elif wall[1] == wall[3]:
if self.direction == "N":
wall = (wall[0]+1, wall[1]-2, wall[2]-2, wall[3]-2)
else:
wall = (wall[0]+1, wall[1], wall[2]-2, wall[3])
return wall
def placeEntrance(self):
wall = self.WallFacingDirection()
print(wall)
self.entranceWall = wall
match self.direction:
case "W":
if (wall[3] - wall[1]) % 2 != 0:
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2 +1), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2 +1), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 +2), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +2), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.entranceCo = ((wall[1] + wall[3]) // 2, (wall[1] + wall[3]) // 2 +2, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 -1)
else:
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1], (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.entranceCo = ((wall[1] + wall[3] )// 2, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 -1)
case "N":
if (wall[2] - wall[0]) % 2 != 0:
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+1, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+2, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+1, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+2, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +2, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +2, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.entranceCo = (wall[0] + (wall[2] - wall[0]) // 2, wall[0] + (wall[2] - wall[0]) // 2 +2, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 -1)
else:
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+1, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+2, wall[1]+1), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1], wall[1]), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1]+3, wall[1]), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.entranceCo = (wall[0] + (wall[2] - wall[0]) // 2, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 -1)
case "E":
if (wall[3] - wall[1]) % 2 != 0:
self.editor.placeBlock((wall[0], self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2 +1), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2 +1), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 +2), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +2), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.entranceCo = ((wall[1] + wall[3]) // 2, (wall[1] + wall[3]) // 2 +2, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 -1)
else:
self.editor.placeBlock((wall[0], self.coordinates_min[1]+1, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0], self.coordinates_min[1]+2, (wall[1] + wall[3]) // 2), Block("air"))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1], (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 ), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 +1 ), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.editor.placeBlock((wall[0]+1, self.coordinates_min[1]+3, (wall[1] + wall[3]) // 2 -1), Block(self.blocks["stairs"], {"facing": "south", "half": "top"}))
self.entranceCo = ((wall[1] + wall[3]) // 2, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 +1, (wall[1] + wall[3]) // 2 -1)
case "S":
print(wall)
if (wall[2] - wall[0]) % 2 != 0:
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+1, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+2, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+1, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+2, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +2, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +2, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.entranceCo = (wall[0] + (wall[2] - wall[0]) // 2, wall[0] + (wall[2] - wall[0]) // 2 +2, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 -1)
else:
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+1, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+2, wall[1]), Block("air"))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "north"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "west"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1], wall[1]+1), Block(self.blocks["stairs"], {"facing": "east"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "north", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 +1, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "west", "half": "top"}))
self.editor.placeBlock((wall[0] + (wall[2] - wall[0]) // 2 -1, self.coordinates_min[1]+3, wall[1]+1), Block(self.blocks["stairs"], {"facing": "east", "half": "top"}))
self.entranceCo = (wall[0] + (wall[2] - wall[0]) // 2, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 +1, wall[0] + (wall[2] - wall[0]) // 2 -1)
case _:
pass
def placeGardenOutline(self):
x_min, y_min, z_min = self.coordinates_min
x_max, y_max, z_max = self.coordinates_max
for i in range (x_min, x_max):
for y in range(z_min, z_max):
if i == x_min or i == x_max - 1 or y == z_min or y == z_max - 1 :
match self.direction:
case "N":
if not (i in self.entranceCo and y == z_min):
self.editor.placeBlock((i, y_min-1, y), Block("oak_log"))
self.editor.placeBlock((i, y_min, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+1, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+2, y), self.gardenOutline)
case "S":
if not (i in self.entranceCo and y == z_max-1):
self.editor.placeBlock((i, y_min-1, y), Block("oak_log"))
self.editor.placeBlock((i, y_min, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+1, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+2, y), self.gardenOutline)
case "E":
if not (i == x_max-1 and y in self.entranceCo):
self.editor.placeBlock((i, y_min-1, y), Block("oak_log"))
self.editor.placeBlock((i, y_min, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+1, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+2, y), self.gardenOutline)
case "W":
if not (i == x_min and y in self.entranceCo):
self.editor.placeBlock((i, y_min-1, y), Block("oak_log"))
self.editor.placeBlock((i, y_min, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+1, y), self.gardenOutline)
self.editor.placeBlock((i, y_min+2, y), self.gardenOutline)
else:
print(i, y)
case _:
self.editor.placeBlock((i, y_min-1, y), self.garden_floor)
else:
self.editor.placeBlock((i, y_min-1, y), self.garden_floor)
def build(self):
house.createHouseSkeleton()
house.putWallOnSkeleton()
house.placeDoor()
house.placeRoof()
house.putCelling()
house.placeWindow()
house.placeEntrance()
house.placeGardenOutline()
if house.nbEtage > 1:
house.placeStairs()
if __name__ == "__main__":
editor = Editor(buffering=True)
buildArea = editor.getBuildArea()
coordinates_min = [min(buildArea.begin[i], buildArea.last[i]) for i in range(3)]
coordinates_max = [max(buildArea.begin[i], buildArea.last[i]) for i in range(3)]
blocks = {
"wall": "blackstone",
"roof": "blackstone",
"roof_slab": "blackstone_slab",
"door": "oak_door",
"window": "glass_pane",
"entrance": "oak_door",
"stairs": "quartz_stairs",
"stairs_slab": "quartz_slab",
"celling": "quartz_block",
"floor": "quartz_block",
"celling_slab": "quartz_slab",
"garden_outline": "oak_leaves",
"garden_floor": "grass_block"
}
for i in range(1):
house = House(editor, coordinates_min, coordinates_max,"W", blocks)
house.build()
new_coordinates_min =(coordinates_max[0] + 10, coordinates_min[1], coordinates_min[2])
new_coordinates_max = (coordinates_max[0] + 10 +24, coordinates_max[1], coordinates_max[2])
coordinates_min = new_coordinates_min
coordinates_max = new_coordinates_max
# delete(editor, coordinates_min, coordinates_max)
editor.flushBuffer()

View File

@@ -1,3 +1,10 @@
from world_maker.world_maker import *
def main():
rectangle_house_mountain, rectangle_building, skeleton_highway, skeleton_mountain = world_maker()
if __name__ == '__main__':
main()
from gdpc import Editor, Block, geometry, Transform from gdpc import Editor, Block, geometry, Transform
import networks.curve as curve import networks.curve as curve
import numpy as np import numpy as np

View File

@@ -1,7 +1,10 @@
from District import District from world_maker.District import District, Road
from Position import Position from world_maker.Position import Position
from PIL import Image from PIL import Image
import random from random import randint
from world_maker.data_analysis import handle_import_image, detect_mountain
from typing import Union
import numpy as np
class City: class City:
@@ -25,8 +28,8 @@ class City:
""" """
Initialize the maps of the city. It reads the heightmap and watermap images and converts them into 2D lists. Initialize the maps of the city. It reads the heightmap and watermap images and converts them into 2D lists.
""" """
heightmap = Image.open('./data/heightmap.png').convert('L') heightmap = Image.open('./world_maker/data/heightmap.png').convert('L')
watermap = Image.open('./data/watermap.png').convert('L') watermap = Image.open('./world_maker/data/watermap.png').convert('L')
width, height = heightmap.size width, height = heightmap.size
self.map_data = [[-1 if watermap.getpixel((x, y)) > 0 else 0 for x in range(width)] for y in range(height)] self.map_data = [[-1 if watermap.getpixel((x, y)) > 0 else 0 for x in range(width)] for y in range(height)]
self.height_map = [[heightmap.getpixel((x, y)) for x in range(width)] for y in range(height)] self.height_map = [[heightmap.getpixel((x, y)) for x in range(width)] for y in range(height)]
@@ -72,7 +75,6 @@ class City:
index_district_chosen = index index_district_chosen = index
else: else:
self.districts[index].area_expend.remove(point) self.districts[index].area_expend.remove(point)
self.districts[index_district_chosen].area.append(point)
self.districts[index_district_chosen].area_expend_from_point.append(point) self.districts[index_district_chosen].area_expend_from_point.append(point)
self.districts[index_district_chosen].area_expend.remove(point) self.districts[index_district_chosen].area_expend.remove(point)
self.map_data[point.y][point.x] = index_district_chosen + 1 self.map_data[point.y][point.x] = index_district_chosen + 1
@@ -81,7 +83,6 @@ class City:
""" """
Update the expansion points of all districts in the city. Update the expansion points of all districts in the city.
""" """
for district in self.districts: for district in self.districts:
if len(district.area_expend_from_point) > 0: if len(district.area_expend_from_point) > 0:
district.update_expend_points(district.area_expend_from_point[0], self.map_data, self.height_map) district.update_expend_points(district.area_expend_from_point[0], self.map_data, self.height_map)
@@ -104,7 +105,7 @@ class City:
""" """
width, height = len(self.map_data[0]), len(self.map_data) width, height = len(self.map_data[0]), len(self.map_data)
img = Image.new('RGB', (width, height)) img = Image.new('RGB', (width, height))
colors = {id_district: (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) colors = {id_district: (randint(0, 255), randint(0, 255), randint(0, 255))
for id_district in range(1, len(self.districts) + 1)} for id_district in range(1, len(self.districts) + 1)}
for y in range(height): for y in range(height):
@@ -114,13 +115,93 @@ class City:
else: else:
img.putpixel((x, y), colors[self.map_data[y][x]]) img.putpixel((x, y), colors[self.map_data[y][x]])
img.save('./data/district.png') img.save('./world_maker/data/district.png')
print("[City] District map created.") print("[City] District map created.")
def draw_roads(self, size_road: int = 1) -> Image:
"""
Draw the roads of the city on the image.
:param size:
"""
image = Image.new('RGB', Image.open('./world_maker/data/heightmap.png').size)
for district in self.districts:
district.draw_roads(image, size_road)
return image
def district_generate_road(self) -> list[Road]:
"""
Generate the roads of the city for each district.
:return: The list of roads of the city.
"""
roads = []
for district in self.districts:
if district.type != "mountain":
district.generate_roads(self.map_data)
roads.extend(district.roads)
return roads
def point_in_which_district(self, point: Union[Position, tuple[int, int]]) -> int:
"""
Get the index of the district in which the point is located.
:param point: The point to check.
:return: The index of the district in which the point is located.
"""
if isinstance(point, Position):
point = (point.x, point.y)
return self.map_data[point[1]][point[0]]
def get_district_mountain_map(self) -> Image:
"""
Get the map of a district.
:param district_id: The id of the district.
:return: The map of the district.
"""
district_id = [district.tile_id for district in self.districts if district.type == "mountain"]
array = np.array([[True if self.map_data[y][x] in district_id else False for x in range(len(self.map_data[0]))]
for y in range(len(self.map_data))])
image = Image.fromarray(array)
image.save('./world_maker/data/mountain_map.png')
return image
def generate_district(self):
image = handle_import_image('./world_maker/data/smooth_sobel_watermap.png').convert('L')
array = np.array(image)
mountain_coo = detect_mountain()
self.add_district(Position(mountain_coo[0], mountain_coo[1]), "mountain")
print("[City] District added.")
remove_circle_data(array, mountain_coo)
area = get_area_array(array)
sizeX, sizeY = len(array[0]), len(array)
while area > sizeX * sizeY * 0.1:
x, y = randint(0, sizeX - 1), randint(0, sizeY - 1)
if array[y][x]:
self.add_district(Position(x, y))
remove_circle_data(array, (x, y))
area = get_area_array(array)
print("[City] District added.")
def remove_circle_data(array, center, radius=100):
y_indices, x_indices = np.indices(array.shape)
dist_sq = (y_indices - center[1]) ** 2 + (x_indices - center[0]) ** 2
mask = dist_sq <= radius ** 2
array[mask] = False
def get_area_array(array) -> int:
return np.sum(array)
if __name__ == '__main__': if __name__ == '__main__':
city = City() city = City()
for i in range(10): for i in range(10):
city.add_district(Position(random.randint(0, 800), random.randint(0, 800))) city.add_district(Position(randint(0, 400), randint(0, 400)))
city.loop_expend_district() city.loop_expend_district()
city.district_draw_map() city.district_draw_map()
city.district_generate_road()
image = city.draw_roads(Image.new('RGB', (401, 401)), 4)
image.save('./world_maker/data/roadmap.png')

View File

@@ -1,8 +1,24 @@
from Position import Position from world_maker.Position import Position
from typing import Union
from random import randint
from PIL import Image
class Road:
def __init__(self, position: Position, id_height: int, id_width: int, border: bool = False):
self.position: Position = position
self.north: Union[Road, None] = None
self.south: Union[Road, None] = None
self.east: Union[Road, None] = None
self.west: Union[Road, None] = None
self.id_height = id_height
self.id_width = id_width
self.border = border
class District: class District:
""" """
The CustomDistrict class represents a district that can be expanded. The District class represents a district that can be expanded.
Attributes: Attributes:
center_expend (Position): The center position from which the district expands. center_expend (Position): The center position from which the district expands.
@@ -10,6 +26,7 @@ class District:
area_expend_from_point (list): The list of positions from which the district can expand. area_expend_from_point (list): The list of positions from which the district can expand.
area_expend (list): The list of positions to which the district will maybe expand. area_expend (list): The list of positions to which the district will maybe expand.
""" """
def __init__(self, tile_id: int, center: Position, district_type: str = ""): def __init__(self, tile_id: int, center: Position, district_type: str = ""):
""" """
The constructor for the District class. The constructor for the District class.
@@ -23,11 +40,13 @@ class District:
self.tile_id = tile_id self.tile_id = tile_id
self.type = district_type self.type = district_type
self.center_expend = center self.center_expend = center
self.area = [center]
self.area_expend_from_point = [center] self.area_expend_from_point = [center]
self.area_expend = [] self.area_expend = []
self.roads: list[Road] = []
self.roads_expend = []
def verify_point(self, point: Position, point_new: Position, map_data: list[list[int]], height_map: list[list[int]]): def verify_point(self, point: Position, point_new: Position, map_data: list[list[int]],
height_map: list[list[int]]):
""" """
Verify if a new point can be added to a district extend area list. Verify if a new point can be added to a district extend area list.
@@ -40,9 +59,32 @@ class District:
return (0 <= point_new.x < len(map_data[0]) and return (0 <= point_new.x < len(map_data[0]) and
0 <= point_new.y < len(map_data) and 0 <= point_new.y < len(map_data) and
map_data[point_new.y][point_new.x] == 0 and map_data[point_new.y][point_new.x] == 0 and
(self.type == "Mountain" or (self.type == "mountain" or
abs(height_map[point_new.y][point_new.x] - height_map[point.y][point.x]) < 2)) abs(height_map[point_new.y][point_new.x] - height_map[point.y][point.x]) < 2))
def is_point_inside(self, point: Position, map_data) -> bool:
"""
Check if a point is inside the district.
:param point: The point to be checked.
:return: True if the point is inside the district, False otherwise.
"""
if not (0 <= point.x < len(map_data[0]) and 0 <= point.y < len(map_data)):
return False
return map_data[point.y][point.x] == self.tile_id
def is_position_in_area_expend(self, position: Position) -> bool:
"""
Check if a position is inside the district.
:param position: The position to be checked.
:return: True if the position is inside the district, False otherwise.
"""
for point in self.area_expend:
if point == position:
return True
return False
def update_expend_points(self, point: Position, map_data: list[list[int]], height_map: list[list[int]]): def update_expend_points(self, point: Position, map_data: list[list[int]], height_map: list[list[int]]):
""" """
Update the points to which the district can expand. Update the points to which the district can expand.
@@ -53,6 +95,142 @@ class District:
""" """
for pos in [Position(1, 0), Position(-1, 0), Position(0, 1), Position(0, -1)]: for pos in [Position(1, 0), Position(-1, 0), Position(0, 1), Position(0, -1)]:
if self.verify_point(point, point + pos, map_data, height_map): if self.verify_point(point, point + pos, map_data, height_map):
if point + pos not in self.area_expend: if not self.is_position_in_area_expend(point + pos):
self.area_expend.append(point + pos) self.area_expend.append(point + pos)
self.area_expend_from_point.remove(point) self.area_expend_from_point.remove(point)
def move_point_to_area(self, point: Position, vector: Position, map_data) -> Position:
while not self.is_point_inside(point + vector, map_data):
point += vector
return point + vector
def get_road_from_point(self, point: Position) -> Union[Road, None]:
"""
Get the road that contains a specific point.
:param point: The point to be checked.
:return: The road that contains the point.
"""
for road in self.roads:
if point == road.position:
return road
return None
def get_road_expend_from_point(self, point: Position) -> Union[Road, None]:
"""
Get the road that contains a specific point.
:param point: The point to be checked.
:return: The road that contains the point.
"""
for road in self.roads_expend:
if point == road.position:
return road
return None
def generate_roads(self, map_data, random_range=(20, 40)):
width = {0: self.center_expend.x}
height = {0: self.center_expend.y}
self.roads_expend = [Road(self.center_expend, 0, 0)]
self.roads = [self.roads_expend[0]]
while len(self.roads_expend) > 0:
road = self.roads_expend.pop(0)
print(road.position)
for id_width in [-1, 1]:
if road.id_width + id_width not in width:
width[road.id_width + id_width] = width[road.id_width] + randint(random_range[0],
random_range[1]) * id_width
road_new = Road(Position(width[road.id_width + id_width], road.position.y),
road.id_height, road.id_width + id_width)
if self.is_point_inside(road_new.position, map_data):
road_search = self.get_road_from_point(road_new.position)
road_expend_search = self.get_road_expend_from_point(road_new.position)
if road_search is not None:
road_new = road_search
if id_width == -1:
road.west = road_new
road_new.east = road
else:
road.east = road_new
road_new.west = road
if road_search is None:
self.roads.append(road_new)
self.roads_expend.append(road_new)
else:
self.roads[self.roads.index(road_search)] = road_new
if road_expend_search is not None:
self.roads_expend[self.roads_expend.index(road_expend_search)] = road_new
else:
point_new = self.move_point_to_area(road_new.position, Position(-id_width, 0), map_data)
road_new = Road(point_new, road.id_height, road.id_width + id_width, True)
if id_width == -1:
road.west = road_new
road_new.east = road
else:
road.east = road_new
road_new.west = road
self.roads.append(road_new)
for id_height in [-1, 1]:
if road.id_height + id_height not in height:
height[road.id_height + id_height] = height[road.id_height] + randint(random_range[0],
random_range[1]) * id_height
road_new = Road(Position(road.position.x, height[road.id_height + id_height]),
road.id_height + id_height, road.id_width)
if self.is_point_inside(road_new.position, map_data):
road_search = self.get_road_from_point(road_new.position)
road_expend_search = self.get_road_expend_from_point(road_new.position)
if road_search is not None:
road_new = road_search
if id_height == -1:
road.north = road_new
road_new.south = road
else:
road.south = road_new
road_new.north = road
if road_search is None:
self.roads.append(road_new)
self.roads_expend.append(road_new)
else:
self.roads[self.roads.index(road_search)] = road_new
if road_expend_search is not None:
self.roads_expend[self.roads_expend.index(road_expend_search)] = road_new
else:
pass
point_new = self.move_point_to_area(road_new.position, Position(0, -id_height), map_data)
road_new = Road(point_new, road.id_height + id_height, road.id_width, True)
if id_height == -1:
road.north = road_new
road_new.south = road
else:
road.south = road_new
road_new.north = road
self.roads.append(road_new)
def draw_roads(self, image: Image, size: int = 1):
for road in self.roads:
image.putpixel((road.position.x, road.position.y), (255, 255, 255))
if road.north is not None:
for y in range(road.position.y, road.north.position.y):
image = draw_square(image, Position(road.position.x, y), size)
if road.south is not None:
for y in range(road.position.y, road.south.position.y):
image = draw_square(image, Position(road.position.x, y), size)
if road.east is not None:
for x in range(road.position.x, road.east.position.x):
image = draw_square(image, Position(x, road.position.y), size)
if road.west is not None:
for x in range(road.position.x, road.west.position.x):
image = draw_square(image, Position(x, road.position.y), size)
def draw_square(image, center: Position, size: int) -> Image:
for x in range(center.x - size, center.x + size):
for y in range(center.y - size, center.y + size):
if 0 <= x < image.width and 0 <= y < image.height:
image.putpixel((x, y), (255, 255, 255))
return image

View File

@@ -3,7 +3,7 @@ import numpy as np
from skimage.morphology import skeletonize from skimage.morphology import skeletonize
from skan.csr import skeleton_to_csgraph from skan.csr import skeleton_to_csgraph
from collections import Counter from collections import Counter
from PIL import Image from PIL import Image, ImageDraw
import random import random
@@ -158,7 +158,7 @@ class Skeleton:
# xzDistance = (max(buildRect.end[0], buildRect.begin[0]) - min(buildRect.end[0], buildRect.begin[0]), # xzDistance = (max(buildRect.end[0], buildRect.begin[0]) - min(buildRect.end[0], buildRect.begin[0]),
# max(buildRect.end[1], buildRect.begin[1]) - min(buildRect.end[1], buildRect.begin[1])) # max(buildRect.end[1], buildRect.begin[1]) - min(buildRect.end[1], buildRect.begin[1]))
heightmap = Image.open("data/heightmap.png").convert('RGB') heightmap = Image.open("./world_maker/data/heightmap.png").convert('RGB')
# roadsArea = Image.new("L", xzDistance, 0) # roadsArea = Image.new("L", xzDistance, 0)
# width, height = heightmap.size # width, height = heightmap.size
@@ -213,3 +213,30 @@ class Skeleton:
# ) # )
print("[Skeleton] Mapping completed.") print("[Skeleton] Mapping completed.")
return heightmap # , roadsArea return heightmap # , roadsArea
def road_area(self, name: str, radius: int = 10) -> Image:
print("[Skeleton] Start mapping the road area...")
heightmap = Image.open("./world_maker/data/heightmap.png")
width, height = heightmap.size
road_area_map = Image.new("L", (width, height), 0)
road_area_map_draw = ImageDraw.Draw(road_area_map)
# Lines
for i in range(len(self.lines)):
for j in range(len(self.lines[i])):
z = self.coordinates[self.lines[i][j]][0]
x = self.coordinates[self.lines[i][j]][2]
circle_coords = (z - radius, x - radius, z + radius, x + radius)
road_area_map_draw.ellipse(circle_coords, fill=255)
# Centers
for i in range(len(self.centers)):
z = self.coordinates[self.centers[i]][0]
x = self.coordinates[self.centers[i]][2]
circle_coords = (z - radius, x - radius, z + radius, x + radius)
road_area_map_draw.ellipse(circle_coords, fill=255)
road_area_map.save("./world_maker/data/"+name)
print("[Skeleton] Road area mapping completed.")
return road_area_map

View File

@@ -1,7 +1,7 @@
from gdpc import Editor, geometry, lookup from gdpc import Editor, geometry, lookup
import numpy as np import numpy as np
from PIL import Image from PIL import Image
from Block import Block from world_maker.Block import Block
waterBiomes = [ waterBiomes = [
"minecraft:ocean", "minecraft:ocean",

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,17 +1,19 @@
import World from world_maker.World import World
from PIL import Image, ImageFilter from PIL import Image, ImageFilter
import numpy as np import numpy as np
from scipy import ndimage from scipy import ndimage
from Skeleton import Skeleton from world_maker.Skeleton import Skeleton
from typing import Union from typing import Union
from random import randint
import cv2
def get_data(world: World): def get_data(world: World):
print("[Data Analysis] Generating data...") print("[Data Analysis] Generating data...")
heightmap, watermap, treemap = world.getData() heightmap, watermap, treemap = world.getData()
heightmap.save('./data/heightmap.png') heightmap.save('./world_maker/data/heightmap.png')
watermap.save('./data/watermap.png') watermap.save('./world_maker/data/watermap.png')
treemap.save('./data/treemap.png') treemap.save('./world_maker/data/treemap.png')
print("[Data Analysis] Data generated.") print("[Data Analysis] Data generated.")
return heightmap, watermap, treemap return heightmap, watermap, treemap
@@ -22,13 +24,14 @@ def handle_import_image(image: Union[str, Image]) -> Image:
return image return image
def filter_negative(image: Image) -> Image: def filter_negative(image: Union[str, Image]) -> Image:
""" """
Invert the colors of an image. Invert the colors of an image.
Args: Args:
image (image): image to filter image (image): image to filter
""" """
image = handle_import_image(image)
return Image.fromarray(np.invert(np.array(image))) return Image.fromarray(np.invert(np.array(image)))
@@ -146,8 +149,8 @@ def subtract_map(image: Union[str, Image], substractImage: Union[str, Image]) ->
def group_map(image1: Union[str, Image], image2: Union[str, Image]) -> Image: def group_map(image1: Union[str, Image], image2: Union[str, Image]) -> Image:
image1 = handle_import_image(image1) image1 = handle_import_image(image1).convert('L')
image2 = handle_import_image(image2) image2 = handle_import_image(image2).convert('L')
array1 = np.array(image1) array1 = np.array(image1)
array2 = np.array(image2) array2 = np.array(image2)
@@ -179,9 +182,9 @@ def filter_remove_details(image: Union[str, Image], n: int = 20) -> Image:
def highway_map() -> Image: def highway_map() -> Image:
print("[Data Analysis] Generating highway map...") print("[Data Analysis] Generating highway map...")
smooth_sobel = filter_smooth("./data/sobelmap.png", 1) smooth_sobel = filter_smooth("./world_maker/data/sobelmap.png", 1)
negative_smooth_sobel = filter_negative(smooth_sobel) negative_smooth_sobel = filter_negative(smooth_sobel)
negative_smooth_sobel_water = subtract_map(negative_smooth_sobel, './data/watermap.png') negative_smooth_sobel_water = subtract_map(negative_smooth_sobel, './world_maker/data/watermap.png')
array_sobel_water = np.array(negative_smooth_sobel_water) array_sobel_water = np.array(negative_smooth_sobel_water)
array_sobel_water = ndimage.binary_erosion(array_sobel_water, iterations=12) array_sobel_water = ndimage.binary_erosion(array_sobel_water, iterations=12)
array_sobel_water = ndimage.binary_dilation(array_sobel_water, iterations=5) array_sobel_water = ndimage.binary_dilation(array_sobel_water, iterations=5)
@@ -190,7 +193,7 @@ def highway_map() -> Image:
array_sobel_water = filter_smooth_array(array_sobel_water, 6) array_sobel_water = filter_smooth_array(array_sobel_water, 6)
image = Image.fromarray(array_sobel_water) image = Image.fromarray(array_sobel_water)
image_no_details = filter_remove_details(image, 15) image_no_details = filter_remove_details(image, 15)
image_no_details.save('./data/highwaymap.png') image_no_details.save('./world_maker/data/highwaymap.png')
print("[Data Analysis] Highway map generated.") print("[Data Analysis] Highway map generated.")
return image_no_details return image_no_details
@@ -208,16 +211,82 @@ def create_volume(surface: np.ndarray, heightmap: np.ndarray, make_it_flat: bool
def convert_2D_to_3D(image: Union[str, Image], make_it_flat: bool = False) -> np.ndarray: def convert_2D_to_3D(image: Union[str, Image], make_it_flat: bool = False) -> np.ndarray:
image = handle_import_image(image) image = handle_import_image(image)
heightmap = Image.open('./data/heightmap.png').convert('L') heightmap = Image.open('./world_maker/data/heightmap.png').convert('L')
heightmap = np.array(heightmap) heightmap = np.array(heightmap)
surface = np.array(image) surface = np.array(image)
volume = create_volume(surface, heightmap, make_it_flat) volume = create_volume(surface, heightmap, make_it_flat)
return volume return volume
def skeleton_highway_map(image: Union[str, Image] = './data/highwaymap.png'): def skeleton_highway_map(image: Union[str, Image] = './world_maker/data/highwaymap.png') -> Skeleton:
image_array = convert_2D_to_3D(image, True) image_array = convert_2D_to_3D(image, True)
skeleton = Skeleton(image_array) skeleton = Skeleton(image_array)
skeleton.parse_graph(True) skeleton.parse_graph(True)
heightmap_skeleton = skeleton.map() heightmap_skeleton = skeleton.map()
heightmap_skeleton.save('./data/skeleton_highway.png') heightmap_skeleton.save('./world_maker/data/skeleton_highway.png')
skeleton.road_area('skeleton_highway_area.png', 10)
return skeleton
def skeleton_mountain_map(image: Union[str, Image] = './world_maker/data/mountain_map.png') -> Skeleton:
image_array = convert_2D_to_3D(image, True)
skeleton = Skeleton(image_array)
skeleton.parse_graph()
heightmap_skeleton = skeleton.map()
heightmap_skeleton.save('./world_maker/data/skeleton_mountain.png')
skeleton.road_area('skeleton_mountain_area.png', 3)
return skeleton
def smooth_sobel_water() -> Image:
watermap = handle_import_image("./world_maker/data/watermap.png")
watermap = filter_negative(filter_remove_details(filter_negative(watermap), 5))
sobel = handle_import_image("./world_maker/data/sobelmap.png")
sobel = filter_remove_details(filter_smooth(sobel, 1), 2)
group = group_map(watermap, sobel)
group = filter_negative(group)
group.save('./world_maker/data/smooth_sobel_watermap.png')
return group
def detect_mountain(image: Union[str, Image] = './world_maker/data/sobelmap.png') -> Image:
image = handle_import_image(image)
sobel = np.array(image)
pixels = sobel.reshape((-1, 1))
pixels = np.float32(pixels)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
k = 3
_, labels, centers = cv2.kmeans(pixels, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
segmented_image = centers[labels.flatten()]
segmented_image = segmented_image.reshape(sobel.shape)
mountain = segmented_image == segmented_image.max()
contours, _ = cv2.findContours(mountain.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
max_contour = max(contours, key=cv2.contourArea)
M = cv2.moments(max_contour)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
print(f"[Data Analysis] The center of the mountain is at ({cX}, {cY})")
return (cX, cY)
def rectangle_2D_to_3D(rectangle: list[tuple[tuple[int, int], tuple[int, int]]],
height_min: int = 6, height_max: int = 10) \
-> list[tuple[tuple[int, int, int], tuple[int, int, int]]]:
image = handle_import_image('./world_maker/data/heightmap.png').convert('L')
new_rectangle = []
for rect in rectangle:
start, end = rect
avg_height = 0
for x in range(start[0], end[0]):
for y in range(start[1], end[1]):
avg_height += image.getpixel((x, y))
avg_height = int(avg_height / ((end[0] - start[0]) * (end[1] - start[1])))
new_rectangle.append(
((start[0], avg_height, start[1]), (end[0], avg_height + randint(height_min, height_max), end[1])))
return new_rectangle

View File

@@ -0,0 +1,112 @@
from PIL import Image
import numpy as np
from typing import Union
from world_maker.data_analysis import handle_import_image
from random import randint
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
class Bin:
def __init__(self, grid):
self.grid = grid
self.rectangles = []
def place_rectangle(self, rectangle):
best_spot = None
best_spot_empty_area = float('inf')
for i in range(len(self.grid[0]) - rectangle.width + 1):
for j in range(len(self.grid) - rectangle.height + 1):
if self.can_place(rectangle, i, j):
empty_area = self.calculate_empty_area(rectangle, i, j)
if empty_area < best_spot_empty_area:
best_spot = (i, j)
best_spot_empty_area = empty_area
if best_spot is not None:
self.rectangles.append((best_spot, (best_spot[0] + rectangle.width, best_spot[1] + rectangle.height)))
self.update_grid(rectangle, *best_spot)
return True
return False
def calculate_empty_area(self, rectangle, x, y):
empty_area = 0
for rect_x in range(x, x + rectangle.width):
for rect_y in range(y, y + rectangle.height):
if self.grid[rect_y][rect_x]:
empty_area += 1
return empty_area
def can_place(self, rectangle, x, y):
for rect_x in range(x, x + rectangle.width):
for rect_y in range(y, y + rectangle.height):
if not self.grid[rect_y][rect_x]:
return False
return True
def update_grid(self, rectangle, x, y):
for rect_x in range(x, x + rectangle.width):
for rect_y in range(y, y + rectangle.height):
self.grid[rect_y][rect_x] = False
def pack_rectangles(rectangles, grid):
rectangles = sorted(rectangles, key=lambda r: r.width * r.height, reverse=True)
bins = [Bin(grid)]
for rectangle in rectangles:
for bin in bins:
if bin.place_rectangle(rectangle):
break
else:
new_bin = Bin(grid)
if new_bin.place_rectangle(rectangle):
bins.append(new_bin)
else:
return False
return True
def generate_rectangle(min_width: int = 10, max_width: int = 25):
width = randint(min_width, max_width)
height = randint(min_width, max_width)
return Rectangle(width, height)
def pack_rectangles(grid, min_width: int = 10, max_width: int = 25):
bin = Bin(grid)
while True:
rectangle = generate_rectangle(min_width, max_width)
if not bin.place_rectangle(rectangle):
break
print(len(bin.rectangles))
return bin.rectangles
def draw_rectangles(rectangles, grid):
image = Image.new('RGB', (len(grid[0]), len(grid)), (0, 0, 0))
for rectangle in rectangles:
start, end = rectangle
for x in range(start[0], end[0]):
for y in range(start[1], end[1]):
image.putpixel((x, y), (144, 255, 144))
return image
def generate_building(image: Union[str, Image], min_width: int = 10, max_width: int = 25):
image = handle_import_image(image).convert('L')
grid = np.array(image)
rectangles = pack_rectangles(grid, min_width, max_width)
draw_rectangles(rectangles, grid).save('./world_maker/data/building.png')
return rectangles
if __name__ == '__main__':
generate_building()

View File

@@ -1,9 +1,34 @@
import World from world_maker.World import World
from PIL import Image from PIL import Image
from data_analysis import get_data, highway_map, filter_sobel, skeleton_highway_map from world_maker.data_analysis import (get_data,filter_negative, rectangle_2D_to_3D, skeleton_mountain_map, highway_map, filter_sobel, skeleton_highway_map, \
smooth_sobel_water, subtract_map, detect_mountain)
from world_maker.City import City
from world_maker.Position import Position
from random import randint
from world_maker.pack_rectangle import generate_building
if __name__ == '__main__': def world_maker():
world = World.World() world = World()
heightmap, watermap, treemap = get_data(world) heightmap, watermap, treemap = get_data(world)
filter_sobel("./data/heightmap.png").save('./data/sobelmap.png') filter_sobel("./world_maker/data/heightmap.png").save('./world_maker/data/sobelmap.png')
skeleton_highway_map(highway_map()) smooth_sobel_water_map = smooth_sobel_water()
skeleton_highway = skeleton_highway_map(highway_map())
city = City()
city.generate_district()
city.loop_expend_district()
city.district_draw_map()
city.district_generate_road()
image_mountain_map = city.get_district_mountain_map()
road = city.draw_roads(4)
road.save('./world_maker/data/roadmap.png')
subtract_map(smooth_sobel_water_map, road).save('./world_maker/data/city_map.png')
subtract_map('./world_maker/data/city_map.png', './world_maker/data/skeleton_highway_area.png').save('./world_maker/data/city_map.png')
subtract_map('./world_maker/data/city_map.png', './world_maker/data/mountain_map.png').save('./world_maker/data/city_map.png')
rectangle_building = generate_building('./world_maker/data/city_map.png')
rectangle_building = rectangle_2D_to_3D(rectangle_building)
skeleton_mountain = skeleton_mountain_map(image_mountain_map)
subtract_map('./world_maker/data/mountain_map.png', './world_maker/data/skeleton_mountain_area.png').save('./world_maker/data/mountain_map.png')
subtract_map(smooth_sobel_water_map, filter_negative('./world_maker/data/mountain_map.png')).save('./world_maker/data/mountain_map.png')
rectangle_mountain = generate_building('./world_maker/data/mountain_map.png')
return rectangle_building, rectangle_mountain, skeleton_highway, skeleton_mountain