Improve construction drawing.

Draw buildings under construction without roof.
This commit is contained in:
Sergey Vartanov 2022-01-23 23:38:20 +03:00
parent f9d9442da3
commit 7fbc7cb96f
3 changed files with 37 additions and 19 deletions

View file

@ -11,7 +11,7 @@ import numpy as np
from colour import Color from colour import Color
from map_machine.color import get_gradient_color from map_machine.color import get_gradient_color
from map_machine.feature.building import Building from map_machine.feature.building import Building, BUILDING_SCALE
from map_machine.feature.crater import Crater from map_machine.feature.crater import Crater
from map_machine.feature.direction import DirectionSector from map_machine.feature.direction import DirectionSector
from map_machine.feature.road import Road, Roads from map_machine.feature.road import Road, Roads
@ -189,7 +189,7 @@ class Constructor:
self.craters: list[Crater] = [] self.craters: list[Crater] = []
self.direction_sectors: list[DirectionSector] = [] self.direction_sectors: list[DirectionSector] = []
self.heights: set[float] = {1.0, 2.0} self.heights: set[float] = {0.25 / BUILDING_SCALE, 0.5 / BUILDING_SCALE}
def add_building(self, building: Building) -> None: def add_building(self, building: Building) -> None:
"""Add building and update levels.""" """Add building and update levels."""

View file

@ -16,8 +16,10 @@ from map_machine.geometry.vector import Segment
from map_machine.osm.osm_reader import OSMNode from map_machine.osm.osm_reader import OSMNode
from map_machine.scheme import Scheme from map_machine.scheme import Scheme
BUILDING_HEIGHT_SCALE: float = 2.5
BUILDING_MINIMAL_HEIGHT: float = 8.0 BUILDING_MINIMAL_HEIGHT: float = 8.0
BUILDING_SCALE: float = 1.0
LEVEL_HEIGHT: float = 2.5
SHADE_SCALE: float = 0.4
class Building(Figure): class Building(Figure):
@ -33,7 +35,10 @@ class Building(Figure):
) -> None: ) -> None:
super().__init__(tags, inners, outers) super().__init__(tags, inners, outers)
self.is_construction: bool = tags.get("building") == "construction" self.is_construction: bool = (
tags.get("building") == "construction"
or tags.get("construction") == "yes"
)
if self.is_construction: if self.is_construction:
self.fill: Color = scheme.get_color("building_construction_color") self.fill: Color = scheme.get_color("building_construction_color")
@ -67,11 +72,11 @@ class Building(Figure):
levels: Optional[str] = self.get_float("building:levels") levels: Optional[str] = self.get_float("building:levels")
if levels: if levels:
self.height = float(levels) * BUILDING_HEIGHT_SCALE self.height = float(levels) * LEVEL_HEIGHT
levels: Optional[str] = self.get_float("building:min_level") levels: Optional[str] = self.get_float("building:min_level")
if levels: if levels:
self.min_height = float(levels) * BUILDING_HEIGHT_SCALE self.min_height = float(levels) * LEVEL_HEIGHT
height: Optional[float] = self.get_length("height") height: Optional[float] = self.get_length("height")
if height: if height:
@ -93,7 +98,7 @@ class Building(Figure):
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 casted by the building."""
scale: float = flinger.get_scale() / 3.0 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))
commands: str = self.get_path(flinger, shift_1) commands: str = self.get_path(flinger, shift_1)
@ -123,17 +128,28 @@ class Building(Figure):
self, svg: Drawing, height: float, previous_height: float, scale: float self, svg: Drawing, height: float, previous_height: float, scale: float
) -> None: ) -> None:
"""Draw building walls.""" """Draw building walls."""
shift_1: np.ndarray = np.array((0.0, -previous_height * scale)) shift_1: np.ndarray = np.array(
shift_2: np.ndarray = np.array((0.0, -height * scale)) (0.0, -previous_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:
fill: Color fill: str
if height <= 1.0: if self.is_construction:
fill = self.wall_bottom_color_1 color_part: float = segment.angle * 0.2
elif height <= 2.0: fill = Color(
fill = self.wall_bottom_color_2 rgb=(
0x84 / 0xFF + color_part,
0x80 / 0xFF + color_part,
0x7C / 0xFF + color_part,
)
).hex
elif height <= 0.25 / BUILDING_SCALE:
fill = self.wall_bottom_color_1.hex
elif height <= 0.5 / BUILDING_SCALE:
fill = self.wall_bottom_color_2.hex
else: else:
color_part: float = self.wall_color_start + segment.angle * 0.2 color_part: float = self.wall_color_start + segment.angle * 0.2
fill = Color(rgb=(color_part, color_part, color_part)) fill = Color(rgb=(color_part, color_part, color_part)).hex
command = ( command = (
"M", "M",
@ -147,8 +163,8 @@ class Building(Figure):
) )
path: Path = svg.path( path: Path = svg.path(
d=command, d=command,
fill=fill.hex, fill=fill,
stroke=fill.hex, stroke=fill,
stroke_width=1, stroke_width=1,
stroke_linejoin="round", stroke_linejoin="round",
) )
@ -157,7 +173,9 @@ class Building(Figure):
def draw_roof(self, svg: Drawing, flinger: Flinger, scale: float) -> None: def draw_roof(self, svg: Drawing, flinger: Flinger, scale: float) -> None:
"""Draw building roof.""" """Draw building roof."""
path: Path = Path( path: Path = Path(
d=self.get_path(flinger, np.array([0.0, -self.height * scale])), d=self.get_path(
flinger, np.array([0.0, -self.height * scale * BUILDING_SCALE])
),
stroke=self.stroke, stroke=self.stroke,
fill="none" if self.is_construction else self.fill, fill="none" if self.is_construction else self.fill,
stroke_linejoin="round", stroke_linejoin="round",

View file

@ -124,7 +124,7 @@ class Map:
logging.info("Drawing buildings...") logging.info("Drawing buildings...")
scale: float = self.flinger.get_scale() / 3.0 scale: float = self.flinger.get_scale()
building_shade: Group = Group(opacity=0.1) building_shade: Group = Group(opacity=0.1)
for building in constructor.buildings: for building in constructor.buildings:
building.draw_shade(building_shade, self.flinger) building.draw_shade(building_shade, self.flinger)