8 Commits

Author SHA1 Message Date
WhyteTiger
3b382f8650 refactoring : createHouseSkeleton, remove another double for loop 2024-09-28 13:24:58 +02:00
WhyteTiger
e9449901a7 refactor : createHouseSkeleton 2024-09-28 13:07:24 +02:00
WhyteTiger
86166905c8 refactoring : createHouseSkeleton, remove double for loop for floor 2024-09-28 12:08:40 +02:00
WhyteTiger
22c2c1bae9 refactoring : createHouseSkeleton, x_max z_max 2024-09-28 11:16:50 +02:00
WhyteTiger
3a48815279 refactoring : terraforming.py 2024-09-28 11:01:20 +02:00
12cdacba4e Optimize remove_trees 2024-09-27 23:37:24 +02:00
68241ae415 Fix heightmap generation with trees 2024-09-27 23:02:24 +02:00
Melvyn
f747dd5b46 refactor : suppression d'une double boucle for dans l'algo de remove_trees 2024-09-27 19:47:01 +02:00
28 changed files with 141 additions and 141 deletions

View File

@@ -4,6 +4,8 @@ import numpy as np
import math import math
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from pyxtension.streams import stream
class House: class House:
def __init__(self, editor, coordinates_min, coordinates_max, direction, list_block): def __init__(self, editor, coordinates_min, coordinates_max, direction, list_block):
@@ -49,37 +51,38 @@ class House:
x_min += 1 x_min += 1
z_min += 1 z_min += 1
x_max -= 1 x_max -= 2
z_max -= 1 z_max -= 2
if x_min + 1 > x_max - 1: if x_min + 1 > x_max :
x = np.random.randint(x_max - 1, x_min + 1) x = np.random.randint(x_max, x_min + 1)
else: else:
x = np.random.randint(x_min + 1, x_max - 1) x = np.random.randint(x_min + 1, x_max)
if z_min + 1 > z_max - 1: if z_min + 1 > z_max:
z = np.random.randint(z_max - 1, z_min + 1) z = np.random.randint(z_max, z_min + 1)
else: else:
z = np.random.randint(z_min + 1, z_max - 1) z = np.random.randint(z_min + 1, z_max)
width = perimeter_width // 2 width = perimeter_width // 2
depth = perimeter_depth // 2 depth = perimeter_depth // 2
height = y_max - y_min height = y_max - y_min
if x + width - 1 > x_max - 1: if x + width - 1 > x_max:
x = x_max - width - 1 x = x_max - width
if z + depth - 1 > z_max - 1: if z + depth - 1 > z_max:
z = z_max - depth - 1 z = z_max - depth
x_plan3d = x - x_min x_plan3d = x - x_min
z_plan3d = z - z_min z_plan3d = z - z_min
for i in range(0, width - 1): geometry.placeCuboid(self.editor, (x, y_min, z), (x + width - 1, y_min, z + depth - 1), self.floor)
for j in range(0, depth - 1): x_range = slice(x_plan3d, x_plan3d + width - 1)
self.editor.placeBlock((x + i, y_min, z + j), self.floor) z_range = slice(z_plan3d, z_plan3d + depth - 1)
self.grid3d[x_plan3d + i, 0, z_plan3d + j] = True, 1 self.grid3d[x_range, 0, z_range] = True, 1
self.skeleton.append((x, z, width - 1, depth - 1, height)) 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), print("Coordinates of the corners: ", (x, z), (x, z + depth - 1),
(x + width - 1, z + depth - 1)) (x + width - 1, z), (x + width - 1, z + depth - 1))
x_min -= 1 x_min -= 1
x_max -= 1 x_max -= 1
@@ -104,54 +107,47 @@ class House:
else: else:
new_width = np.random.randint(width - 2, 5) new_width = np.random.randint(width - 2, 5)
if max(x_min+1, x-new_width) > min(x_max-new_width-1, x+width): if max(x_min+1, x-new_width) > min(x_max-new_width, x+width):
new_x = np.random.randint( new_x = np.random.randint(min(x_max - new_width, x + width),
min(x_max - new_width - 1, x + width), max(x_min + 1, x - new_width)) max(x_min + 1, x - new_width))
else: else:
new_x = np.random.randint( new_x = np.random.randint(max(x_min + 1, x - new_width),
max(x_min + 1, x - new_width), min(x_max - new_width - 1, x + width)) min(x_max - new_width, x + width))
if max(z_min+1, z-new_depth) > min(z_max-new_depth-1, z+depth): if max(z_min+1, z-new_depth) > min(z_max-new_depth, z+depth):
new_z = np.random.randint( new_z = np.random.randint(min(z_max - new_depth, z + depth),
min(z_max - new_depth - 1, z + depth), max(z_min + 1, z - new_depth)) max(z_min + 1, z - new_depth))
else: else:
new_z = np.random.randint( new_z = np.random.randint(max(z_min + 1, z - new_depth),
max(z_min + 1, z - new_depth), min(z_max - new_depth - 1, z + depth)) min(z_max - new_depth, z + depth))
new_x_plan3d = new_x - x_min - 1 new_x_plan3d = new_x - x_min - 1
new_z_plan3d = new_z - z_min + 1 new_z_plan3d = new_z - z_min + 1
adjacent_blocks = 0 adjacent_blocks = 0
for i in range(new_x_plan3d, new_x_plan3d + new_width): for i in range(new_x_plan3d, new_x_plan3d + new_width) :
for j in range(new_z_plan3d, new_z_plan3d + new_depth): 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 \ 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 + 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 or \
self.grid3d[i, 0, j + 1]['bool'] and self.grid3d[i, 0, j + 1]['int'] == 1: self.grid3d[i, 0, j + 1]['bool'] and self.grid3d[i, 0, j + 1]['int'] == 1:
adjacent_blocks += 1 adjacent_blocks += 1
if adjacent_blocks < 3: new_x_range = slice(new_x_plan3d, new_x_plan3d + new_width)
new_z_range = slice(new_z_plan3d, new_z_plan3d + new_depth)
if adjacent_blocks < 3 or np.any(self.grid3d[new_x_range, 0, new_z_range]['bool']) :
continue continue
if not np.any( geometry.placeCuboid(self.editor, (new_x, y_min, new_z), (new_x+new_width-1, y_min, new_z+new_depth-1), self.floor)
self.grid3d[new_x_plan3d:new_x_plan3d + new_width, 0, new_z_plan3d:new_z_plan3d + new_depth][ new_x_plan3d += 1
'bool']): new_z_plan3d -= 1
new_x_plan3d = new_x - x_min new_x_range = slice(new_x_plan3d, new_x_plan3d + new_width)
new_z_plan3d = new_z - z_min new_z_range = slice(new_z_plan3d, new_z_plan3d + new_depth)
for i in range(0, new_width): self.grid3d[new_x_range, 0, new_z_range] = True, 2
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: self.skeleton.append((new_x, new_z, new_width, new_depth, height))
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 break
else: else:
print("Failed to place rectangle after 100000 attempts.") print("Failed to place rectangle after 100000 attempts.")
@@ -1249,6 +1245,7 @@ class House:
self.placeStairs() self.placeStairs()
if __name__ == "__main__": if __name__ == "__main__":
editor = Editor(buffering=True) editor = Editor(buffering=True)
buildArea = editor.getBuildArea() buildArea = editor.getBuildArea()

