Exemple #1
0
    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)