Add smooth terrain
8
main.py
@@ -5,7 +5,7 @@ import gdpc.exceptions
|
|||||||
from world_maker.world_maker import *
|
from world_maker.world_maker import *
|
||||||
from world_maker.data_analysis import transpose_form_heightmap
|
from world_maker.data_analysis import transpose_form_heightmap
|
||||||
from world_maker.Skeleton import Skeleton, simplify_coordinates
|
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.geometry.Point3D import Point3D
|
||||||
from networks.roads_2.Road import Road
|
from networks.roads_2.Road import Road
|
||||||
from networks.legacy_roads import roads
|
from networks.legacy_roads import roads
|
||||||
@@ -21,8 +21,10 @@ def main():
|
|||||||
buildArea = editor.getBuildArea()
|
buildArea = editor.getBuildArea()
|
||||||
origin = ((buildArea.begin).x, (buildArea.begin).z)
|
origin = ((buildArea.begin).x, (buildArea.begin).z)
|
||||||
|
|
||||||
remove_trees('./world_maker/data/heightmap.png',
|
# remove_trees('./world_maker/data/heightmap.png', './world_maker/data/treemap.png',
|
||||||
'./world_maker/data/treemap.png', './world_maker/data/smooth_sobel_watermap.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_mountain, origin)
|
||||||
# set_roads(skeleton_highway, origin)
|
# set_roads(skeleton_highway, origin)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 387 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 12 KiB |
BIN
world_maker/data/heightmap_smooth.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 645 B |
|
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 454 B |
|
Before Width: | Height: | Size: 960 B After Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 748 B |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
world_maker/data/smooth_terrain_delta.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 658 B |
@@ -105,7 +105,7 @@ def filter_sobel(image: Union[str, Image]) -> Image:
|
|||||||
return 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 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.
|
: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)
|
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:
|
def subtract_map(image: Union[str, Image], substractImage: Union[str, Image]) -> Image:
|
||||||
image = handle_import_image(image)
|
image = handle_import_image(image)
|
||||||
substractImage = handle_import_image(substractImage).convert('L')
|
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:
|
def filter_smooth_array(array: np.ndarray, radius: int = 3) -> np.ndarray:
|
||||||
image = Image.fromarray(array)
|
image = Image.fromarray(array)
|
||||||
smooth_image = filter_smooth(image, radius)
|
smooth_image = filter_smooth_theshold(image, radius)
|
||||||
array = np.array(smooth_image)
|
array = np.array(smooth_image)
|
||||||
return array
|
return array
|
||||||
|
|
||||||
@@ -182,7 +190,7 @@ 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("./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 = filter_negative(smooth_sobel)
|
||||||
negative_smooth_sobel_water = subtract_map(
|
negative_smooth_sobel_water = subtract_map(
|
||||||
negative_smooth_sobel, './world_maker/data/watermap.png')
|
negative_smooth_sobel, './world_maker/data/watermap.png')
|
||||||
@@ -247,7 +255,7 @@ def smooth_sobel_water() -> Image:
|
|||||||
watermap = filter_negative(
|
watermap = filter_negative(
|
||||||
filter_remove_details(filter_negative(watermap), 5))
|
filter_remove_details(filter_negative(watermap), 5))
|
||||||
sobel = handle_import_image("./world_maker/data/sobelmap.png")
|
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 = group_map(watermap, sobel)
|
||||||
group = filter_negative(group)
|
group = filter_negative(group)
|
||||||
group.save('./world_maker/data/smooth_sobel_watermap.png')
|
group.save('./world_maker/data/smooth_sobel_watermap.png')
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gdpc import Editor, Block, geometry
|
from gdpc import Editor, Block, geometry, lookup
|
||||||
from PIL import Image
|
from PIL 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
|
||||||
|
|
||||||
|
|
||||||
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)
|
editor = Editor(buffering=True)
|
||||||
build_area = editor.getBuildArea()
|
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 x in range(0, distance[0]):
|
||||||
for z in range(0, distance[1]):
|
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)
|
treeArea = morphology.flood(treesmap, (z, x), tolerance=1)
|
||||||
blend = Image.blend(Image.fromarray(treeArea).convert(
|
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))
|
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'))
|
||||||
|
|
||||||
|
|
||||||
|
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')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from world_maker.World import World
|
from world_maker.World import World
|
||||||
from PIL import Image
|
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,
|
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.City import City
|
||||||
from world_maker.Position import Position
|
from world_maker.Position import Position
|
||||||
from random import randint
|
from random import randint
|
||||||
@@ -11,8 +11,13 @@ from world_maker.pack_rectangle import generate_building
|
|||||||
def world_maker():
|
def world_maker():
|
||||||
world = World()
|
world = World()
|
||||||
heightmap, watermap, treemap = get_data(world)
|
heightmap, watermap, treemap = get_data(world)
|
||||||
|
|
||||||
|
filter_smooth(
|
||||||
|
'./world_maker/data/heightmap.png', 4).save('./world_maker/data/heightmap_smooth.png')
|
||||||
|
|
||||||
filter_sobel(
|
filter_sobel(
|
||||||
"./world_maker/data/heightmap.png").save('./world_maker/data/sobelmap.png')
|
"./world_maker/data/heightmap.png").save('./world_maker/data/sobelmap.png')
|
||||||
|
|
||||||
smooth_sobel_water_map = smooth_sobel_water()
|
smooth_sobel_water_map = smooth_sobel_water()
|
||||||
skeleton_highway = skeleton_highway_map(highway_map())
|
skeleton_highway = skeleton_highway_map(highway_map())
|
||||||
city = City()
|
city = City()
|
||||||
|
|||||||