mirror of
https://github.com/enzet/map-machine.git
synced 2025-04-30 10:47:29 +02:00
Make building colors configurable.
It is now possible to draw building colors with `--building-colors` option. Map Machine will use roof colors in flat building mode and roof and wall colors in isometric building mode.
This commit is contained in:
parent
55a6698e05
commit
d3c18a3d5f
2 changed files with 98 additions and 47 deletions
|
@ -38,19 +38,26 @@ class Building(Figure):
|
||||||
)
|
)
|
||||||
self.has_walls: bool = tags.get("building") != "roof"
|
self.has_walls: bool = tags.get("building") != "roof"
|
||||||
|
|
||||||
|
self.default_fill: Color
|
||||||
|
self.default_stroke: Color
|
||||||
if self.is_construction:
|
if self.is_construction:
|
||||||
self.fill: Color = scheme.get_color("building_construction_color")
|
self.default_fill = scheme.get_color("building_construction_color")
|
||||||
self.stroke: Color = scheme.get_color(
|
self.default_stroke = scheme.get_color(
|
||||||
"building_construction_border_color"
|
"building_construction_border_color"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if color := tags.get("roof:colour"):
|
self.default_fill = scheme.get_color("building_color")
|
||||||
self.fill = scheme.get_color(color)
|
self.default_stroke = scheme.get_color("building_border_color")
|
||||||
self.stroke: Color = Color(self.fill)
|
|
||||||
self.stroke.set_luminance(self.fill.get_luminance() * 0.85)
|
self.fill: Color
|
||||||
else:
|
self.stroke: Color
|
||||||
self.fill: Color = scheme.get_color("building_color")
|
if color := tags.get("roof:colour"):
|
||||||
self.stroke: Color = scheme.get_color("building_border_color")
|
self.fill = scheme.get_color(color)
|
||||||
|
self.stroke = Color(self.fill)
|
||||||
|
self.stroke.set_luminance(self.fill.get_luminance() * 0.85)
|
||||||
|
else:
|
||||||
|
self.fill = scheme.get_color("building_color")
|
||||||
|
self.stroke = scheme.get_color("building_border_color")
|
||||||
|
|
||||||
self.parts: list[Segment] = []
|
self.parts: list[Segment] = []
|
||||||
|
|
||||||
|
@ -65,31 +72,23 @@ class Building(Figure):
|
||||||
self.height: float = BUILDING_MINIMAL_HEIGHT
|
self.height: float = BUILDING_MINIMAL_HEIGHT
|
||||||
self.min_height: float = 0.0
|
self.min_height: float = 0.0
|
||||||
|
|
||||||
self.wall_color: Color
|
self.wall_default_color: Color
|
||||||
if self.is_construction:
|
if self.is_construction:
|
||||||
self.wall_color = scheme.get_color("wall_construction_color")
|
self.wall_default_color = scheme.get_color(
|
||||||
|
"wall_construction_color"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.wall_color = scheme.get_color("wall_color")
|
self.wall_default_color = scheme.get_color("wall_color")
|
||||||
|
|
||||||
|
self.wall_color: Color = self.wall_default_color
|
||||||
if material := tags.get("building:material"):
|
if material := tags.get("building:material"):
|
||||||
if material in scheme.material_colors:
|
if material in scheme.material_colors:
|
||||||
self.wall_color = Color(scheme.material_colors[material])
|
self.wall_color = Color(scheme.material_colors[material])
|
||||||
|
|
||||||
if color := tags.get("building:colour"):
|
if color := tags.get("building:colour"):
|
||||||
self.wall_color = scheme.get_color(color)
|
self.wall_color = scheme.get_color(color)
|
||||||
|
|
||||||
if color := tags.get("colour"):
|
if color := tags.get("colour"):
|
||||||
self.wall_color = scheme.get_color(color)
|
self.wall_color = scheme.get_color(color)
|
||||||
|
|
||||||
self.wall_bottom_color_1: Color = Color(self.wall_color)
|
|
||||||
self.wall_bottom_color_1.set_luminance(
|
|
||||||
self.wall_color.get_luminance() * 0.70
|
|
||||||
)
|
|
||||||
self.wall_bottom_color_2: Color = Color(self.wall_color)
|
|
||||||
self.wall_bottom_color_2.set_luminance(
|
|
||||||
self.wall_color.get_luminance() * 0.85
|
|
||||||
)
|
|
||||||
|
|
||||||
if levels := self.get_float("building:levels"):
|
if levels := self.get_float("building:levels"):
|
||||||
self.height = BUILDING_MINIMAL_HEIGHT + levels * LEVEL_HEIGHT
|
self.height = BUILDING_MINIMAL_HEIGHT + levels * LEVEL_HEIGHT
|
||||||
|
|
||||||
|
@ -102,18 +101,24 @@ class Building(Figure):
|
||||||
if height := self.get_length("min_height"):
|
if height := self.get_length("min_height"):
|
||||||
self.min_height = BUILDING_MINIMAL_HEIGHT + height
|
self.min_height = BUILDING_MINIMAL_HEIGHT + height
|
||||||
|
|
||||||
def draw(self, svg: Drawing, flinger: Flinger) -> None:
|
def draw(
|
||||||
|
self, svg: Drawing, flinger: Flinger, use_building_colors: bool
|
||||||
|
) -> None:
|
||||||
"""Draw simple building shape."""
|
"""Draw simple building shape."""
|
||||||
path: Path = Path(
|
path: Path = Path(
|
||||||
d=self.get_path(flinger),
|
d=self.get_path(flinger),
|
||||||
stroke=self.stroke.hex,
|
stroke=self.stroke.hex
|
||||||
fill=self.fill.hex,
|
if use_building_colors
|
||||||
|
else self.default_stroke.hex,
|
||||||
|
fill=self.fill.hex
|
||||||
|
if use_building_colors
|
||||||
|
else self.default_fill.hex,
|
||||||
stroke_linejoin="round",
|
stroke_linejoin="round",
|
||||||
)
|
)
|
||||||
svg.add(path)
|
svg.add(path)
|
||||||
|
|
||||||
def draw_shade(self, building_shade: Group, flinger: Flinger) -> None:
|
def draw_shade(self, building_shade: Group, flinger: Flinger) -> None:
|
||||||
"""Draw shade casted by the building."""
|
"""Draw shade cast by the building."""
|
||||||
scale: float = flinger.get_scale() * SHADE_SCALE
|
scale: float = flinger.get_scale() * SHADE_SCALE
|
||||||
shift_1: np.ndarray = np.array((scale * self.min_height, 0.0))
|
shift_1: np.ndarray = np.array((scale * self.min_height, 0.0))
|
||||||
shift_2: np.ndarray = np.array((scale * self.height, 0.0))
|
shift_2: np.ndarray = np.array((scale * self.height, 0.0))
|
||||||
|
@ -141,7 +146,12 @@ class Building(Figure):
|
||||||
building_shade.add(path)
|
building_shade.add(path)
|
||||||
|
|
||||||
def draw_walls(
|
def draw_walls(
|
||||||
self, svg: Drawing, height: float, previous_height: float, scale: float
|
self,
|
||||||
|
svg: Drawing,
|
||||||
|
height: float,
|
||||||
|
previous_height: float,
|
||||||
|
scale: float,
|
||||||
|
use_building_colors: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Draw building walls."""
|
"""Draw building walls."""
|
||||||
if not self.has_walls:
|
if not self.has_walls:
|
||||||
|
@ -153,16 +163,36 @@ class Building(Figure):
|
||||||
shift_2: np.ndarray = np.array((0.0, -height * scale * BUILDING_SCALE))
|
shift_2: np.ndarray = np.array((0.0, -height * scale * BUILDING_SCALE))
|
||||||
|
|
||||||
for segment in self.parts:
|
for segment in self.parts:
|
||||||
draw_walls(svg, self, segment, height, shift_1, shift_2)
|
draw_walls(
|
||||||
|
svg,
|
||||||
|
self,
|
||||||
|
segment,
|
||||||
|
height,
|
||||||
|
shift_1,
|
||||||
|
shift_2,
|
||||||
|
use_building_colors,
|
||||||
|
)
|
||||||
|
|
||||||
def draw_roof(self, svg: Drawing, flinger: Flinger, scale: float) -> None:
|
def draw_roof(
|
||||||
|
self,
|
||||||
|
svg: Drawing,
|
||||||
|
flinger: Flinger,
|
||||||
|
scale: float,
|
||||||
|
use_building_colors: bool,
|
||||||
|
) -> None:
|
||||||
"""Draw building roof."""
|
"""Draw building roof."""
|
||||||
|
|
||||||
|
fill: Color = self.fill if use_building_colors else self.default_fill
|
||||||
|
stroke: Color = (
|
||||||
|
self.stroke if use_building_colors else self.default_stroke
|
||||||
|
)
|
||||||
|
|
||||||
path: Path = Path(
|
path: Path = Path(
|
||||||
d=self.get_path(
|
d=self.get_path(
|
||||||
flinger, np.array([0.0, -self.height * scale * BUILDING_SCALE])
|
flinger, np.array([0.0, -self.height * scale * BUILDING_SCALE])
|
||||||
),
|
),
|
||||||
stroke=self.stroke,
|
stroke=stroke,
|
||||||
fill="none" if self.is_construction else self.fill.hex,
|
fill="none" if self.is_construction else fill.hex,
|
||||||
stroke_linejoin="round",
|
stroke_linejoin="round",
|
||||||
)
|
)
|
||||||
svg.add(path)
|
svg.add(path)
|
||||||
|
@ -175,33 +205,42 @@ def draw_walls(
|
||||||
height: float,
|
height: float,
|
||||||
shift_1: np.ndarray,
|
shift_1: np.ndarray,
|
||||||
shift_2: np.ndarray,
|
shift_2: np.ndarray,
|
||||||
):
|
use_building_colors: bool,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Draw walls for buildings as a quadrangle.
|
Draw walls for buildings as a quadrangle.
|
||||||
|
|
||||||
Color of the wall is based on illumination.
|
Color of the wall is based on illumination.
|
||||||
"""
|
"""
|
||||||
|
color: Color = (
|
||||||
|
building.wall_color
|
||||||
|
if use_building_colors
|
||||||
|
else building.wall_default_color
|
||||||
|
)
|
||||||
|
|
||||||
color: Color
|
color: Color
|
||||||
if building.is_construction:
|
if building.is_construction:
|
||||||
color_part: float = segment.angle * 0.2
|
color_part: float = segment.angle * 0.2
|
||||||
color = Color(
|
color = Color(
|
||||||
rgb=(
|
rgb=(
|
||||||
building.wall_color.get_red() + color_part,
|
color.get_red() + color_part,
|
||||||
building.wall_color.get_green() + color_part,
|
color.get_green() + color_part,
|
||||||
building.wall_color.get_blue() + color_part,
|
color.get_blue() + color_part,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif height <= 0.25 / BUILDING_SCALE:
|
elif height <= 0.25 / BUILDING_SCALE:
|
||||||
color = building.wall_bottom_color_1
|
color = Color(color)
|
||||||
|
color.set_luminance(color.get_luminance() * 0.70)
|
||||||
elif height <= 0.5 / BUILDING_SCALE:
|
elif height <= 0.5 / BUILDING_SCALE:
|
||||||
color = building.wall_bottom_color_2
|
color = Color(color)
|
||||||
|
color.set_luminance(color.get_luminance() * 0.85)
|
||||||
else:
|
else:
|
||||||
color_part: float = segment.angle * 0.2 - 0.1
|
color_part: float = segment.angle * 0.2 - 0.1
|
||||||
color = Color(
|
color = Color(
|
||||||
rgb=(
|
rgb=(
|
||||||
max(min(building.wall_color.get_red() + color_part, 1), 0),
|
max(min(color.get_red() + color_part, 1), 0),
|
||||||
max(min(building.wall_color.get_green() + color_part, 1), 0),
|
max(min(color.get_green() + color_part, 1), 0),
|
||||||
max(min(building.wall_color.get_blue() + color_part, 1), 0),
|
max(min(color.get_blue() + color_part, 1), 0),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class Map:
|
||||||
for crater in constructor.craters:
|
for crater in constructor.craters:
|
||||||
crater.draw(self.svg, self.flinger)
|
crater.draw(self.svg, self.flinger)
|
||||||
|
|
||||||
self.draw_buildings(constructor)
|
self.draw_buildings(constructor, self.configuration.use_building_colors)
|
||||||
|
|
||||||
for direction_sector in constructor.direction_sectors:
|
for direction_sector in constructor.direction_sectors:
|
||||||
direction_sector.draw(self.svg, self.scheme)
|
direction_sector.draw(self.svg, self.scheme)
|
||||||
|
@ -133,16 +133,18 @@ class Map:
|
||||||
if self.configuration.show_credit:
|
if self.configuration.show_credit:
|
||||||
self.draw_credits(constructor.flinger.size)
|
self.draw_credits(constructor.flinger.size)
|
||||||
|
|
||||||
def draw_buildings(self, constructor: Constructor) -> None:
|
def draw_buildings(
|
||||||
|
self, constructor: Constructor, use_building_colors: bool
|
||||||
|
) -> None:
|
||||||
"""Draw buildings: shade, walls, and roof."""
|
"""Draw buildings: shade, walls, and roof."""
|
||||||
if self.configuration.building_mode == BuildingMode.NO:
|
if self.configuration.building_mode == BuildingMode.NO:
|
||||||
return
|
return
|
||||||
if self.configuration.building_mode == BuildingMode.FLAT:
|
if self.configuration.building_mode == BuildingMode.FLAT:
|
||||||
for building in constructor.buildings:
|
for building in constructor.buildings:
|
||||||
building.draw(self.svg, self.flinger)
|
building.draw(self.svg, self.flinger, use_building_colors)
|
||||||
return
|
return
|
||||||
|
|
||||||
logging.info("Drawing buildings...")
|
logging.info("Drawing isometric buildings...")
|
||||||
|
|
||||||
scale: float = self.flinger.get_scale()
|
scale: float = self.flinger.get_scale()
|
||||||
building_shade: Group = Group(opacity=0.1)
|
building_shade: Group = Group(opacity=0.1)
|
||||||
|
@ -171,12 +173,22 @@ class Map:
|
||||||
if building.height < height or building.min_height >= height:
|
if building.height < height or building.min_height >= height:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
draw_walls(self.svg, building, wall, height, shift_1, shift_2)
|
draw_walls(
|
||||||
|
self.svg,
|
||||||
|
building,
|
||||||
|
wall,
|
||||||
|
height,
|
||||||
|
shift_1,
|
||||||
|
shift_2,
|
||||||
|
use_building_colors,
|
||||||
|
)
|
||||||
|
|
||||||
if self.configuration.draw_roofs:
|
if self.configuration.draw_roofs:
|
||||||
for building in constructor.buildings:
|
for building in constructor.buildings:
|
||||||
if building.height == height:
|
if building.height == height:
|
||||||
building.draw_roof(self.svg, self.flinger, scale)
|
building.draw_roof(
|
||||||
|
self.svg, self.flinger, scale, use_building_colors
|
||||||
|
)
|
||||||
|
|
||||||
previous_height = height
|
previous_height = height
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue