Support color for icon shape.
* Create icon shape specification with color. * Change icon generation rules. * Add height label processing.
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 93 KiB |
BIN
doc/grid.png
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
BIN
doc/power.png
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 145 KiB |
|
@ -19,7 +19,8 @@ from roentgen.osm_reader import (
|
|||
Map, OSMMember, OSMNode, OSMRelation, OSMWay, Tagged
|
||||
)
|
||||
from roentgen.point import Point
|
||||
from roentgen.scheme import Icon, LineStyle, Scheme
|
||||
from roentgen.scheme import Icon, LineStyle, Scheme, ShapeSpecification, \
|
||||
DEFAULT_COLOR
|
||||
from roentgen.util import MinMax
|
||||
|
||||
DEBUG: bool = False
|
||||
|
@ -445,34 +446,35 @@ class Constructor:
|
|||
continue
|
||||
|
||||
priority: int
|
||||
icon_set: Icon
|
||||
icon: Icon
|
||||
draw_outline: bool = True
|
||||
|
||||
if self.mode in ["time", "user-coloring"]:
|
||||
if not tags:
|
||||
continue
|
||||
color = DEFAULT_COLOR
|
||||
if self.mode == "user-coloring":
|
||||
color = get_user_color(node.user, self.seed)
|
||||
if self.mode == "time":
|
||||
color = get_time_color(node.timestamp, self.map_.time)
|
||||
dot, _ = self.icon_extractor.get_path(DEFAULT_SMALL_SHAPE_ID)
|
||||
icon_set = Icon([dot], [], color, set(), True)
|
||||
icon = Icon([ShapeSpecification(dot, color)], [], set())
|
||||
priority = 0
|
||||
draw_outline = False
|
||||
labels = []
|
||||
else:
|
||||
icon_set, priority = self.scheme.get_icon(
|
||||
icon, priority = self.scheme.get_icon(
|
||||
self.icon_extractor, tags
|
||||
)
|
||||
labels = self.scheme.construct_text(tags, True)
|
||||
|
||||
self.nodes.append(Point(
|
||||
icon_set, labels, tags, flung, node.coordinates,
|
||||
icon, labels, tags, flung, node.coordinates,
|
||||
priority=priority, draw_outline=draw_outline
|
||||
))
|
||||
|
||||
missing_tags.update(
|
||||
f"{key}: {tags[key]}" for key in tags
|
||||
if key not in icon_set.processed)
|
||||
if key not in icon.processed)
|
||||
|
||||
ui.progress_bar(-1, len(self.map_.node_map), text="Constructing nodes")
|
||||
|
|
|
@ -11,7 +11,7 @@ from colour import Color
|
|||
from svgwrite import Drawing
|
||||
|
||||
from roentgen.icon import IconExtractor, Shape
|
||||
from roentgen.scheme import Scheme
|
||||
from roentgen.scheme import Scheme, ShapeSpecification
|
||||
|
||||
|
||||
def draw_all_icons(
|
||||
|
@ -35,9 +35,18 @@ def draw_all_icons(
|
|||
|
||||
to_draw: List[Set[str]] = []
|
||||
|
||||
icons_file_name: str = "icons/icons.svg"
|
||||
extractor: IconExtractor = IconExtractor(icons_file_name)
|
||||
|
||||
for element in scheme.icons: # type: Dict[str, Any]
|
||||
if "icon" in element and set(element["icon"]) not in to_draw:
|
||||
to_draw.append(set(element["icon"]))
|
||||
if "icon" in element:
|
||||
specifications = [
|
||||
ShapeSpecification.from_structure(x, extractor, scheme)
|
||||
for x in element["icon"]
|
||||
]
|
||||
ids = set(x.shape.id_ for x in specifications)
|
||||
if ids not in to_draw:
|
||||
to_draw.append(ids)
|
||||
if "add_icon" in element and set(element["add_icon"]) not in to_draw:
|
||||
to_draw.append(set(element["add_icon"]))
|
||||
if "over_icon" not in element:
|
||||
|
@ -65,16 +74,13 @@ def draw_all_icons(
|
|||
current_set not in to_draw):
|
||||
to_draw.append(current_set)
|
||||
|
||||
icons_file_name: str = "icons/icons.svg"
|
||||
extractor: IconExtractor = IconExtractor(icons_file_name)
|
||||
|
||||
specified_ids: Set[str] = set()
|
||||
|
||||
for icons_to_draw in to_draw: # type: List[str]
|
||||
specified_ids |= icons_to_draw
|
||||
print(
|
||||
"Icons with no tag specification: \n " +
|
||||
", ".join(sorted(extractor.icons.keys() - specified_ids)) + "."
|
||||
", ".join(sorted(extractor.shapes.keys() - specified_ids)) + "."
|
||||
)
|
||||
|
||||
draw_grid(
|
||||
|
|
|
@ -5,12 +5,10 @@ Author: Sergey Vartanov (me@enzet.ru).
|
|||
"""
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Dict, Optional
|
||||
from xml.dom.minidom import Document, Element, Node, parse
|
||||
|
||||
import numpy as np
|
||||
import svgwrite
|
||||
from colour import Color
|
||||
from svgwrite import Drawing
|
||||
|
||||
from roentgen import ui
|
||||
|
@ -55,56 +53,6 @@ class Shape:
|
|||
d=self.path, transform=f"translate({shift[0]},{shift[1]})"
|
||||
)
|
||||
|
||||
def draw(
|
||||
self, svg: svgwrite.Drawing, point: np.array, color: Color,
|
||||
opacity: float = 1.0, tags: Dict[str, Any] = None, outline: bool = False
|
||||
) -> None:
|
||||
"""
|
||||
Draw icon shape into SVG file.
|
||||
|
||||
:param svg: output SVG file
|
||||
:param point: 2D position of the icon centre
|
||||
:param color: fill color
|
||||
:param opacity: icon opacity
|
||||
:param tags: tags to be displayed as hint
|
||||
:param outline: draw outline for the icon
|
||||
"""
|
||||
point = np.array(list(map(int, point)))
|
||||
|
||||
path: svgwrite.path.Path = self.get_path(svg, point)
|
||||
path.update({"fill": color.hex})
|
||||
if outline:
|
||||
opacity: float = 0.5
|
||||
|
||||
path.update({
|
||||
"fill": color.hex,
|
||||
"stroke": color.hex,
|
||||
"stroke-width": 2.2,
|
||||
"stroke-linejoin": "round",
|
||||
})
|
||||
if opacity != 1.0:
|
||||
path.update({"opacity": opacity})
|
||||
if tags:
|
||||
title: str = "\n".join(map(lambda x: x + ": " + tags[x], tags))
|
||||
path.set_desc(title=title)
|
||||
svg.add(path)
|
||||
|
||||
|
||||
def is_standard(id_: str):
|
||||
"""
|
||||
Check whether SVG object ID is standard Inkscape ID.
|
||||
"""
|
||||
matcher = re.match(STANDARD_INKSCAPE_ID, id_)
|
||||
return matcher is not None
|
||||
if id_ == "base":
|
||||
return True
|
||||
for prefix in [
|
||||
]:
|
||||
matcher = re.match(prefix + "\\d+", id_)
|
||||
if matcher:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class IconExtractor:
|
||||
"""
|
||||
|
@ -118,10 +66,10 @@ class IconExtractor:
|
|||
:param svg_file_name: input SVG file name with icons. File may contain
|
||||
any other irrelevant graphics.
|
||||
"""
|
||||
self.icons: Dict[str, Shape] = {}
|
||||
self.shapes: Dict[str, Shape] = {}
|
||||
|
||||
with open(svg_file_name) as input_file:
|
||||
content = parse(input_file) # type: Document
|
||||
content: Document = parse(input_file)
|
||||
for element in content.childNodes: # type: Element
|
||||
if element.nodeName != "svg":
|
||||
continue
|
||||
|
@ -145,7 +93,7 @@ class IconExtractor:
|
|||
return
|
||||
|
||||
id_: str = node.getAttribute("id")
|
||||
if is_standard(id_):
|
||||
if re.match(STANDARD_INKSCAPE_ID, id_) is not None:
|
||||
return
|
||||
|
||||
if node.hasAttribute("d"):
|
||||
|
@ -172,7 +120,7 @@ class IconExtractor:
|
|||
name = child_node.childNodes[0].nodeValue
|
||||
break
|
||||
|
||||
self.icons[id_] = Shape(path, point, id_, name)
|
||||
self.shapes[id_] = Shape(path, point, id_, name)
|
||||
else:
|
||||
ui.error(f"not standard ID {id_}")
|
||||
|
||||
|
@ -182,8 +130,8 @@ class IconExtractor:
|
|||
|
||||
:param id_: string icon identifier
|
||||
"""
|
||||
if id_ in self.icons:
|
||||
return self.icons[id_], True
|
||||
if id_ in self.shapes:
|
||||
return self.shapes[id_], True
|
||||
|
||||
ui.error(f"no such icon ID {id_}")
|
||||
return self.icons[DEFAULT_SHAPE_ID], False
|
||||
ui.error(f"no such shape ID {id_}")
|
||||
return self.shapes[DEFAULT_SHAPE_ID], False
|
||||
|
|
|
@ -7,7 +7,7 @@ from colour import Color
|
|||
from roentgen.color import is_bright
|
||||
from roentgen.icon import Shape
|
||||
from roentgen.osm_reader import Tagged
|
||||
from roentgen.scheme import Icon
|
||||
from roentgen.scheme import Icon, ShapeSpecification
|
||||
from roentgen.text import Label
|
||||
|
||||
DEFAULT_FONT: str = "Roboto"
|
||||
|
@ -71,17 +71,17 @@ class Point(Tagged):
|
|||
Draw main shape for one node.
|
||||
"""
|
||||
if (
|
||||
self.icon.main_icon and
|
||||
(not self.icon.main_icon[0].is_default() or
|
||||
self.is_for_node)
|
||||
self.icon.main_icon[0].is_default() and
|
||||
not self.icon.extra_icons
|
||||
):
|
||||
position = self.point + np.array((0, self.y))
|
||||
self.main_icon_painted: bool = self.draw_point_shape(
|
||||
svg, self.icon.main_icon,
|
||||
position, self.icon.color, occupied,
|
||||
tags=self.tags)
|
||||
if self.main_icon_painted:
|
||||
self.y += 16
|
||||
return
|
||||
|
||||
position = self.point + np.array((0, self.y))
|
||||
self.main_icon_painted: bool = self.draw_point_shape(
|
||||
svg, self.icon.main_icon, position, occupied, tags=self.tags
|
||||
)
|
||||
if self.main_icon_painted:
|
||||
self.y += 16
|
||||
|
||||
def draw_extra_shapes(
|
||||
self, svg: svgwrite.Drawing, occupied: Optional[Occupied] = None
|
||||
|
@ -108,14 +108,14 @@ class Point(Tagged):
|
|||
for shape_ids in self.icon.extra_icons:
|
||||
self.draw_point_shape(
|
||||
svg, shape_ids, self.point + np.array((left, self.y)),
|
||||
Color("#888888"), occupied)
|
||||
occupied=occupied)
|
||||
left += 16
|
||||
if self.icon.extra_icons:
|
||||
self.y += 16
|
||||
|
||||
def draw_point_shape(
|
||||
self, svg: svgwrite.Drawing, shapes: List[Shape], position,
|
||||
fill: Color, occupied, tags: Optional[Dict[str, str]] = None
|
||||
self, svg: svgwrite.Drawing, shapes: List[ShapeSpecification], position,
|
||||
occupied, tags: Optional[Dict[str, str]] = None
|
||||
) -> bool:
|
||||
"""
|
||||
Draw one combined icon and its outline.
|
||||
|
@ -129,16 +129,13 @@ class Point(Tagged):
|
|||
# Draw outlines.
|
||||
|
||||
if self.draw_outline:
|
||||
for icon in shapes: # type: Shape
|
||||
bright: bool = is_bright(fill)
|
||||
color: Color = Color("black") if bright else Color("white")
|
||||
opacity: float = 0.7 if bright else 0.5
|
||||
icon.draw(svg, position, color, opacity=opacity, outline=True)
|
||||
for shape in shapes:
|
||||
shape.draw(svg, position, outline=True)
|
||||
|
||||
# Draw icons.
|
||||
|
||||
for icon in shapes: # type: Shape
|
||||
icon.draw(svg, position, fill, tags=tags)
|
||||
for shape in shapes: # type: ShapeSpecification
|
||||
shape.draw(svg, position, tags=tags)
|
||||
|
||||
if occupied:
|
||||
overlap: int = occupied.overlap
|
||||
|
|
|
@ -3,32 +3,102 @@ Röntgen drawing scheme.
|
|||
|
||||
Author: Sergey Vartanov (me@enzet.ru).
|
||||
"""
|
||||
import copy
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
||||
|
||||
import numpy as np
|
||||
import svgwrite
|
||||
import yaml
|
||||
from colour import Color
|
||||
|
||||
from roentgen.color import is_bright
|
||||
from roentgen.icon import DEFAULT_SHAPE_ID, IconExtractor, Shape
|
||||
from roentgen.text import Label, get_address, get_text
|
||||
|
||||
DEFAULT_COLOR: Color = Color("#444444")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ShapeSpecification:
|
||||
"""
|
||||
Specification for shape as a part of an icon.
|
||||
"""
|
||||
|
||||
shape: Shape
|
||||
color: Color = DEFAULT_COLOR
|
||||
|
||||
@classmethod
|
||||
def from_structure(
|
||||
cls, structure: Any, extractor: IconExtractor, scheme: "Scheme",
|
||||
color: Color = DEFAULT_COLOR
|
||||
) -> "ShapeSpecification":
|
||||
"""
|
||||
Parse shape specification from structure.
|
||||
"""
|
||||
shape: Shape
|
||||
shape, _ = extractor.get_path(DEFAULT_SHAPE_ID)
|
||||
color: Color = color
|
||||
if isinstance(structure, str):
|
||||
shape, _ = extractor.get_path(structure)
|
||||
elif isinstance(structure, dict):
|
||||
if "shape" in structure:
|
||||
shape, _ = extractor.get_path(structure["shape"])
|
||||
if "color" in structure:
|
||||
color = scheme.get_color(structure["color"])
|
||||
return cls(shape, color)
|
||||
|
||||
def is_default(self) -> bool:
|
||||
"""
|
||||
Check whether shape is default.
|
||||
"""
|
||||
return self.shape.id_ == DEFAULT_SHAPE_ID
|
||||
|
||||
def draw(
|
||||
self, svg: svgwrite.Drawing, point: np.array,
|
||||
tags: Dict[str, Any] = None, outline: bool = False
|
||||
) -> None:
|
||||
"""
|
||||
Draw icon shape into SVG file.
|
||||
|
||||
:param svg: output SVG file
|
||||
:param point: 2D position of the icon centre
|
||||
:param opacity: icon opacity
|
||||
:param tags: tags to be displayed as hint
|
||||
:param outline: draw outline for the icon
|
||||
"""
|
||||
point = np.array(list(map(int, point)))
|
||||
|
||||
path: svgwrite.path.Path = self.shape.get_path(svg, point)
|
||||
path.update({"fill": self.color.hex})
|
||||
if outline:
|
||||
bright: bool = is_bright(self.color)
|
||||
color: Color = Color("black") if bright else Color("white")
|
||||
opacity: float = 0.7 if bright else 0.5
|
||||
|
||||
path.update({
|
||||
"fill": color.hex,
|
||||
"stroke": color.hex,
|
||||
"stroke-width": 2.2,
|
||||
"stroke-linejoin": "round",
|
||||
"opacity": opacity,
|
||||
})
|
||||
if tags:
|
||||
title: str = "\n".join(map(lambda x: x + ": " + tags[x], tags))
|
||||
path.set_desc(title=title)
|
||||
svg.add(path)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Icon:
|
||||
"""
|
||||
Node representation: icons and color.
|
||||
"""
|
||||
main_icon: List[Shape] # list of icons
|
||||
extra_icons: List[List[Shape]] # list of lists of icons
|
||||
color: Color # fill color of all icons
|
||||
main_icon: List[ShapeSpecification] # list of shapes
|
||||
extra_icons: List[List[ShapeSpecification]] # list of lists of shapes
|
||||
# tag keys that were processed to create icon set (other
|
||||
# tag keys should be displayed by text or ignored)
|
||||
processed: Set[str]
|
||||
is_default: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -148,9 +218,7 @@ class Scheme:
|
|||
try:
|
||||
return Color(color)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return DEFAULT_COLOR
|
||||
return DEFAULT_COLOR
|
||||
|
||||
def is_no_drawable(self, key: str) -> bool:
|
||||
"""
|
||||
|
@ -199,72 +267,79 @@ class Scheme:
|
|||
if tags_hash in self.cache:
|
||||
return self.cache[tags_hash]
|
||||
|
||||
main_icon_id: Optional[List[str]] = None
|
||||
extra_icon_ids: List[List[str]] = []
|
||||
main_icon: List[ShapeSpecification] = []
|
||||
extra_icons: List[List[ShapeSpecification]] = []
|
||||
processed: Set[str] = set()
|
||||
fill: Color = DEFAULT_COLOR
|
||||
priority: int = 0
|
||||
|
||||
for index, matcher in enumerate(self.icons):
|
||||
# type: (int, Dict[str, Any])
|
||||
index: int
|
||||
matcher: Dict[str, Any]
|
||||
matched: bool = is_matched(matcher, tags)
|
||||
matcher_tags: Set[str] = matcher["tags"].keys()
|
||||
if not matched:
|
||||
continue
|
||||
priority = len(self.icons) - index
|
||||
if "draw" in matcher and not matcher["draw"]:
|
||||
processed |= set(matcher["tags"].keys())
|
||||
processed |= set(matcher_tags)
|
||||
if "icon" in matcher:
|
||||
main_icon_id = copy.deepcopy(matcher["icon"])
|
||||
processed |= set(matcher["tags"].keys())
|
||||
main_icon = [
|
||||
ShapeSpecification.from_structure(x, icon_extractor, self)
|
||||
for x in matcher["icon"]
|
||||
]
|
||||
processed |= set(matcher_tags)
|
||||
if "over_icon" in matcher:
|
||||
if main_icon_id: # TODO: check main icon in under icons
|
||||
main_icon_id += matcher["over_icon"]
|
||||
for key in matcher["tags"].keys():
|
||||
if main_icon:
|
||||
main_icon += [
|
||||
ShapeSpecification.from_structure(
|
||||
x, icon_extractor, self
|
||||
)
|
||||
for x in matcher["over_icon"]
|
||||
]
|
||||
for key in matcher_tags:
|
||||
processed.add(key)
|
||||
if "add_icon" in matcher:
|
||||
extra_icon_ids += [matcher["add_icon"]]
|
||||
for key in matcher["tags"].keys():
|
||||
extra_icons += [[
|
||||
ShapeSpecification.from_structure(
|
||||
x, icon_extractor, self, Color("#888888")
|
||||
)
|
||||
for x in matcher["add_icon"]
|
||||
]]
|
||||
for key in matcher_tags:
|
||||
processed.add(key)
|
||||
if "color" in matcher:
|
||||
fill = self.get_color(matcher["color"])
|
||||
for key in matcher["tags"].keys():
|
||||
processed.add(key)
|
||||
assert False
|
||||
if "set_main_color" in matcher:
|
||||
for shape in main_icon:
|
||||
shape.color = self.get_color(matcher["set_main_color"])
|
||||
|
||||
color: Optional[Color] = None
|
||||
|
||||
for tag_key in tags: # type: str
|
||||
if (tag_key.endswith(":color") or
|
||||
tag_key.endswith(":colour")):
|
||||
fill = self.get_color(tags[tag_key])
|
||||
color = self.get_color(tags[tag_key])
|
||||
processed.add(tag_key)
|
||||
|
||||
for tag_key in tags: # type: str
|
||||
if tag_key in ["color", "colour"]:
|
||||
fill = self.get_color(tags[tag_key])
|
||||
color = self.get_color(tags[tag_key])
|
||||
processed.add(tag_key)
|
||||
|
||||
keys_left = list(filter(
|
||||
lambda x: x not in processed and
|
||||
not self.is_no_drawable(x), tags.keys()
|
||||
))
|
||||
if color:
|
||||
for shape_specification in main_icon:
|
||||
shape_specification.color = color
|
||||
|
||||
is_default: bool = False
|
||||
if not main_icon_id and not extra_icon_ids and keys_left:
|
||||
main_icon_id = [DEFAULT_SHAPE_ID]
|
||||
is_default = True
|
||||
keys_left = [
|
||||
x for x in tags.keys()
|
||||
if x not in processed and not self.is_no_drawable(x)
|
||||
]
|
||||
|
||||
main_icon: List[Shape] = []
|
||||
if main_icon_id:
|
||||
main_icon = list(map(
|
||||
lambda x: icon_extractor.get_path(x)[0], main_icon_id
|
||||
))
|
||||
default_shape, _ = icon_extractor.get_path(DEFAULT_SHAPE_ID)
|
||||
if not main_icon:
|
||||
main_icon = [ShapeSpecification(default_shape)]
|
||||
|
||||
extra_icons: List[List[Shape]] = []
|
||||
for icon_id in extra_icon_ids:
|
||||
extra_icons.append(list(map(
|
||||
lambda x: icon_extractor.get_path(x)[0], icon_id)))
|
||||
|
||||
returned: Icon = Icon(
|
||||
main_icon, extra_icons, fill, processed, is_default
|
||||
)
|
||||
returned: Icon = Icon(main_icon, extra_icons, processed)
|
||||
self.cache[tags_hash] = returned, priority
|
||||
|
||||
return returned, priority
|
||||
|
@ -283,8 +358,9 @@ class Scheme:
|
|||
priority = element["priority"]
|
||||
for key in element: # type: str
|
||||
if key not in [
|
||||
"tags", "no_tags", "priority", "level", "icon",
|
||||
"r", "r1", "r2"]:
|
||||
"tags", "no_tags", "priority", "level", "icon", "r", "r1",
|
||||
"r2"
|
||||
]:
|
||||
value = element[key]
|
||||
if isinstance(value, str) and value.endswith("_color"):
|
||||
value = self.get_color(value)
|
||||
|
@ -374,6 +450,9 @@ class Scheme:
|
|||
if k in tags:
|
||||
texts.append(Label(tags[k], Color("#444444")))
|
||||
tags.pop(k)
|
||||
if "height" in tags:
|
||||
texts.append(Label(f"↕ {tags['height']} m"))
|
||||
tags.pop("height")
|
||||
for tag in tags:
|
||||
if self.is_writable(tag):
|
||||
texts.append(Label(tags[tag]))
|
||||
|
|
|
@ -141,31 +141,24 @@ node_icons:
|
|||
icon: [electricity]
|
||||
# plant=*
|
||||
- tags: {plant: christmas_trees}
|
||||
icon: [christmas_tree]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: christmas_tree, color: orchard_border_color}]
|
||||
# produce=*
|
||||
- tags: {produce: apple}
|
||||
icon: [apple]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: apple, color: orchard_border_color}]
|
||||
- tags: {produce: christmas_trees}
|
||||
icon: [christmas_tree]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: christmas_tree, color: orchard_border_color}]
|
||||
- tags: {produce: pear}
|
||||
icon: [pear]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: pear, color: orchard_border_color}]
|
||||
# trees=*
|
||||
- tags: {trees: apple_trees}
|
||||
icon: [apple]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: apple, color: orchard_border_color}]
|
||||
- tags: {trees: pear_trees}
|
||||
icon: [pear]
|
||||
color: orchard_border_color
|
||||
icon: [{shape: pear, color: orchard_border_color}]
|
||||
|
||||
# Bigger objects
|
||||
|
||||
- tags: {waterway: waterfall}
|
||||
icon: [waterfall]
|
||||
color: water_border_color
|
||||
icon: [{shape: waterfall, color: water_border_color}]
|
||||
- tags: {natural: cliff}
|
||||
icon: [cliff]
|
||||
- tags: {natural: peak}
|
||||
|
@ -361,19 +354,15 @@ node_icons:
|
|||
# Emergency
|
||||
|
||||
- tags: {emergency: defibrillator}
|
||||
icon: [defibrillator]
|
||||
color: emergency_color
|
||||
icon: [{shape: defibrillator, color: emergency_color}]
|
||||
- tags: {emergency: fire_extinguisher}
|
||||
icon: [fire_extinguisher]
|
||||
color: emergency_color
|
||||
icon: [{shape: fire_extinguisher, color: emergency_color}]
|
||||
- tags: {emergency: fire_hydrant}
|
||||
icon: [fire_hydrant]
|
||||
- tags: {emergency: life_ring}
|
||||
icon: [life_ring]
|
||||
color: emergency_color
|
||||
icon: [{shape: life_ring, color: emergency_color}]
|
||||
- tags: {emergency: phone}
|
||||
icon: [sos_phone]
|
||||
color: emergency_color
|
||||
icon: [{shape: sos_phone, color: emergency_color}]
|
||||
|
||||
# Transport-important middle objects
|
||||
|
||||
|
@ -628,8 +617,7 @@ node_icons:
|
|||
- tags: {amenity: clock}
|
||||
icon: [clock]
|
||||
- tags: {amenity: fountain}
|
||||
icon: [fountain]
|
||||
color: water_border_color
|
||||
icon: [{shape: fountain, color: water_border_color}]
|
||||
- tags: {amenity: waste_basket}
|
||||
icon: [waste_basket]
|
||||
- tags: {highway: street_lamp}
|
||||
|
@ -666,50 +654,38 @@ node_icons:
|
|||
icon: [lowered_kerb]
|
||||
# Trees
|
||||
- tags: {natural: tree}
|
||||
icon: [tree]
|
||||
color: tree_color
|
||||
icon: [{shape: tree, color: tree_color}]
|
||||
- tags: {leaf_type: broadleaved}
|
||||
icon: [tree_with_leaf]
|
||||
color: tree_color
|
||||
icon: [{shape: tree_with_leaf, color: tree_color}]
|
||||
- tags: {leaf_type: needleleaved}
|
||||
icon: [needleleaved_tree]
|
||||
color: tree_color
|
||||
icon: [{shape: needleleaved_tree, color: tree_color}]
|
||||
- tags: {leaf_type: palm}
|
||||
icon: [palm]
|
||||
color: tree_color
|
||||
icon: [{shape: palm, color: tree_color}]
|
||||
- tags: {natural: tree, leaf_type: broadleaved}
|
||||
icon: [tree_with_leaf]
|
||||
color: tree_color
|
||||
icon: [{shape: tree_with_leaf, color: tree_color}]
|
||||
- tags: {natural: tree, leaf_type: needleleaved}
|
||||
icon: [needleleaved_tree]
|
||||
color: tree_color
|
||||
icon: [{shape: needleleaved_tree, color: tree_color}]
|
||||
- tags: {natural: tree, leaf_type: palm}
|
||||
icon: [palm]
|
||||
color: tree_color
|
||||
icon: [{shape: palm, color: tree_color}]
|
||||
- tags: {natural: tree, type: conifer}
|
||||
icon: [needleleaved_tree]
|
||||
color: tree_color
|
||||
icon: [{shape: needleleaved_tree, color: tree_color}]
|
||||
- tags: {leaf_cycle: deciduous}
|
||||
color: decidious_color
|
||||
set_main_color: decidious_color
|
||||
- tags: {leaf_cycle: evergreen}
|
||||
color: evergreen_color
|
||||
set_main_color: evergreen_color
|
||||
- tags: {natural: tree, leaf_cycle: deciduous}
|
||||
color: decidious_color
|
||||
set_main_color: decidious_color
|
||||
- tags: {natural: tree, leaf_cycle: evergreen}
|
||||
color: evergreen_color
|
||||
set_main_color: evergreen_color
|
||||
- tags: {natural: bush}
|
||||
icon: [bush]
|
||||
color: tree_color
|
||||
icon: [{shape: bush, color: tree_color}]
|
||||
# Tree genus
|
||||
- tags: {natural: tree, genus: Betula}
|
||||
icon: [betula]
|
||||
color: tree_color
|
||||
icon: [{shape: betula, color: tree_color}]
|
||||
- tags: {natural: tree, "genus:en": Birch}
|
||||
icon: [betula]
|
||||
color: tree_color
|
||||
icon: [{shape: betula, color: tree_color}]
|
||||
- tags: {natural: tree, "genus:ru": Берёза}
|
||||
icon: [betula]
|
||||
color: tree_color
|
||||
icon: [{shape: betula, color: tree_color}]
|
||||
|
||||
- tags: {railway: buffer_stop}
|
||||
icon: [buffer_stop]
|
||||
|
|