16
main.py
View File

@@ -15,7 +15,8 @@ from networks.geometry.Point3D import Point3D
from networks.geometry.Point2D import Point2D from networks.geometry.Point2D import Point2D
from networks.geometry.Circle import Circle from networks.geometry.Circle import Circle
from PIL import Image from PIL import Image as img
from PIL.Image import Image
from utils.JsonReader import JsonReader from utils.JsonReader import JsonReader
from utils.YamlReader import YamlReader from utils.YamlReader import YamlReader
from buildings.Building import Building from buildings.Building import Building
@@ -44,6 +45,7 @@ def main():
time_remove_tree = time.time() - start_time time_remove_tree = time.time() - start_time
print(f"[TIME] Remove tree {time_remove_tree}") print(f"[TIME] Remove tree {time_remove_tree}")
"""
start_time = time.time() start_time = time.time()
smooth_terrain('./world_maker/data/heightmap.png', smooth_terrain('./world_maker/data/heightmap.png',
'./world_maker/data/heightmap_smooth.png', './world_maker/data/smooth_sobel_watermap.png') './world_maker/data/heightmap_smooth.png', './world_maker/data/smooth_sobel_watermap.png')
@@ -117,17 +119,17 @@ def main():
entranceDirection[random.randint(0, 3)], blocks) entranceDirection[random.randint(0, 3)], blocks)
house.build() house.build()
time_houses = time.time() - start_time time_houses = time.time() - start_time
print(f"[TIME] Houses {time_houses}") print(f"[TIME] Houses {time_houses}") """
print("[GDMC] Done!\n\n") print("[GDMC] Done!\n\n")
print(f"[TIME] Total {time.time() - start_time_all}") print(f"[TIME] Total {time.time() - start_time_all}")
print(f"[TIME] World_maker {time_world_maker}") print(f"[TIME] World_maker {time_world_maker}")
print(f"[TIME] Remove tree {time_remove_tree}") print(f"[TIME] Remove tree {time_remove_tree}")
print(f"[TIME] Smooth terrain {time_smooth_terrain}") #print(f"[TIME] Smooth terrain {time_smooth_terrain}")
print(f"[TIME] Roads {time_roads}") #print(f"[TIME] Roads {time_roads}")
print(f"[TIME] Buildings {time_buildings}") #print(f"[TIME] Buildings {time_buildings}")
print(f"[TIME] Houses {time_houses}") #print(f"[TIME] Houses {time_houses}")
def get_height_building_from_center(center, position, length_world): def get_height_building_from_center(center, position, length_world):
@@ -162,7 +164,7 @@ def set_roads(skeleton: Skeleton, origin):
for j in range(len(skeleton.lines[i])): for j in range(len(skeleton.lines[i])):
xyz = transpose_form_heightmap('./world_maker/data/heightmap.png', xyz = transpose_form_heightmap('./world_maker/data/heightmap.png',
skeleton.coordinates[skeleton.lines[i][j]], origin) skeleton.coordinates[skeleton.lines[i][j]], origin)
heightmap_smooth = Image.open( heightmap_smooth = img.open(
'./world_maker/data/road_heightmap.png') './world_maker/data/road_heightmap.png')
skeleton.lines[i][j] = [xyz[0], heightmap_smooth.getpixel( skeleton.lines[i][j] = [xyz[0], heightmap_smooth.getpixel(
(skeleton.coordinates[skeleton.lines[i][j]][0], skeleton.coordinates[skeleton.lines[i][j]][-1])), xyz[2]] (skeleton.coordinates[skeleton.lines[i][j]][0], skeleton.coordinates[skeleton.lines[i][j]][-1])), xyz[2]]

