Add legacy support
This commit is contained in:
210
networks/legacy_roads/Skeleton.py
Normal file
210
networks/legacy_roads/Skeleton.py
Normal file
@@ -0,0 +1,210 @@
|
||||
import numpy as np
|
||||
import skan
|
||||
from skimage.morphology import skeletonize
|
||||
from skan.csr import skeleton_to_csgraph
|
||||
from collections import Counter
|
||||
from PIL import Image
|
||||
import random
|
||||
|
||||
from gdpc import Editor
|
||||
|
||||
|
||||
class Skeleton:
|
||||
def __init__(self):
|
||||
self.lines = []
|
||||
self.intersections = []
|
||||
self.centers = []
|
||||
self.graph = []
|
||||
self.coordinates = []
|
||||
|
||||
def setSkeleton(self, data):
|
||||
binary_skeleton = skeletonize(data)
|
||||
|
||||
graph, coordinates = skeleton_to_csgraph(binary_skeleton)
|
||||
self.graph = graph.tocoo()
|
||||
|
||||
# List of lists. Inverted coordinates.
|
||||
coordinates = list(coordinates)
|
||||
print(coordinates)
|
||||
for i in range(len(coordinates)):
|
||||
coordinates[i] = list(coordinates[i])
|
||||
|
||||
print(coordinates)
|
||||
coordinates_final = []
|
||||
|
||||
for i in range(len(coordinates[0])):
|
||||
print((coordinates[0][i], coordinates[1][i], coordinates[2][i]))
|
||||
coordinates_final.append(
|
||||
(coordinates[0][i], coordinates[1][i], coordinates[2][i]))
|
||||
|
||||
self.coordinates = coordinates_final
|
||||
|
||||
def findNextElements(self, key):
|
||||
"""Find the very nearest elements"""
|
||||
|
||||
line = []
|
||||
|
||||
values = np.array(self.graph.row)
|
||||
indices = np.where(values == key)[0]
|
||||
|
||||
for i in range(len(indices)):
|
||||
if self.graph.row[indices[i]] == key:
|
||||
line.append(self.graph.col[indices[i]])
|
||||
return line
|
||||
|
||||
def findLine(self, key):
|
||||
nextKeys = self.findNextElements(key)
|
||||
|
||||
if len(nextKeys) >= 3: # Intersections.
|
||||
return nextKeys
|
||||
|
||||
if len(nextKeys) == 2 or len(nextKeys) == 1: # In line or endpoints.
|
||||
line = []
|
||||
line.append(key)
|
||||
line.insert(0, nextKeys[0])
|
||||
if len(nextKeys) == 2:
|
||||
line.insert(len(line), nextKeys[1])
|
||||
|
||||
nextKeys = line[0], line[-1]
|
||||
|
||||
while len(nextKeys) == 2 or len(nextKeys) == 1:
|
||||
extremity = []
|
||||
for key in nextKeys:
|
||||
nextKeys = self.findNextElements(key)
|
||||
|
||||
if len(nextKeys) <= 2:
|
||||
# Add the neighbors that is not already in the line.
|
||||
for element in nextKeys:
|
||||
if element not in line:
|
||||
extremity.append(element)
|
||||
line.append(element)
|
||||
|
||||
if len(nextKeys) >= 3:
|
||||
# Add the intersection only.
|
||||
extremity.append(key)
|
||||
|
||||
nextKeys = []
|
||||
for key in extremity:
|
||||
ends = self.findNextElements(key)
|
||||
if len(ends) == 2:
|
||||
nextKeys.append(key)
|
||||
return line
|
||||
|
||||
def parseGraph(self):
|
||||
for key, value in sorted(
|
||||
Counter(self.graph.row).items(), key=lambda kv: kv[1], reverse=True
|
||||
):
|
||||
# Start from the biggest intersections.
|
||||
if value != 2: # We don't want to be in the middle of a line.
|
||||
line = self.findLine(key)
|
||||
|
||||
# We have now all the connected points if it's an
|
||||
# intersection. We need to find the line.
|
||||
|
||||
if value != 1:
|
||||
# It's not an endpoint.
|
||||
self.centers.append(key)
|
||||
self.intersections.append(line)
|
||||
for i in line:
|
||||
line = self.findLine(i)
|
||||
|
||||
if i in line:
|
||||
# The key is inside the result : it's a line.
|
||||
alreadyInside = False
|
||||
for l in self.lines:
|
||||
# Verification if not already inside.
|
||||
if Counter(l) == Counter(line):
|
||||
alreadyInside = True
|
||||
# print(line, "inside", lines)
|
||||
|
||||
if alreadyInside == False:
|
||||
self.lines.append(line)
|
||||
else:
|
||||
# The key is not inside the result, it's an
|
||||
# intersection directly connected to the key.
|
||||
line = [key, i]
|
||||
alreadyInside = False
|
||||
for l in self.lines:
|
||||
# Verification if not already inside.
|
||||
if Counter(l) == Counter(line):
|
||||
alreadyInside = True
|
||||
# print(line, "inside", lines)
|
||||
|
||||
if alreadyInside == False:
|
||||
self.lines.append(line)
|
||||
|
||||
def map(self):
|
||||
"""
|
||||
|
||||
Generate an image to visualize 2D path of the skeleton.
|
||||
|
||||
Returns:
|
||||
image: 2D path of the skeleton on top of the heightmap.
|
||||
"""
|
||||
editor = Editor()
|
||||
|
||||
buildArea = editor.getBuildArea()
|
||||
buildRect = buildArea.toRect()
|
||||
xzStart = buildRect.begin
|
||||
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]))
|
||||
|
||||
heightmap = Image.open("data/heightmap.png").convert('RGB')
|
||||
roadsArea = Image.new("L", xzDistance, 0)
|
||||
width, height = heightmap.size
|
||||
|
||||
# Lines
|
||||
for i in range(len(self.lines)):
|
||||
r, g, b = (random.randint(0, 255), random.randint(
|
||||
0, 255), random.randint(0, 255))
|
||||
|
||||
for j in range(len(self.lines[i])):
|
||||
|
||||
z = self.coordinates[self.lines[i][j]][0]
|
||||
y = self.coordinates[self.lines[i][j]][1]
|
||||
x = self.coordinates[self.lines[i][j]][2]
|
||||
|
||||
heightmap.putpixel(
|
||||
(
|
||||
int(z),
|
||||
int(x),
|
||||
),
|
||||
(r + j, g + j, b + j),
|
||||
)
|
||||
|
||||
roadsArea.putpixel(
|
||||
(
|
||||
int(z),
|
||||
int(x),
|
||||
),
|
||||
(255),
|
||||
)
|
||||
|
||||
# Centers
|
||||
for i in range(len(self.centers)):
|
||||
print(self.coordinates[self.centers[i]])
|
||||
heightmap.putpixel(
|
||||
(int(self.coordinates[self.centers[i]][0]), int(
|
||||
self.coordinates[self.centers[i]][2])),
|
||||
(255, 255, 0),
|
||||
)
|
||||
|
||||
roadsArea.putpixel(
|
||||
(int(self.coordinates[self.centers[i]][0]), int(
|
||||
self.coordinates[self.centers[i]][2])),
|
||||
(255),
|
||||
)
|
||||
|
||||
# # Intersections
|
||||
# for i in range(len(self.intersections)):
|
||||
# intersection = []
|
||||
# for j in range(len(self.intersections[i])):
|
||||
# intersection.append(self.coordinates[self.intersections[i][j]])
|
||||
|
||||
# for i in range(len(intersection)):
|
||||
# heightmap.putpixel(
|
||||
# (int(self.intersections[i][2]), int(self.intersections[i][0])),
|
||||
# (255, 0, 255),
|
||||
# )
|
||||
|
||||
return heightmap, roadsArea
|
||||
2005
networks/legacy_roads/house.py
Normal file
2005
networks/legacy_roads/house.py
Normal file
File diff suppressed because it is too large
Load Diff
117
networks/legacy_roads/list_block.py
Normal file
117
networks/legacy_roads/list_block.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from gdpc import Block
|
||||
|
||||
|
||||
air = Block('air')
|
||||
|
||||
stairs_devant = Block("oak_stairs", {"facing": "east"})
|
||||
stairs_derriere = Block("oak_stairs", {"facing": "west"})
|
||||
stairs_droite = Block("oak_stairs", {"facing": "north"})
|
||||
stairs_gauche = Block("oak_stairs", {"facing": "south"})
|
||||
|
||||
stairs_devant_retourner = Block(
|
||||
"oak_stairs", {"facing": "east", "half": "top"})
|
||||
stairs_derriere_retourner = Block(
|
||||
"oak_stairs", {"facing": "west", "half": "top"})
|
||||
stairs_droite_retourner = Block(
|
||||
"oak_stairs", {"facing": "north", "half": "top"})
|
||||
stairs_gauche_retourner = Block(
|
||||
"oak_stairs", {"facing": "south", "half": "top"})
|
||||
|
||||
|
||||
stairs_quartz_devant = Block(
|
||||
"quartz_stairs", {"facing": "east", "half": "top"})
|
||||
stairs_quartz_derriere = Block(
|
||||
"quartz_stairs", {"facing": "west", "half": "top"})
|
||||
stairs_quartz_droite = Block(
|
||||
"quartz_stairs", {"facing": "north", "half": "top"})
|
||||
stairs_quartz_gauche = Block(
|
||||
"quartz_stairs", {"facing": "south", "half": "top"})
|
||||
|
||||
|
||||
door_east = Block("oak_door", {"facing": "east"})
|
||||
|
||||
|
||||
oak_planks = Block("oak_planks")
|
||||
oak_log = Block("oak_log")
|
||||
spruce_wood = Block("spruce_wood")
|
||||
|
||||
|
||||
black_stained_glass = Block("black_stained_glass")
|
||||
|
||||
|
||||
white_concrete_powder = Block("white_concrete_powder")
|
||||
white_concrete = Block("white_concrete")
|
||||
|
||||
grass_block = Block("grass_block")
|
||||
podzol = Block("podzol")
|
||||
|
||||
block_quartz = Block("quartz_block")
|
||||
|
||||
|
||||
block_white_concrete = Block("white_concrete")
|
||||
|
||||
|
||||
oak_slab = Block('oak_slab')
|
||||
quartz_slab_up = Block('quartz_slab', {"type": "top"})
|
||||
|
||||
oak_fence = Block('oak_fence')
|
||||
|
||||
|
||||
style_basique = {
|
||||
'mur': "white_concrete",
|
||||
'sol': "oak_planks",
|
||||
'grass': "grass_block",
|
||||
'chemin': "quartz_block",
|
||||
'fence': 'oak_fence',
|
||||
'toit_esca': 'oak_stairs',
|
||||
'toit_planche': "oak_planks",
|
||||
'toit_slab': 'oak_slab',
|
||||
'glass': "glass",
|
||||
'door': 'oak_door'
|
||||
|
||||
|
||||
}
|
||||
|
||||
style_jungle = {
|
||||
'mur': "light_gray_concrete",
|
||||
'sol': "acacia_planks",
|
||||
'grass': "grass_block",
|
||||
'chemin': "podzol",
|
||||
'fence': 'acacia_fence',
|
||||
'toit_esca': 'acacia_stairs',
|
||||
'toit_planche': "acacia_planks",
|
||||
'toit_slab': 'acacia_slab',
|
||||
'glass': "glass",
|
||||
'door': 'acacia_door'
|
||||
|
||||
|
||||
}
|
||||
style_end = {
|
||||
'mur': "purple_concrete",
|
||||
'sol': "crimson_planks",
|
||||
'grass': "grass_block",
|
||||
'chemin': "amethyst_block",
|
||||
'fence': 'crimson_fence',
|
||||
'toit_esca': 'crimson_stairs',
|
||||
'toit_planche': "crimson_planks",
|
||||
'toit_slab': 'crimson_slab',
|
||||
'glass': "glass",
|
||||
'door': 'crimson_door'
|
||||
|
||||
|
||||
}
|
||||
|
||||
style_birch = {
|
||||
'mur': "yellow_concrete",
|
||||
'sol': "birch_planks",
|
||||
'grass': "grass_block",
|
||||
'chemin': "rooted_dirt",
|
||||
'fence': 'birch_fence',
|
||||
'toit_esca': 'birch_stairs',
|
||||
'toit_planche': "birch_planks",
|
||||
'toit_slab': 'birch_slab',
|
||||
'glass': "glass",
|
||||
'door': 'birch_door'
|
||||
|
||||
|
||||
}
|
||||
1155
networks/legacy_roads/maths.py
Normal file
1155
networks/legacy_roads/maths.py
Normal file
File diff suppressed because it is too large
Load Diff
662
networks/legacy_roads/roads.py
Normal file
662
networks/legacy_roads/roads.py
Normal file
@@ -0,0 +1,662 @@
|
||||
import networks.legacy_roads.Skeleton as Skeleton
|
||||
import networks.legacy_roads.house as house
|
||||
from math import sqrt
|
||||
from gdpc import Editor
|
||||
import sys
|
||||
from gdpc import Block as place
|
||||
import numpy as np
|
||||
import networks.legacy_roads.maths as maths
|
||||
import math
|
||||
|
||||
import networks.legacy_roads.tools as tools
|
||||
|
||||
import random
|
||||
from random import randint
|
||||
|
||||
from PIL import Image
|
||||
from collections import Counter
|
||||
|
||||
alreadyGenerated = []
|
||||
|
||||
|
||||
######################## Lanes materials presets #######################
|
||||
|
||||
|
||||
standard_modern_lane_composition = {
|
||||
"road_surface": {
|
||||
"black_concrete": 3,
|
||||
"coal_block": 1,
|
||||
"black_concrete_powder": 2,
|
||||
},
|
||||
"median_strip": {"stone": 1},
|
||||
"structure": {"stone": 3, "andesite": 1},
|
||||
"central_lines": {"yellow_concrete": 3, "yellow_concrete_powder": 1},
|
||||
"external_lines": {"white_concrete": 3, "white_concrete_powder": 1},
|
||||
"lines": {"white_concrete": 3, "white_concrete_powder": 1},
|
||||
}
|
||||
|
||||
# editor.placeBlock((x, y, z), place("minecraft:white_concrete"))
|
||||
|
||||
######################### Additional functions #########################
|
||||
|
||||
|
||||
def cleanLanes(lanes):
|
||||
cleanLanes = {}
|
||||
for lane in lanes:
|
||||
for xyz in lanes[lane]:
|
||||
if (round(xyz[0]), round(xyz[1]), round(xyz[2]),) not in [
|
||||
cleanLanes[i][j]
|
||||
for __, i in enumerate(cleanLanes)
|
||||
for j in range(len(cleanLanes[i]))
|
||||
]:
|
||||
if cleanLanes.get(lane) == None:
|
||||
cleanLanes[lane] = []
|
||||
cleanLanes[lane].append(
|
||||
(round(xyz[0]), round(xyz[1]), round(xyz[2]))
|
||||
)
|
||||
return cleanLanes
|
||||
|
||||
|
||||
def findGround(xzStart, xz): # TODO: Change error.
|
||||
"""
|
||||
Find the surface at xz using heightmap.
|
||||
|
||||
Args:
|
||||
xzStart (tuple): Starting coordinates of the heightmap (northwest corner).
|
||||
xz (tuple): Coordinates xz in the Minecraft world.
|
||||
|
||||
Returns:
|
||||
tuple: Coordinates xyz in the Minecraft world.
|
||||
"""
|
||||
im = Image.open("./world_maker/data/heightmap.png")
|
||||
x = round(xz[0] - xzStart[0])
|
||||
z = round(xz[-1] - xzStart[-1])
|
||||
# Alpha is defined as the height ([3]).
|
||||
width, height = im.size
|
||||
if x >= width or z >= height:
|
||||
print("img:", x, z)
|
||||
print(width, height)
|
||||
print(xzStart, xz)
|
||||
try:
|
||||
return xz[0], (im.getpixel((x, z))[2]) - 1, xz[-1]
|
||||
except:
|
||||
print("Error getpixel in map.py:42 with ", x, z)
|
||||
return None
|
||||
|
||||
|
||||
############################ Lanes functions ###########################
|
||||
|
||||
housesCoordinates = []
|
||||
|
||||
|
||||
def singleLaneLeft(XYZ, blocks=standard_modern_lane_composition):
|
||||
"""Left side."""
|
||||
|
||||
factor = 8
|
||||
distance = 2
|
||||
|
||||
roadMarkings = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 1,
|
||||
resolution=0,
|
||||
pixelPerfect=True,
|
||||
factor=1,
|
||||
start=2,
|
||||
)
|
||||
roadMarkings = cleanLanes(roadMarkings)
|
||||
|
||||
roadSurface = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=factor,
|
||||
)
|
||||
roadSurface = cleanLanes(roadSurface)
|
||||
|
||||
walkway = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 3,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=4,
|
||||
start=3,
|
||||
)
|
||||
walkway = cleanLanes(walkway)
|
||||
|
||||
houses = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 14,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=1,
|
||||
start=distance + 13,
|
||||
)
|
||||
houses = cleanLanes(houses)
|
||||
|
||||
road_surface = blocks.get("road_surface")
|
||||
structure = blocks.get("structure")
|
||||
|
||||
for lane in roadSurface:
|
||||
for xyz in roadSurface[lane]:
|
||||
tools.fillBlock(
|
||||
"air", (xyz[0], xyz[1], xyz[2], xyz[0], xyz[1] + 4, xyz[2])
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(road_surface.keys()),
|
||||
weights=road_surface.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
xyz,
|
||||
)
|
||||
alreadyGenerated.append((xyz[0], xyz[2]))
|
||||
|
||||
lines = blocks.get("lines")
|
||||
for lane in roadMarkings:
|
||||
for xyz in roadMarkings[lane]:
|
||||
if lane == -1:
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(lines.keys()),
|
||||
weights=lines.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1], xyz[2]),
|
||||
)
|
||||
|
||||
for lane in walkway:
|
||||
for xyz in walkway[lane]:
|
||||
if lane <= -1:
|
||||
counterSegments = 0
|
||||
tools.fillBlock(
|
||||
"air",
|
||||
(xyz[0], xyz[1] + 1, xyz[2], xyz[0], xyz[1] + 4, xyz[2]),
|
||||
)
|
||||
tools.fillBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] + 1, xyz[2], xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
alreadyGenerated.append((xyz[0], xyz[2]))
|
||||
|
||||
counterSegments = 0
|
||||
for lane in houses:
|
||||
for xyz in houses[lane]:
|
||||
if lane <= -1:
|
||||
counterSegments += 1
|
||||
if counterSegments % 10 == 0:
|
||||
housesCoordinates.append((xyz[0], xyz[1], xyz[2]))
|
||||
|
||||
|
||||
def singleLaneRight(XYZ, blocks=standard_modern_lane_composition):
|
||||
"""Right side."""
|
||||
|
||||
factor = 8
|
||||
distance = 2
|
||||
|
||||
roadMarkings = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 1,
|
||||
resolution=0,
|
||||
pixelPerfect=True,
|
||||
factor=1,
|
||||
start=2,
|
||||
)
|
||||
roadMarkings = cleanLanes(roadMarkings)
|
||||
|
||||
roadSurface = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=factor,
|
||||
)
|
||||
roadSurface = cleanLanes(roadSurface)
|
||||
|
||||
walkway = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 3,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=4,
|
||||
start=3,
|
||||
)
|
||||
walkway = cleanLanes(walkway)
|
||||
|
||||
houses = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
distance + 14,
|
||||
resolution=0,
|
||||
pixelPerfect=False,
|
||||
factor=1,
|
||||
start=distance + 13,
|
||||
)
|
||||
houses = cleanLanes(houses)
|
||||
|
||||
road_surface = blocks.get("road_surface")
|
||||
structure = blocks.get("structure")
|
||||
central_lines = blocks.get("central_lines")
|
||||
|
||||
for lane in roadSurface:
|
||||
for xyz in roadSurface[lane]:
|
||||
tools.fillBlock(
|
||||
"air", (xyz[0], xyz[1], xyz[2], xyz[0], xyz[1] + 4, xyz[2])
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(road_surface.keys()),
|
||||
weights=road_surface.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
xyz,
|
||||
)
|
||||
alreadyGenerated.append((xyz[0], xyz[2]))
|
||||
|
||||
lines = blocks.get("lines")
|
||||
counterSegments = 0
|
||||
for lane in roadMarkings:
|
||||
for xyz in roadMarkings[lane]:
|
||||
if lane == 1:
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(lines.keys()),
|
||||
weights=lines.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1], xyz[2]),
|
||||
)
|
||||
|
||||
if lane == -1: # Central Lane.
|
||||
counterSegments += 1
|
||||
if counterSegments % 4 != 0:
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(central_lines.keys()),
|
||||
weights=central_lines.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1], xyz[2]),
|
||||
)
|
||||
else:
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
tools.setBlock(
|
||||
random.choices(
|
||||
list(road_surface.keys()),
|
||||
weights=road_surface.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1], xyz[2]),
|
||||
)
|
||||
|
||||
for lane in walkway:
|
||||
for xyz in walkway[lane]:
|
||||
if lane >= 1:
|
||||
tools.fillBlock(
|
||||
"air",
|
||||
(xyz[0], xyz[1] + 1, xyz[2], xyz[0], xyz[1] + 4, xyz[2]),
|
||||
)
|
||||
tools.fillBlock(
|
||||
random.choices(
|
||||
list(structure.keys()),
|
||||
weights=structure.values(),
|
||||
k=1,
|
||||
)[0],
|
||||
(xyz[0], xyz[1] + 1, xyz[2], xyz[0], xyz[1] - 1, xyz[2]),
|
||||
)
|
||||
alreadyGenerated.append((xyz[0], xyz[2]))
|
||||
|
||||
counterSegments = 0
|
||||
for lane in houses:
|
||||
for xyz in houses[lane]:
|
||||
if lane >= 1:
|
||||
counterSegments += 1
|
||||
if counterSegments % 10 == 0:
|
||||
housesCoordinates.append((xyz[0], xyz[1], xyz[2]))
|
||||
|
||||
|
||||
############################ Roads Generator ###########################
|
||||
|
||||
|
||||
class RoadCurve:
|
||||
def __init__(self, roadData, XYZ):
|
||||
print("road, first input:", XYZ)
|
||||
"""Create points that forms the lanes depending of the roadData."""
|
||||
self.roadData = roadData
|
||||
self.XYZ = XYZ
|
||||
|
||||
# Find the offset, where the lanes is.
|
||||
self.lanesXYZ = {}
|
||||
for __, i in enumerate(self.roadData["lanes"]):
|
||||
laneCenterDistance = self.roadData["lanes"][i]["centerDistance"]
|
||||
self.lanesXYZ[i] = maths.curveSurface(
|
||||
np.array(XYZ),
|
||||
abs(laneCenterDistance),
|
||||
resolution=0,
|
||||
pixelPerfect=True,
|
||||
factor=1,
|
||||
start=abs(laneCenterDistance) - 1,
|
||||
returnLine=False,
|
||||
)
|
||||
# We only take the desired side.
|
||||
if laneCenterDistance == 0:
|
||||
self.lanesXYZ[i] = self.lanesXYZ[i][0]
|
||||
if laneCenterDistance > 0:
|
||||
self.lanesXYZ[i] = self.lanesXYZ[i][1]
|
||||
if laneCenterDistance < 0:
|
||||
self.lanesXYZ[i] = self.lanesXYZ[i][-1]
|
||||
|
||||
def setLanes(self, lanes=[]):
|
||||
"""Generate the lanes depending of the function name."""
|
||||
for __, i in enumerate(self.roadData["lanes"]):
|
||||
if i in lanes or lanes == []:
|
||||
self.roadData["lanes"][i]["type"](np.array(self.lanesXYZ[i]))
|
||||
|
||||
def getLanes(self, lanes=[]):
|
||||
"""Return the points that forms the lanes."""
|
||||
lanesDict = {}
|
||||
for __, i in enumerate(self.roadData["lanes"]):
|
||||
if i in lanes or lanes == []:
|
||||
lanesDict[i] = self.lanesXYZ[i]
|
||||
return lanesDict
|
||||
|
||||
|
||||
############################# Lanes Preset #############################
|
||||
|
||||
|
||||
standard_modern_lane_agencement = {
|
||||
"lanes": {
|
||||
-1: {"type": singleLaneLeft, "centerDistance": -3},
|
||||
1: {"type": singleLaneRight, "centerDistance": 3},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
standard_modern_lanes_agencement = {
|
||||
"mainRoads": {
|
||||
0: {
|
||||
"lanes": {
|
||||
-1: {"type": singleLaneLeft, "centerDistance": -5},
|
||||
0: {"type": singleLaneLeft, "centerDistance": 0},
|
||||
1: {"type": singleLaneRight, "centerDistance": 5},
|
||||
}
|
||||
},
|
||||
1: {
|
||||
"lanes": {
|
||||
-1: {"type": singleLaneRight, "centerDistance": -5},
|
||||
0: {"type": singleLaneRight, "centerDistance": 0},
|
||||
1: {"type": singleLaneRight, "centerDistance": 5},
|
||||
}
|
||||
},
|
||||
},
|
||||
"sideRoads": {
|
||||
0: {
|
||||
"lanes": {
|
||||
-1: {"type": singleLaneLeft, "centerDistance": -5},
|
||||
1: {"type": singleLaneLeft, "centerDistance": 0},
|
||||
2: {"type": singleLaneLeft, "centerDistance": 5},
|
||||
}
|
||||
},
|
||||
1: {
|
||||
"lanes": {
|
||||
-1: {"type": singleLaneLeft, "centerDistance": -5},
|
||||
1: {"type": singleLaneLeft, "centerDistance": 0},
|
||||
2: {"type": singleLaneLeft, "centerDistance": 5},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
######
|
||||
|
||||
|
||||
sys.path.append("Terraformer/mapAnalysis/")
|
||||
|
||||
|
||||
def get_distance(point1, point2):
|
||||
# Calculate the Euclidean distance between two points
|
||||
return sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2 + (point1[2] - point2[2]) ** 2)
|
||||
|
||||
|
||||
def simplify_coordinates(coordinates, epsilon):
|
||||
if len(coordinates) < 3:
|
||||
return coordinates
|
||||
|
||||
# Find the point with the maximum distance
|
||||
max_distance = 0
|
||||
max_index = 0
|
||||
end_index = len(coordinates) - 1
|
||||
|
||||
for i in range(1, end_index):
|
||||
distance = get_distance(coordinates[i], coordinates[0])
|
||||
if distance > max_distance:
|
||||
max_distance = distance
|
||||
max_index = i
|
||||
|
||||
simplified_coordinates = []
|
||||
|
||||
# If the maximum distance is greater than epsilon, recursively simplify
|
||||
if max_distance > epsilon:
|
||||
rec_results1 = simplify_coordinates(coordinates[:max_index+1], epsilon)
|
||||
rec_results2 = simplify_coordinates(coordinates[max_index:], epsilon)
|
||||
|
||||
# Combine the simplified sub-results
|
||||
simplified_coordinates.extend(rec_results1[:-1])
|
||||
simplified_coordinates.extend(rec_results2)
|
||||
else:
|
||||
# The maximum distance is less than epsilon, retain the endpoints
|
||||
simplified_coordinates.append(coordinates[0])
|
||||
simplified_coordinates.append(coordinates[end_index])
|
||||
|
||||
return simplified_coordinates
|
||||
|
||||
|
||||
def irlToMc(coordinates):
|
||||
|
||||
heightmap = Image.open('./world_maker/data/heightmap.png')
|
||||
|
||||
editor = Editor()
|
||||
buildArea = editor.getBuildArea()
|
||||
xMin = (editor.getBuildArea().begin).x
|
||||
yMin = (editor.getBuildArea().begin).y
|
||||
zMin = (editor.getBuildArea().begin).z
|
||||
|
||||
print(xMin, yMin, zMin)
|
||||
|
||||
coordinates_final = []
|
||||
|
||||
coordinates_final.append(coordinates[0] + xMin)
|
||||
coordinates_final.append(heightmap.getpixel(
|
||||
(coordinates[0], coordinates[2]))[0])
|
||||
coordinates_final.append(coordinates[2] + zMin)
|
||||
|
||||
return coordinates_final
|
||||
|
||||
|
||||
def setRoads(skeleton):
|
||||
# Generation
|
||||
for i in range(len(skeleton.lines)):
|
||||
for j in range(len(skeleton.lines[i])):
|
||||
xyz = irlToMc(skeleton.coordinates[skeleton.lines[i][j]])
|
||||
skeleton.lines[i][j] = xyz
|
||||
print(skeleton.lines[i][j])
|
||||
|
||||
# Simplification
|
||||
|
||||
for i in range(len(skeleton.lines)):
|
||||
skeleton.lines[i] = simplify_coordinates(skeleton.lines[i], 10)
|
||||
|
||||
for i in range(len(skeleton.lines)): # HERE --------------------------------------
|
||||
print(skeleton.lines[i])
|
||||
road = RoadCurve(standard_modern_lane_agencement, skeleton.lines[i])
|
||||
road.setLanes()
|
||||
print(road.getLanes(), "LANES ***********")
|
||||
|
||||
rejected = []
|
||||
accepted = []
|
||||
# print(housesCoordinates)
|
||||
for i in range(len(housesCoordinates)):
|
||||
pos = housesCoordinates[i]
|
||||
# print(pos, "pos0")
|
||||
editor = Editor()
|
||||
xMin = (editor.getBuildArea().begin).x
|
||||
yMin = (editor.getBuildArea().begin).y
|
||||
zMin = (editor.getBuildArea().begin).z
|
||||
base = findGround((xMin, zMin), pos)
|
||||
if base != None:
|
||||
# print(pos, "pos1")
|
||||
pos1 = (
|
||||
pos[0] - random.randint(3, 6),
|
||||
base[1],
|
||||
pos[2] - random.randint(3, 6),
|
||||
)
|
||||
pos2 = (
|
||||
pos[0] + random.randint(3, 6),
|
||||
base[1],
|
||||
pos[2] + random.randint(3, 6),
|
||||
)
|
||||
pos3 = (
|
||||
pos1[0],
|
||||
base[1],
|
||||
pos2[2],
|
||||
)
|
||||
pos4 = (
|
||||
pos2[0],
|
||||
base[1],
|
||||
pos1[2],
|
||||
)
|
||||
# print(pos1, pos2, pos3, pos4, "pos")
|
||||
xMin = (editor.getBuildArea().begin).x
|
||||
yMin = (editor.getBuildArea().begin).y
|
||||
zMin = (editor.getBuildArea().begin).z
|
||||
Ypos1 = findGround((xMin, zMin), pos1)
|
||||
Ypos2 = findGround((xMin, zMin), pos2)
|
||||
Ypos3 = findGround((xMin, zMin), pos3)
|
||||
Ypos4 = findGround((xMin, zMin), pos4)
|
||||
|
||||
if (
|
||||
Ypos1 != None
|
||||
and Ypos2 != None
|
||||
and Ypos3 != None
|
||||
and Ypos4 != None
|
||||
):
|
||||
|
||||
pos2 = (
|
||||
pos2[0],
|
||||
max(Ypos1[1], Ypos2[1], base[1], Ypos3[1], Ypos4[1]),
|
||||
pos2[2],
|
||||
)
|
||||
pos1 = (
|
||||
pos1[0],
|
||||
max(Ypos1[1], Ypos2[1], base[1], Ypos3[1], Ypos4[1]),
|
||||
pos1[2],
|
||||
)
|
||||
if (
|
||||
(pos1[0], pos1[2]) not in alreadyGenerated
|
||||
and (
|
||||
pos2[0],
|
||||
pos2[2],
|
||||
)
|
||||
not in alreadyGenerated
|
||||
and (pos1[0], pos2[2]) not in alreadyGenerated
|
||||
and (pos2[0], pos1[2])
|
||||
): # HERE, remove print and find why house gen on self
|
||||
|
||||
for xi in range(
|
||||
-5,
|
||||
(max(pos1[0], pos2[0]) - min(pos1[0], pos2[0])) + 5,
|
||||
):
|
||||
for yi in range(
|
||||
-5,
|
||||
(max(pos1[2], pos2[2]) - min(pos1[2], pos2[2]))
|
||||
+ 5,
|
||||
):
|
||||
alreadyGenerated.append(
|
||||
(
|
||||
min(pos1[0], pos2[0]) + xi,
|
||||
min(pos1[2], pos2[2]) + yi,
|
||||
)
|
||||
)
|
||||
|
||||
nb_style = randint(0, 3)
|
||||
door = ["left", "right"]
|
||||
r2 = random.randint(0, 1)
|
||||
facing = ["south", "north", "east", "west"]
|
||||
r3 = random.randint(0, 3)
|
||||
|
||||
xyz1 = (min(pos1[0], pos2[0]), min(
|
||||
pos1[1], pos2[1]), min(pos1[2], pos2[2]))
|
||||
xyz2 = (max(pos1[0], pos2[0]), max(
|
||||
pos1[1], pos2[1]), max(pos1[2], pos2[2]))
|
||||
|
||||
house.house(xyz1, xyz2, door[r2], 10, nb_style, facing[r3])
|
||||
accepted.append(
|
||||
(
|
||||
pos1[0],
|
||||
pos1[2],
|
||||
pos2[0],
|
||||
pos2[2],
|
||||
)
|
||||
)
|
||||
else:
|
||||
rejected.append(
|
||||
(
|
||||
pos1[0],
|
||||
pos1[2],
|
||||
pos2[0],
|
||||
pos2[2],
|
||||
)
|
||||
)
|
||||
|
||||
print("Done")
|
||||
40
networks/legacy_roads/tools.py
Normal file
40
networks/legacy_roads/tools.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from gdpc import Block as place
|
||||
from gdpc import Editor
|
||||
import networks.legacy_roads.maths as maths
|
||||
|
||||
|
||||
USE_BATCHING = True
|
||||
editor = Editor(buffering=True, caching=True, multithreading=True)
|
||||
|
||||
|
||||
def setBlock(block, xyz):
|
||||
x, y, z = xyz
|
||||
editor.placeBlock((x, y, z), place(block))
|
||||
|
||||
|
||||
def getBlock(xyz):
|
||||
print("You used getBlock in a deprecated manner.")
|
||||
# x, y, z = xyz
|
||||
# return minecraft.getBlock(x, y, z)
|
||||
|
||||
|
||||
def fillBlock(block, xyz):
|
||||
print("fill", xyz)
|
||||
xDistance = max(xyz[0], xyz[3]) - min(xyz[0], xyz[3])
|
||||
yDistance = max(xyz[1], xyz[4]) - min(xyz[1], xyz[4])
|
||||
zDistance = max(xyz[2], xyz[5]) - min(xyz[2], xyz[5])
|
||||
|
||||
coordinates = []
|
||||
|
||||
for i in range(min(xyz[0], xyz[3]), max(xyz[0], xyz[3])+1):
|
||||
for j in range(min(xyz[1], xyz[4]), max(xyz[1], xyz[4])+1):
|
||||
for k in range(min(xyz[2], xyz[5]), max(xyz[2], xyz[5])+1):
|
||||
coordinates.append((i, j, k))
|
||||
|
||||
editor.placeBlock(coordinates, place(block))
|
||||
|
||||
|
||||
def setLine(block, xyz0, xyz1, pixelPerfect=True):
|
||||
points = maths.line(xyz0, xyz1, pixelPerfect)
|
||||
for i in points:
|
||||
setBlock(block, (i[0], i[1], i[2]))
|
||||
Reference in New Issue
Block a user