def draw(self, constructor: Constructor): """ Draw map. """ ways = sorted(constructor.figures, key=lambda x: x.line_style.priority) ways_length: int = len(ways) for index, way in enumerate(ways): # type: Figure ui.progress_bar(index, ways_length, step=10, text="Drawing ways") path_commands: str = way.get_path(self.flinger) if path_commands: path = Path(d=path_commands) path.update(way.line_style.style) self.svg.add(path) ui.progress_bar(-1, 0, text="Drawing ways") # Trees for node in constructor.nodes: if not (node.get_tag("natural") == "tree" and ("diameter_crown" in node.tags or "circumference" in node.tags)): continue if "circumference" in node.tags: if "diameter_crown" in node.tags: opacity = 0.7 radius = float(node.tags["diameter_crown"]) / 2 else: opacity = 0.3 radius = 2 self.svg.add( self.svg.circle( node.point, radius * self.flinger.get_scale(node.coordinates), fill=self.scheme.get_color("evergreen_color"), opacity=opacity)) self.svg.add( self.svg.circle(node.point, float(node.tags["circumference"]) / 2 / np.pi * self.flinger.get_scale(node.coordinates), fill="#B89A74")) # Draw building shade. building_shade: Group = Group(opacity=0.1) length: float = self.flinger.get_scale() for way in constructor.buildings: # type: Building shift = np.array((length * way.get_levels(), 0)) for nodes11 in way.inners + way.outers: for i in range(len(nodes11) - 1): # type: int flung_1 = self.flinger.fling(nodes11[i].coordinates) flung_2 = self.flinger.fling(nodes11[i + 1].coordinates) building_shade.add( Path(("M", flung_1, "L", flung_2, np.add( flung_2, shift), np.add(flung_1, shift), "Z"), fill="#000000", stroke="#000000", stroke_width=1)) self.svg.add(building_shade) # Draw buildings. previous_level: float = 0 level_height: float = self.flinger.get_scale() level_count: int = len(constructor.levels) for index, level in enumerate(sorted(constructor.levels)): ui.progress_bar(index, level_count, step=1, text="Drawing buildings") fill: Color() for way in constructor.buildings: # type: Building if way.get_levels() < level: continue shift_1 = [0, -previous_level * level_height] shift_2 = [0, -level * level_height] for segment in way.parts: # type: Segment if level == 0.5: fill = Color("#AAAAAA") elif level == 1: fill = Color("#C3C3C3") else: color_part: float = 0.8 + segment.angle * 0.2 fill = Color(rgb=(color_part, color_part, color_part)) self.svg.add( self.svg.path(d=("M", segment.point_1 + shift_1, "L", segment.point_2 + shift_1, segment.point_2 + shift_2, segment.point_1 + shift_2, segment.point_1 + shift_1, "Z"), fill=fill.hex, stroke=fill.hex, stroke_width=1, stroke_linejoin="round")) # Draw building roofs. for way in constructor.buildings: # type: Building if way.get_levels() == level: shift = np.array([0, -way.get_levels() * level_height]) path_commands: str = way.get_path(self.flinger, shift) path = Path(d=path_commands, opacity=1) path.update(way.line_style.style) path.update({"stroke-linejoin": "round"}) self.svg.add(path) previous_level = level ui.progress_bar(-1, level_count, step=1, text="Drawing buildings") # Directions for node in constructor.nodes: # type: Point angle = None is_revert_gradient: bool = False if node.get_tag("man_made") == "surveillance": direction = node.get_tag("camera:direction") if "camera:angle" in node.tags: angle = float(node.get_tag("camera:angle")) if "angle" in node.tags: angle = float(node.get_tag("angle")) direction_radius: float = ( 25 * self.flinger.get_scale(node.coordinates)) direction_color: Color = ( self.scheme.get_color("direction_camera_color")) elif node.get_tag("traffic_sign") == "stop": direction = node.get_tag("direction") direction_radius: float = ( 25 * self.flinger.get_scale(node.coordinates)) direction_color: Color = Color("red") else: direction = node.get_tag("direction") direction_radius: float = ( 50 * self.flinger.get_scale(node.coordinates)) direction_color: Color = ( self.scheme.get_color("direction_view_color")) is_revert_gradient = True if not direction: continue point = (node.point.astype(int)).astype(float) if angle: paths = [ Sector(direction, angle).draw(point, direction_radius) ] else: paths = DirectionSet(direction).draw(point, direction_radius) for path in paths: gradient = self.svg.defs.add( self.svg.radialGradient(center=point, r=direction_radius, gradientUnits="userSpaceOnUse")) if is_revert_gradient: gradient \ .add_stop_color(0, direction_color.hex, opacity=0) \ .add_stop_color(1, direction_color.hex, opacity=0.7) else: gradient \ .add_stop_color(0, direction_color.hex, opacity=0.4) \ .add_stop_color(1, direction_color.hex, opacity=0) self.svg.add( self.svg.path(d=["M", point] + path + ["L", point, "Z"], fill=gradient.get_paint_server())) # All other points if self.overlap == 0: occupied = None else: occupied = Occupied(self.flinger.size[0], self.flinger.size[1], self.overlap) nodes = sorted(constructor.nodes, key=lambda x: -x.priority) for index, node in enumerate(nodes): # type: int, Point if (node.get_tag("natural") == "tree" and ("diameter_crown" in node.tags or "circumference" in node.tags)): continue ui.progress_bar(index, len(nodes), step=10, text="Drawing nodes") node.draw_shapes(self.svg, occupied) ui.progress_bar(-1, len(nodes), step=10, text="Drawing nodes") if self.draw_captions == "no": return for node in nodes: # type: Point if self.mode not in [CREATION_TIME_MODE, AUTHOR_MODE]: node.draw_texts(self.svg, self.scheme, occupied, self.draw_captions)