diff --git a/buildings/Facade.py b/buildings/Facade.py index e542bb1..ea53ae7 100644 --- a/buildings/Facade.py +++ b/buildings/Facade.py @@ -1,6 +1,6 @@ import random as rd from utils.Enums import COLLUMN_STYLE -from gdpc import Editor, Transform +from gdpc import Editor, Block, geometry, Transform from buildings.geometry.Vertice import Vertice from buildings.elements.Window import Window @@ -15,11 +15,16 @@ class Facade: self.window = self.get_window() self.has_balcony = self.has_balcony() self.has_inter_floor = self.has_inter_floor() + self.editor, self.materials = None,None - def build(self, editor : Editor, materials : list[str]): + def build(self, editor : Editor, materials : list[str]): + self.editor = editor + self.materials = materials + for vertice in self.vertices: vertice.fill(editor, materials[0], self.height, xpadding = self.padding, zpadding = self.padding) with editor.pushTransform(Transform(vertice.point1.position,rotation = vertice.facing.value)): + self.build_inter_floor(vertice) self.window.build(editor, vertice.get_len(), self.height, materials) def get_window(self) -> Window: @@ -31,9 +36,13 @@ class Facade: return Window(self.rdata["windows"] ,max_width, max_height) + def build_inter_floor(self, vertice : Vertice): + if self.has_inter_floor: + geometry.placeCuboid(self.editor,(0,self.height,-1),(self.length,self.height,-1),Block(self.materials[4], {"facing": "south", "half": "top"})) + def has_balcony(self) -> bool: - pass + return self.rdata["balcony"] >= rd.random() def has_inter_floor(self) -> bool: - pass + return self.rdata["inter_floor"] >= rd.random() \ No newline at end of file diff --git a/buildings/elements/Balcony.py b/buildings/elements/Balcony.py new file mode 100644 index 0000000..55691ab --- /dev/null +++ b/buildings/elements/Balcony.py @@ -0,0 +1,4 @@ +class Balcony: + def __init__(self, length, width): + self.length = length + self.width = width \ No newline at end of file diff --git a/buildings/elements/Window.py b/buildings/elements/Window.py index 395cc5c..4d211da 100644 --- a/buildings/elements/Window.py +++ b/buildings/elements/Window.py @@ -1,7 +1,8 @@ import random as rd import math from gdpc import Editor, Block, geometry, Transform -from utils.Enums import COLLUMN_STYLE +from utils.Enums import COLLUMN_STYLE, BORDER_RADIUS +from utils.functions import * from buildings.geometry.Point import Point from buildings.geometry.Vertice import Vertice @@ -13,6 +14,7 @@ class Window: self.has_multiple_windows = self.has_multiple_windows() self.is_alternate = self.is_alternate() self.has_vertical_crossbar, self.has_horizontal_crossbar = self.has_crossbars() + self.border_radius = self.border_radius() self.padding = 0 self.editor, self.materials = None,None @@ -24,12 +26,12 @@ class Window: self.padding = (facade_len - self.width)//2 self.width = facade_len - self.padding*2 - self.is_alternate = True if not self.is_grounded: editor.transform @= Transform((0,(facade_height-self.height)//2,0)) + editor.transform @= Transform((self.padding,0,0)) if self.has_multiple_windows: self.build_multiple_windows() else : - self.place_glasses(self.padding, self.width+self.padding) + self.place_glasses(0, self.width) def build_multiple_windows(self): slices = rd.randint(3, self.width//self.rdata["size"]["min_width"]) @@ -48,9 +50,8 @@ class Window: if i == mid: wsize, isize = wsize + remainder, isize + remainder # kepp a spacing between windows, "is revert" is used to keep symetry - if is_window: - x= self.padding + gap - self.place_glasses(x, x+wsize) + if is_window: + self.place_glasses(gap, gap+wsize) gap += wsize else : gap += isize @@ -70,9 +71,10 @@ class Window: is_block = not is_block else: - geometry.placeCuboid(self.editor,(x1,0,0),(x2,self.height,0),Block(self.materials[1])) + geometry.placeCuboid(self.editor,(x1,0,0),(x2-1,self.height,0),Block(self.materials[1])) self.build_crossbars(x1, x2-1, len) + if len > 1: self.build_border_radius(x1, x2-1) def get_size(self, max_width : int ,max_height : int) -> tuple[int,int]: return ( @@ -83,29 +85,38 @@ class Window: def build_crossbars(self, x1 : int, x2 : int, len : int): if self.has_vertical_crossbar and self.height >= self.rdata["crossbars"]["min_height_for_vertical_crossbar"]: y = self.height//2 - geometry.placeCuboid(self.editor,(x1,y,0),(x2,self.height-y,0),Block(self.materials[3])) + geometry.placeCuboid(self.editor,(x1,y,0),(x2,y,0),Block(self.materials[3])) if self.has_horizontal_crossbar and len >= self.rdata["crossbars"]["min_width_for_horizontal_crossbar"]: - pass + x = len//2 + geometry.placeCuboid(self.editor,(x1+x,0,0),(x2-x,self.height,0),Block(self.materials[3], {"up" : "true"})) + + def build_border_radius(self, x1 : int, x2 : int): + if self.border_radius != BORDER_RADIUS.NONE: + self.editor.placeBlock((x1,self.height,0),Block(self.materials[4], {"facing": "west", "half": "top"})) + self.editor.placeBlock((x2,self.height,0),Block(self.materials[4], {"facing": "east", "half": "top"})) + if self.border_radius == BORDER_RADIUS.TOP_AND_BOTTOM: + self.editor.placeBlock((x1,0,0),Block(self.materials[4], {"facing": "west"})) + self.editor.placeBlock((x2,0,0),Block(self.materials[4], {"facing": "east"})) def is_grounded(self): # if the window is grounded or if there is a padding between the window and the ground - if self.rdata["grounded"] >= rd.random(): return True - return False + return self.rdata["grounded"] >= rd.random() def has_multiple_windows(self): if self.width > self.rdata["size"]["max_width"]: return True - if self.width >= self.rdata["multiple"]["min_width"]: - return True - if self.rdata["multiple"]["proba"] >= rd.random(): return True - return False + elif self.width >= self.rdata["multiple"]["min_width"]: + return self.rdata["multiple"]["proba"] >= rd.random() + else : return False def is_alternate(self): # if the window alternate between glass_blocks and glass_panes - if self.rdata["alternate"] >= rd.random(): return True - return False + return self.rdata["alternate"] >= rd.random() def has_crossbars(self): # if the window has crossbars data = self.rdata["crossbars"] - return (data["vertical_crossbar"] >= rd.random(), data["horizontal_crossbar"] >= rd.random()) \ No newline at end of file + return (data["vertical_crossbar"] >= rd.random(), data["horizontal_crossbar"] >= rd.random()) + + def border_radius(self): + return select_random(self.rdata["border_radius"], BORDER_RADIUS) \ No newline at end of file diff --git a/main.py b/main.py index c6dd711..9dd676e 100644 --- a/main.py +++ b/main.py @@ -7,9 +7,11 @@ from buildings.Building import Building from buildings.geometry.Vertice import Vertice from buildings.geometry.Point import Point -from utils.Enums import DIRECTION,COLLUMN_STYLE +from utils.Enums import DIRECTION,COLLUMN_STYLE,BORDER_RADIUS from buildings.Facade import Facade +from utils.functions import * + editor = Editor(buffering=True) f = JsonReader('buildings\shapes.json') @@ -18,20 +20,21 @@ shapes = f.data y = YamlReader('params.yml') random_data = y.data -transform = Transform((0,-60,0),rotation = 0) + +transform = Transform((0,-60,-5),rotation = 0) editor.transform.push(transform) -geometry.placeCuboid(editor, (0,-60,-5), (100,-45,-5), Block("air")) +geometry.placeCuboid(editor, (0,0,-1), (100,15,1), Block("air")) x = 0 facade = [] for i in range(3,13): - facade.append(Facade(random_data["buildings"]["facade"],[Vertice(Point(x,0,-5), Point(x+i,0,-5), DIRECTION.NORTH)],i,i,COLLUMN_STYLE.NONE)) + facade.append(Facade(random_data["buildings"]["facade"],[Vertice(Point(x,0,0), Point(x+i,0,0), DIRECTION.NORTH)],i,i,COLLUMN_STYLE.NONE)) x += i+2 for f in facade: - f.build(editor, ["stone_bricks","glass_pane","glass","cobblestone_wall"]) + f.build(editor, ["stone_bricks","glass_pane","glass","cobblestone_wall","stone_brick_stairs"]) # F = Foundations((0,0), (20,20), shapes[0]['matrice']) diff --git a/params.yml b/params.yml index c35e466..7cd9afc 100644 --- a/params.yml +++ b/params.yml @@ -7,10 +7,10 @@ buildings: foudations: collumn_style : # proportion of each style - - none: 1 - - inner: 1 - - outer: 1 - - both: 1 + none: 1 + inner: 1 + outer: 1 + both: 1 floor: min_height: 4 max_height: 7 @@ -34,5 +34,10 @@ buildings: # min size and probability of multiple windows on the same vertice min_width: 5 proba: 0.5 + border_radius: + # proportion of each style + none: 2 + top: 1 + top_and_bottom: 1 inter_floor: 0.5 balcony: 0.25 \ No newline at end of file diff --git a/utils/Enums.py b/utils/Enums.py index 66c55b9..4da1c62 100644 --- a/utils/Enums.py +++ b/utils/Enums.py @@ -10,4 +10,9 @@ class COLLUMN_STYLE(Enum): NONE = 0 INNER = 1 OUTER = 2 - BOTH = 3 \ No newline at end of file + BOTH = 3 + +class BORDER_RADIUS(Enum): + NONE = 0 + TOP = 1 + TOP_AND_BOTTOM = 2 \ No newline at end of file diff --git a/utils/functions.py b/utils/functions.py new file mode 100644 index 0000000..aec47f8 --- /dev/null +++ b/utils/functions.py @@ -0,0 +1,6 @@ +from enum import Enum +import random as rd + +def select_random(rdata : dict, enum : Enum) -> Enum: + # select a random value of the dict according to his coef and return the corresponding value in the enum + return enum[rd.choice([elt for elt,num in rdata.items() for _ in range(num)]).upper()] \ No newline at end of file