View File

@@ -4,7 +4,8 @@ from typing import List, Union
import numpy as np import numpy as np
from gdpc import Editor from gdpc import Editor
from PIL import Image, ImageDraw from PIL.Image import Image
from PIL import Image as img, ImageDraw
from skan.csr import skeleton_to_csgraph from skan.csr import skeleton_to_csgraph
from skimage.morphology import skeletonize from skimage.morphology import skeletonize
from networks.geometry.Point3D import Point3D from networks.geometry.Point3D import Point3D
@@ -12,7 +13,7 @@ from networks.geometry.Point3D import Point3D
def handle_import_image(image: Union[str, Image]) -> Image: def handle_import_image(image: Union[str, Image]) -> Image:
if isinstance(image, str): if isinstance(image, str):
return Image.open(image) return img.open(image)
return image return image
@@ -203,7 +204,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( heightmap = img.open(
"./world_maker/data/heightmap.png").convert('RGB') "./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
@@ -264,9 +265,9 @@ class Skeleton:
def road_area(self, name: str, radius: int = 10) -> Image: def road_area(self, name: str, radius: int = 10) -> Image:
print("[Skeleton] Start mapping the road area...") print("[Skeleton] Start mapping the road area...")
heightmap = Image.open("./world_maker/data/heightmap.png") heightmap = img.open("./world_maker/data/heightmap.png")
width, height = heightmap.size width, height = heightmap.size
road_area_map = Image.new("L", (width, height), 0) road_area_map = img.new("L", (width, height), 0)
road_area_map_draw = ImageDraw.Draw(road_area_map) road_area_map_draw = ImageDraw.Draw(road_area_map)
# Lines # Lines

View File

@@ -29,8 +29,10 @@ class World:
editor = Editor(buffering=True) editor = Editor(buffering=True)
buildArea = editor.getBuildArea() buildArea = editor.getBuildArea()
self.coordinates_min = [min(buildArea.begin[i], buildArea.last[i]) for i in range(3)] self.coordinates_min = [
self.coordinates_max = [max(buildArea.begin[i], buildArea.last[i]) for i in range(3)] min(buildArea.begin[i], buildArea.last[i]) for i in range(3)]
self.coordinates_max = [
max(buildArea.begin[i], buildArea.last[i]) for i in range(3)]
self.length_x = self.coordinates_max[0] - self.coordinates_min[0] + 1 self.length_x = self.coordinates_max[0] - self.coordinates_min[0] + 1
self.length_y = self.coordinates_max[1] - self.coordinates_min[1] + 1 self.length_y = self.coordinates_max[1] - self.coordinates_min[1] + 1
@@ -62,7 +64,8 @@ class World:
Add block or list of block to the volume. Add block or list of block to the volume.
""" """
self.volume[volumeCoordinates[0]][volumeCoordinates[1]][volumeCoordinates[2]] = None self.volume[volumeCoordinates[0]][volumeCoordinates[1]
][volumeCoordinates[2]] = None
def getBlockFromCoordinates(self, coordinates): def getBlockFromCoordinates(self, coordinates):
""" """
@@ -85,9 +88,11 @@ class World:
for j in range(-1, 2): for j in range(-1, 2):
for k in range(-1, 2): for k in range(-1, 2):
if not (i == 0 and j == 0 and k == 0): if not (i == 0 and j == 0 and k == 0):
coordinates = (Block.coordinates[0] + i, Block.coordinates[1] + j, Block.coordinates[2] + k) coordinates = (
Block.coordinates[0] + i, Block.coordinates[1] + j, Block.coordinates[2] + k)
if self.isInVolume(coordinates): if self.isInVolume(coordinates):
Block.addNeighbors([self.getBlockFromCoordinates(coordinates)]) Block.addNeighbors(
[self.getBlockFromCoordinates(coordinates)])
def setVolume(self): def setVolume(self):
""" """
@@ -99,7 +104,8 @@ class World:
for x in range(self.coordinates_min[0], self.coordinates_max[0] + 1): for x in range(self.coordinates_min[0], self.coordinates_max[0] + 1):
for y in range(self.coordinates_min[1], self.coordinates_max[1] + 1): for y in range(self.coordinates_min[1], self.coordinates_max[1] + 1):
for z in range(self.coordinates_min[2], self.coordinates_max[2] + 1): for z in range(self.coordinates_min[2], self.coordinates_max[2] + 1):
self.addBlocks([Block((x, y, z), editor.getBlock((x, y, z)).id)]) self.addBlocks(
[Block((x, y, z), editor.getBlock((x, y, z)).id)])
def getData(self): def getData(self):
""" """
@@ -120,8 +126,10 @@ class World:
slice = editor.loadWorldSlice(buildRect) slice = editor.loadWorldSlice(buildRect)
heightmapData = list(np.array(slice.heightmaps["MOTION_BLOCKING_NO_LEAVES"], dtype=np.uint8)) heightmapData = list(
treesmapData = list(np.array(slice.heightmaps["MOTION_BLOCKING"], dtype=np.uint8)) np.array(slice.heightmaps["MOTION_BLOCKING_NO_LEAVES"], dtype=np.uint16))
treesmapData = list(
np.array(slice.heightmaps["MOTION_BLOCKING"], dtype=np.uint16))
for x in range(0, xzDistance[0]): for x in range(0, xzDistance[0]):
for z in range(0, xzDistance[1]): for z in range(0, xzDistance[1]):
@@ -148,7 +156,8 @@ class World:
# print('getData for tree', xzStart[0] + x + i, k, xzStart[1] + z + j) # print('getData for tree', xzStart[0] + x + i, k, xzStart[1] + z + j)
blockNeighbor = slice.getBlock((x + i, k, z + j)) blockNeighbor = slice.getBlock(
(x + i, k, z + j))
if blockNeighbor.id not in lookup.TREES: if blockNeighbor.id not in lookup.TREES:
height += k height += k
number += 1 number += 1
@@ -162,7 +171,9 @@ class World:
else: else:
watermap.putpixel((x, z), 0) watermap.putpixel((x, z), 0)
self.addBlocks([Block((xzStart[0] + x, 100, xzStart[1] + z), block)]) # y set to 100 for 2D # y set to 100 for 2D
self.addBlocks(
[Block((xzStart[0] + x, 100, xzStart[1] + z), block)])
return heightmap, watermap, treesmap return heightmap, watermap, treesmap
@@ -213,7 +224,8 @@ class World:
slice = editor.loadWorldSlice(buildRect) slice = editor.loadWorldSlice(buildRect)
heightmapData = list(np.array(slice.heightmaps["MOTION_BLOCKING_NO_LEAVES"], dtype=np.uint8)) heightmapData = list(
np.array(slice.heightmaps["MOTION_BLOCKING_NO_LEAVES"], dtype=np.uint8))
for x in range(0, xzDistance[0]): for x in range(0, xzDistance[0]):
for z in range(0, xzDistance[1]): for z in range(0, xzDistance[1]):

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 89 B

View File

@@ -2,7 +2,8 @@ from typing import Union
import numpy as np import numpy as np
from gdpc import Editor, Block, geometry, lookup from gdpc import Editor, Block, geometry, lookup
from PIL import Image from PIL import Image as img
from PIL.Image import Image
from skimage import morphology from skimage import morphology
from world_maker.data_analysis import handle_import_image from world_maker.data_analysis import handle_import_image
@@ -16,38 +17,25 @@ def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask
start = build_rectangle.begin start = build_rectangle.begin
distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]), max( distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]),
build_rectangle.end[1], build_rectangle.begin[1]) - min(build_rectangle.end[1], build_rectangle.begin[1])) max(build_rectangle.end[1], build_rectangle.begin[1]) - min(build_rectangle.end[1], build_rectangle.begin[1]))
heightmap = handle_import_image(heightmap).convert('L') heightmap = handle_import_image(heightmap).convert('L')
treesmap = handle_import_image(treesmap).convert('L') treesmap = handle_import_image(treesmap).convert('L')
mask = handle_import_image(mask) mask = handle_import_image(mask)
removed_treesmap = Image.new("L", distance, 0) removed_treesmap = img.new("L", distance, 0)
removed = [] for (x, z) in [(x, z) for x in range(distance[0]) for z in range(distance[1])] :
for x in range(0, distance[0]):
for z in range(0, distance[1]):
if mask.getpixel((x, z)) != 0 and treesmap.getpixel((x, z)) > 0 and (x, z) not in removed: if mask.getpixel((x, z)) != 0 and treesmap.getpixel((x, z)) > 0:
tree_area = morphology.flood(treesmap, (z, x), tolerance=1) tree_area = morphology.flood(treesmap, (z, x), tolerance=1)
blend = Image.blend(Image.fromarray(tree_area).convert( removed_treesmap = img.fromarray(np.where(tree_area, treesmap, 0).astype(np.uint8))
'L'), removed_treesmap.convert('L'), 0.5)
array = np.array(blend.convert('L'))
bool_array = array > 1
removed_treesmap = Image.fromarray(bool_array)
removed.append((x, z))
for x in range(0, distance[0]):
for z in range(0, distance[1]):
if removed_treesmap.getpixel((x, z)) != 0:
y = heightmap.getpixel((x, z)) y = heightmap.getpixel((x, z))
y_top = removed_treesmap.getpixel((x, z)) y_top = removed_treesmap.getpixel((x, z))
geometry.placeLine( geometry.placeLine(editor, (start[0] + x, y+1, start[1] + z), (start[0] + x, y_top, start[1] + z), Block('air'))
editor, (start[0] + x, y+1, start[1] + z), (start[0] + x, y_top, start[1] + z), Block('air'))
removed_treesmap.save('./world_maker/data/removed_treesmap.png') removed_treesmap.save('./world_maker/data/removed_treesmap.png')
print("[Remove tree] Done.") print("[Remove tree] Done.")
@@ -62,39 +50,39 @@ def smooth_terrain(heightmap: Union[str, Image], heightmap_smooth: Union[str, Im
start = build_rectangle.begin start = build_rectangle.begin
distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]), max( distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]),
build_rectangle.end[1], build_rectangle.begin[1]) - min(build_rectangle.end[1], build_rectangle.begin[1])) max(build_rectangle.end[1], build_rectangle.begin[1]) - min(build_rectangle.end[1], build_rectangle.begin[1]))
heightmap = handle_import_image(heightmap).convert('L') heightmap = handle_import_image(heightmap).convert('L')
heightmap_smooth = handle_import_image(heightmap_smooth).convert('L') heightmap_smooth = handle_import_image(heightmap_smooth).convert('L')
mask = handle_import_image(mask).convert('L') mask = handle_import_image(mask).convert('L')
smooth_terrain_delta = Image.new("RGB", distance, 0) smooth_terrain_delta = img.new("RGB", distance, 0)
slice = editor.loadWorldSlice(build_rectangle) slice = editor.loadWorldSlice(build_rectangle)
smoothable_blocks = lookup.OVERWORLD_SOILS | lookup.OVERWORLD_STONES | lookup.SNOWS smoothable_blocks = lookup.OVERWORLD_SOILS | lookup.OVERWORLD_STONES | lookup.SNOWS
for x in range(0, distance[0]): for (x, z) in [(x, z) for x in range(distance[0]) for z in range(distance[1])] :
for z in range(0, distance[1]):
if mask.getpixel((x, z)) != 0: if mask.getpixel((x, z)) == 0:
continue
y = heightmap.getpixel((x, z)) y = heightmap.getpixel((x, z))
y_smooth = heightmap_smooth.getpixel((x, z)) y_smooth = heightmap_smooth.getpixel((x, z))
delta = y - y_smooth delta = y - y_smooth
smooth_terrain_delta.putpixel((x, z), delta) smooth_terrain_delta.putpixel((x, z), delta)
if delta != 0: if delta == 0:
continue
block = slice.getBlock((x, y, z)) block = slice.getBlock((x, y, z))
if block.id in smoothable_blocks:
if block.id not in smoothable_blocks:
continue
if delta > 0: if delta > 0:
geometry.placeLine( geometry.placeLine(editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), Block('air'))
editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), Block('air')) editor.placeBlock((start[0] + x, y_smooth, start[1] + z), block)
editor.placeBlock(
(start[0] + x, y_smooth, start[1] + z), block)
else: else:
geometry.placeLine( geometry.placeLine(editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), block)
editor, (start[0] + x, y, start[1] + z), (start[0] + x, y_smooth, start[1] + z), block)
smooth_terrain_delta.save('./world_maker/data/smooth_terrain_delta.png') smooth_terrain_delta.save('./world_maker/data/smooth_terrain_delta.png')
print("[Smooth terrain] Done.") print("[Smooth terrain] Done.")