diff --git a/main.py b/main.py index 7f912dc..cb3a8b6 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ import gdpc.exceptions from world_maker.world_maker import * from world_maker.data_analysis import transpose_form_heightmap from world_maker.Skeleton import Skeleton, simplify_coordinates -from world_maker.terraforming import remove_trees +from world_maker.terraforming import remove_trees, smooth_terrain from networks.geometry.Point3D import Point3D from networks.roads_2.Road import Road from networks.legacy_roads import roads @@ -21,8 +21,10 @@ def main(): buildArea = editor.getBuildArea() origin = ((buildArea.begin).x, (buildArea.begin).z) - remove_trees('./world_maker/data/heightmap.png', - './world_maker/data/treemap.png', './world_maker/data/smooth_sobel_watermap.png') + # remove_trees('./world_maker/data/heightmap.png', './world_maker/data/treemap.png', + # './world_maker/data/smooth_sobel_watermap.png') + smooth_terrain('./world_maker/data/heightmap.png', + './world_maker/data/heightmap_smooth.png', './world_maker/data/smooth_sobel_watermap.png') # set_roads(skeleton_mountain, origin) # set_roads(skeleton_highway, origin) diff --git a/world_maker/data/building.png b/world_maker/data/building.png index 4d8c79a..7160ed9 100644 Binary files a/world_maker/data/building.png and b/world_maker/data/building.png differ diff --git a/world_maker/data/city_map.png b/world_maker/data/city_map.png index ae6e3f8..a6d60e6 100644 Binary files a/world_maker/data/city_map.png and b/world_maker/data/city_map.png differ diff --git a/world_maker/data/district.png b/world_maker/data/district.png index c4193b7..d8191d3 100644 Binary files a/world_maker/data/district.png and b/world_maker/data/district.png differ diff --git a/world_maker/data/heightmap.png b/world_maker/data/heightmap.png index b379956..b961768 100644 Binary files a/world_maker/data/heightmap.png and b/world_maker/data/heightmap.png differ diff --git a/world_maker/data/heightmap_smooth.png b/world_maker/data/heightmap_smooth.png new file mode 100644 index 0000000..e366caa Binary files /dev/null and b/world_maker/data/heightmap_smooth.png differ diff --git a/world_maker/data/highwaymap.png b/world_maker/data/highwaymap.png index dc3fecf..eda2e82 100644 Binary files a/world_maker/data/highwaymap.png and b/world_maker/data/highwaymap.png differ diff --git a/world_maker/data/mountain_map.png b/world_maker/data/mountain_map.png index 89ef441..57e7a16 100644 Binary files a/world_maker/data/mountain_map.png and b/world_maker/data/mountain_map.png differ diff --git a/world_maker/data/removed_treesmap.png b/world_maker/data/removed_treesmap.png index f41640e..ad74f8b 100644 Binary files a/world_maker/data/removed_treesmap.png and b/world_maker/data/removed_treesmap.png differ diff --git a/world_maker/data/roadmap.png b/world_maker/data/roadmap.png index da2b612..b5fbd37 100644 Binary files a/world_maker/data/roadmap.png and b/world_maker/data/roadmap.png differ diff --git a/world_maker/data/skeleton_highway.png b/world_maker/data/skeleton_highway.png index 9ac6485..a486dcd 100644 Binary files a/world_maker/data/skeleton_highway.png and b/world_maker/data/skeleton_highway.png differ diff --git a/world_maker/data/skeleton_highway_area.png b/world_maker/data/skeleton_highway_area.png index 6a9ecf9..4ca5c47 100644 Binary files a/world_maker/data/skeleton_highway_area.png and b/world_maker/data/skeleton_highway_area.png differ diff --git a/world_maker/data/skeleton_mountain.png b/world_maker/data/skeleton_mountain.png index 44968bb..8b2fae1 100644 Binary files a/world_maker/data/skeleton_mountain.png and b/world_maker/data/skeleton_mountain.png differ diff --git a/world_maker/data/skeleton_mountain_area.png b/world_maker/data/skeleton_mountain_area.png index 7010d14..dd64749 100644 Binary files a/world_maker/data/skeleton_mountain_area.png and b/world_maker/data/skeleton_mountain_area.png differ diff --git a/world_maker/data/smooth_sobel_watermap.png b/world_maker/data/smooth_sobel_watermap.png index 64c79e6..df4efa0 100644 Binary files a/world_maker/data/smooth_sobel_watermap.png and b/world_maker/data/smooth_sobel_watermap.png differ diff --git a/world_maker/data/smooth_terrain_delta.png b/world_maker/data/smooth_terrain_delta.png new file mode 100644 index 0000000..85e44d0 Binary files /dev/null and b/world_maker/data/smooth_terrain_delta.png differ diff --git a/world_maker/data/sobelmap.png b/world_maker/data/sobelmap.png index 4020e72..2147614 100644 Binary files a/world_maker/data/sobelmap.png and b/world_maker/data/sobelmap.png differ diff --git a/world_maker/data/treemap.png b/world_maker/data/treemap.png index 474d635..a721eb6 100644 Binary files a/world_maker/data/treemap.png and b/world_maker/data/treemap.png differ diff --git a/world_maker/data/watermap.png b/world_maker/data/watermap.png index 7010d14..38472c6 100644 Binary files a/world_maker/data/watermap.png and b/world_maker/data/watermap.png differ diff --git a/world_maker/data_analysis.py b/world_maker/data_analysis.py index 361d654..a04fa60 100644 --- a/world_maker/data_analysis.py +++ b/world_maker/data_analysis.py @@ -105,7 +105,7 @@ def filter_sobel(image: Union[str, Image]) -> Image: return image -def filter_smooth(image: Union[str, Image], radius: int = 3): +def filter_smooth_theshold(image: Union[str, Image], radius: int = 3): """ :param image: white and black image representing the derivative of the terrain (sobel), where black is flat and white is very steep. :param radius: Radius of the Gaussian blur. @@ -135,6 +135,14 @@ def filter_smooth(image: Union[str, Image], radius: int = 3): return Image.fromarray(bool_array) +def filter_smooth(image: Union[str, Image], radius: int = 3): + + image = handle_import_image(image) + image = image.convert('L') + image = image.filter(ImageFilter.GaussianBlur(radius)) + return image + + def subtract_map(image: Union[str, Image], substractImage: Union[str, Image]) -> Image: image = handle_import_image(image) substractImage = handle_import_image(substractImage).convert('L') @@ -163,7 +171,7 @@ def group_map(image1: Union[str, Image], image2: Union[str, Image]) -> Image: def filter_smooth_array(array: np.ndarray, radius: int = 3) -> np.ndarray: image = Image.fromarray(array) - smooth_image = filter_smooth(image, radius) + smooth_image = filter_smooth_theshold(image, radius) array = np.array(smooth_image) return array @@ -182,7 +190,7 @@ def filter_remove_details(image: Union[str, Image], n: int = 20) -> Image: def highway_map() -> Image: print("[Data Analysis] Generating highway map...") - smooth_sobel = filter_smooth("./world_maker/data/sobelmap.png", 1) + smooth_sobel = filter_smooth_theshold("./world_maker/data/sobelmap.png", 1) negative_smooth_sobel = filter_negative(smooth_sobel) negative_smooth_sobel_water = subtract_map( negative_smooth_sobel, './world_maker/data/watermap.png') @@ -247,7 +255,7 @@ def smooth_sobel_water() -> Image: 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) + sobel = filter_remove_details(filter_smooth_theshold(sobel, 1), 2) group = group_map(watermap, sobel) group = filter_negative(group) group.save('./world_maker/data/smooth_sobel_watermap.png') diff --git a/world_maker/terraforming.py b/world_maker/terraforming.py index 28455b2..73b047e 100644 --- a/world_maker/terraforming.py +++ b/world_maker/terraforming.py @@ -1,14 +1,14 @@ from typing import Union import numpy as np -from gdpc import Editor, Block, geometry +from gdpc import Editor, Block, geometry, lookup from PIL import Image from skimage import morphology from world_maker.data_analysis import handle_import_image -def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask: Union[str, Image], ): +def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask: Union[str, Image]): editor = Editor(buffering=True) build_area = editor.getBuildArea() @@ -29,7 +29,7 @@ def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask for x in range(0, distance[0]): for z in range(0, distance[1]): - if mask.getpixel((x, z)) == 255 and treesmap.getpixel((x, z)) > 0 and (x, z) not in removed: + if mask.getpixel((x, z)) != 0 and treesmap.getpixel((x, z)) > 0 and (x, z) not in removed: treeArea = morphology.flood(treesmap, (z, x), tolerance=1) blend = Image.blend(Image.fromarray(treeArea).convert( @@ -52,3 +52,48 @@ def remove_trees(heightmap: Union[str, Image], treesmap: Union[str, Image], mask y_top = removed_treesmap.getpixel((x, z)) geometry.placeLine( editor, (start[0] + x, y+1, start[1] + z), (start[0] + x, y_top, start[1] + z), Block('air')) + + +def smooth_terrain(heightmap: Union[str, Image], heightmap_smooth: Union[str, Image], mask: Union[str, Image]): + + editor = Editor() + build_area = editor.getBuildArea() + build_rectangle = build_area.toRect() + + start = build_rectangle.begin + + distance = (max(build_rectangle.end[0], build_rectangle.begin[0]) - min(build_rectangle.end[0], build_rectangle.begin[0]), 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_smooth = handle_import_image(heightmap_smooth).convert('L') + mask = handle_import_image(mask).convert('L') + + smooth_terrain_delta = Image.new("RGB", distance, 0) + + slice = editor.loadWorldSlice(build_rectangle) + smoothable_blocks = lookup.OVERWORLD_SOILS | lookup.OVERWORLD_STONES | lookup.SNOWS + + for x in range(0, distance[0]): + for z in range(0, distance[1]): + + if mask.getpixel((x, z)) != 0: + y = heightmap.getpixel((x, z)) + y_smooth = heightmap_smooth.getpixel((x, z)) + delta = y - y_smooth + smooth_terrain_delta.putpixel((x, z), delta) + + if delta != 0: + block = slice.getBlock((x, y, z)) + if block.id in smoothable_blocks: + if delta > 0: + geometry.placeLine( + 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) + + else: + geometry.placeLine( + 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') diff --git a/world_maker/world_maker.py b/world_maker/world_maker.py index a007e62..5ac439a 100644 --- a/world_maker/world_maker.py +++ b/world_maker/world_maker.py @@ -1,7 +1,7 @@ from world_maker.World import World from PIL import Image 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) + smooth_sobel_water, subtract_map, detect_mountain, filter_smooth) from world_maker.City import City from world_maker.Position import Position from random import randint @@ -11,8 +11,13 @@ from world_maker.pack_rectangle import generate_building def world_maker(): world = World() heightmap, watermap, treemap = get_data(world) + + filter_smooth( + './world_maker/data/heightmap.png', 4).save('./world_maker/data/heightmap_smooth.png') + filter_sobel( "./world_maker/data/heightmap.png").save('./world_maker/data/sobelmap.png') + smooth_sobel_water_map = smooth_sobel_water() skeleton_highway = skeleton_highway_map(highway_map()) city = City()