KOSMIndoorMap

mapcssstyle.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "mapcssstyle.h"
8#include "mapcssstyle_p.h"
9#include "mapcssparser.h"
10#include "mapcssresult.h"
11#include "mapcssrule_p.h"
12#include "mapcssstate_p.h"
13#include "mapcsstypes.h"
14
15#include <QDebug>
16#include <QIODevice>
17
18using namespace KOSMIndoorMap;
19
20// NOTE:
21// - only add rules we really need, this has runtime cost
22// - keep value lists alphabetically sorted
23// - follow rules linked on https://wiki.openstreetmap.org/wiki/Area
24static constexpr inline const char* way_rule_highway_values[] = {
25 "platform",
26 "rest_area",
27 "services"
28};
29static constexpr inline const char* way_rule_natural_values[] = {
30 "bare_rock",
31 "bay",
32 "beach",
33 "crevasse",
34 "desert",
35 "fell",
36 "glacier",
37 "grassland",
38 "heath",
39 "landslide",
40 "mud",
41 "reef",
42 "rock",
43 "sand",
44 "scree",
45 "scrub",
46 "shingle",
47 "sinkhole",
48 "stone",
49 "water",
50 "wetland",
51 "wood"
52};
53
54MapCSSStylePrivate::MapCSSStylePrivate()
55 : m_wayTypeRules({
56 { OSM::TagKey{}, "building", MapCSSObjectType::Area, {}},
57 { OSM::TagKey{}, "highway", MapCSSObjectType::Area, std::span<const char* const>{way_rule_highway_values}},
58 { OSM::TagKey{}, "natural", MapCSSObjectType::Area, std::span<const char* const>{way_rule_natural_values}},
59 })
60{
61}
62
64 : d(new MapCSSStylePrivate)
65{}
66
67MapCSSStyle::MapCSSStyle(MapCSSStyle&&) noexcept = default;
68MapCSSStyle::~MapCSSStyle() = default;
69MapCSSStyle& MapCSSStyle::operator=(MapCSSStyle&&) noexcept = default;
70
71bool MapCSSStyle::isEmpty() const
72{
73 return d->m_rules.empty();
74}
75
77{
78 d->m_areaKey = dataSet.tagKey("area");
79 d->m_typeKey = dataSet.tagKey("type");
80
81 for (auto &rule : d->m_wayTypeRules) {
82 rule.tag = dataSet.tagKey(rule.tagName);
83 }
84 std::sort(d->m_wayTypeRules.begin(), d->m_wayTypeRules.end(), [](const auto &lhs, const auto &rhs) { return lhs.tag < rhs.tag; });
85
86 for (const auto &rule : d->m_rules) {
87 rule->compile(dataSet);
88 }
89}
90
91void MapCSSStyle::initializeState(MapCSSState &state) const
92{
93 // determine object type of the input element
94 // This involves tag lookups (and thus cost), but as long as there is at least
95 // one area and one line selector for each zoom level this is break-even. In practice
96 // there are actually many more than that, which means this is a useful optimization
97 // over doing this in MapCSSBasicSelector after checking for the zoom level
98 switch (state.element.type()) {
99 case OSM::Type::Null:
100 Q_UNREACHABLE();
101 case OSM::Type::Node:
102 state.objectType = MapCSSObjectType::Node;
103 break;
104 case OSM::Type::Way:
105 {
106 if (!state.element.way()->isClosed()) {
107 state.objectType = MapCSSObjectType::Line;
108 break;
109 }
110 const auto area = state.element.tagValue(d->m_areaKey);
111 if (area == "yes") {
112 state.objectType = MapCSSObjectType::Area;
113 } else if (!area.isEmpty()) {
114 state.objectType = MapCSSObjectType::Line;
115 } else {
116 state.objectType = MapCSSObjectType::LineOrArea;
117 for (const auto &tag : state.element.way()->tags) {
118 auto it = std::lower_bound(d->m_wayTypeRules.begin(), d->m_wayTypeRules.end(), tag.key, [](const auto &rule, const auto &key) {
119 return rule.tag < key;
120 });
121 if (it != d->m_wayTypeRules.end() && (*it).tag == tag.key) {
122 if ((*it).values.empty()) {
123 state.objectType = (*it).type;
124 } else {
125 if (std::binary_search((*it).values.begin(), (*it).values.end(), tag.value)) {
126 state.objectType = (*it).type;
127 } else {
128 state.objectType = (*it).type == MapCSSObjectType::Line ? MapCSSObjectType::Area :MapCSSObjectType::Line;
129 }
130 }
131 break;
132 }
133 }
134 }
135 break;
136 }
137 case OSM::Type::Relation:
138 state.objectType = state.element.tagValue(d->m_typeKey) == "multipolygon" ? MapCSSObjectType::Area : MapCSSObjectType::Relation;
139 break;
140 }
141}
142
143void MapCSSStyle::evaluate(const MapCSSState &state, MapCSSResult &result) const
144{
145 result.clear();
146
147 for (const auto &rule : d->m_rules) {
148 rule->evaluate(state, result);
149 }
150}
151
152void MapCSSStyle::evaluateCanvas(const MapCSSState &state, MapCSSResult &result) const
153{
154 result.clear();
155 for (const auto &rule : d->m_rules) {
156 rule->evaluateCanvas(state, result);
157 }
158}
159
161{
162 for (const auto &rule : d->m_rules) {
163 rule->write(out);
164 }
165}
166
167ClassSelectorKey MapCSSStyle::classKey(const char *className) const
168{
169 return d->m_classSelectorRegistry.key(className);
170}
171
172LayerSelectorKey MapCSSStyle::layerKey(const char *layerName) const
173{
174 return d->m_layerSelectorRegistry.key(layerName);
175}
Result of MapCSS stylesheet evaluation for all layer selectors.
void clear()
Reset result state from a previous evaluation, while retaining previously allocated resource for reus...
A parsed MapCSS style sheet.
Definition mapcssstyle.h:33
void evaluate(const MapCSSState &state, MapCSSResult &result) const
Evaluates the style sheet for a given state state (OSM element, view state, element state,...
MapCSSStyle()
Creates an invalid/empty style.
void write(QIODevice *out) const
Write this style as MapCSS to out.
LayerSelectorKey layerKey(const char *layerName) const
Look up a layer selector key for the given name, if it exists.
ClassSelectorKey classKey(const char *className) const
Look up a class selector key for the given name, if it exists.
void compile(OSM::DataSet &dataSet)
Optimizes style sheet rules for application against dataSet.
void initializeState(MapCSSState &state) const
Initializes the evaluation state.
void evaluateCanvas(const MapCSSState &state, MapCSSResult &result) const
Evaluate canvas style rules.
A set of nodes, ways and relations.
Definition datatypes.h:346
TagKey tagKey(const char *keyName) const
Look up a tag key for the given tag name, if it exists.
Definition datatypes.cpp:38
A key of an OSM tag.
Definition datatypes.h:179
OSM-based multi-floor indoor maps for buildings.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:11:15 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.