Changeset View
Changeset View
Standalone View
Standalone View
src/plugins/runner/osm/OsmWay.cpp
Show All 12 Lines | |||||
13 | #include <GeoDataPlacemark.h> | 13 | #include <GeoDataPlacemark.h> | ||
14 | #include <GeoDataLineStyle.h> | 14 | #include <GeoDataLineStyle.h> | ||
15 | #include <GeoDataPolyStyle.h> | 15 | #include <GeoDataPolyStyle.h> | ||
16 | #include <GeoDataStyle.h> | 16 | #include <GeoDataStyle.h> | ||
17 | #include <GeoDataDocument.h> | 17 | #include <GeoDataDocument.h> | ||
18 | #include <osm/OsmObjectManager.h> | 18 | #include <osm/OsmObjectManager.h> | ||
19 | #include <MarbleDirs.h> | 19 | #include <MarbleDirs.h> | ||
20 | #include <StyleBuilder.h> | 20 | #include <StyleBuilder.h> | ||
21 | #include <GeoDataMultiGeometry.h> | ||||
21 | 22 | | |||
22 | namespace Marble { | 23 | namespace Marble { | ||
23 | 24 | | |||
24 | QSet<StyleBuilder::OsmTag> OsmWay::s_areaTags; | 25 | QSet<StyleBuilder::OsmTag> OsmWay::s_areaTags; | ||
26 | QSet<StyleBuilder::OsmTag> OsmWay::s_buildingTags; | ||||
25 | 27 | | |||
26 | GeoDataPlacemark *OsmWay::create(const OsmNodes &nodes, QSet<qint64> &usedNodes) const | 28 | GeoDataPlacemark *OsmWay::create(const OsmNodes &nodes, QSet<qint64> &usedNodes) const | ||
27 | { | 29 | { | ||
28 | OsmPlacemarkData osmData = m_osmData; | 30 | OsmPlacemarkData osmData = m_osmData; | ||
29 | GeoDataGeometry *geometry = 0; | 31 | GeoDataGeometry *geometry = 0; | ||
30 | 32 | | |||
31 | if (isArea()) { | 33 | if (isArea()) { | ||
32 | GeoDataLinearRing linearRing; | 34 | GeoDataLinearRing linearRing; | ||
33 | linearRing.reserve(m_references.size()); | 35 | linearRing.reserve(m_references.size()); | ||
34 | bool const stripLastNode = m_references.first() == m_references.last(); | 36 | bool const stripLastNode = m_references.first() == m_references.last(); | ||
35 | for (int i=0, n=m_references.size() - (stripLastNode ? 1 : 0); i<n; ++i) { | 37 | for (int i=0, n=m_references.size() - (stripLastNode ? 1 : 0); i<n; ++i) { | ||
36 | qint64 nodeId = m_references[i]; | 38 | qint64 nodeId = m_references[i]; | ||
37 | auto const nodeIter = nodes.constFind(nodeId); | 39 | auto const nodeIter = nodes.constFind(nodeId); | ||
38 | if (nodeIter == nodes.constEnd()) { | 40 | if (nodeIter == nodes.constEnd()) { | ||
39 | return nullptr; | 41 | return nullptr; | ||
40 | } | 42 | } | ||
41 | 43 | | |||
42 | OsmNode const & node = nodeIter.value(); | 44 | OsmNode const & node = nodeIter.value(); | ||
43 | osmData.addNodeReference(node.coordinates(), node.osmData()); | 45 | osmData.addNodeReference(node.coordinates(), node.osmData()); | ||
44 | linearRing.append(node.coordinates()); | 46 | linearRing.append(node.coordinates()); | ||
45 | usedNodes << nodeId; | 47 | usedNodes << nodeId; | ||
46 | } | 48 | } | ||
47 | 49 | | |||
50 | if (isBuilding()) { | ||||
51 | GeoDataBuilding building; | ||||
52 | building.setName(extractBuildingName()); | ||||
53 | building.setHeight(extractBuildingHeight()); | ||||
54 | building.setEntries(extractNamedEntries()); | ||||
55 | building.multiGeometry()->append(new GeoDataLinearRing(linearRing.optimized())); | ||||
56 | | ||||
57 | geometry = new GeoDataBuilding(building); | ||||
58 | } else { | ||||
48 | geometry = new GeoDataLinearRing(linearRing.optimized()); | 59 | geometry = new GeoDataLinearRing(linearRing.optimized()); | ||
60 | } | ||||
49 | } else { | 61 | } else { | ||
50 | GeoDataLineString lineString; | 62 | GeoDataLineString lineString; | ||
51 | lineString.reserve(m_references.size()); | 63 | lineString.reserve(m_references.size()); | ||
52 | 64 | | |||
53 | for(auto nodeId: m_references) { | 65 | for(auto nodeId: m_references) { | ||
54 | auto const nodeIter = nodes.constFind(nodeId); | 66 | auto const nodeIter = nodes.constFind(nodeId); | ||
55 | if (nodeIter == nodes.constEnd()) { | 67 | if (nodeIter == nodes.constEnd()) { | ||
56 | return nullptr; | 68 | return nullptr; | ||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Line(s) | 155 | if (s_areaTags.isEmpty()) { | |||
184 | 196 | | |||
185 | s_areaTags.insert(StyleBuilder::OsmTag(QStringLiteral("marble_land"), QStringLiteral("landmass"))); | 197 | s_areaTags.insert(StyleBuilder::OsmTag(QStringLiteral("marble_land"), QStringLiteral("landmass"))); | ||
186 | s_areaTags.insert(StyleBuilder::OsmTag(QStringLiteral("settlement"), QStringLiteral("yes"))); | 198 | s_areaTags.insert(StyleBuilder::OsmTag(QStringLiteral("settlement"), QStringLiteral("yes"))); | ||
187 | } | 199 | } | ||
188 | 200 | | |||
189 | return s_areaTags.contains(keyValue); | 201 | return s_areaTags.contains(keyValue); | ||
190 | } | 202 | } | ||
191 | 203 | | |||
204 | bool OsmWay::isBuilding() const | ||||
205 | { | ||||
206 | for (auto iter = m_osmData.tagsBegin(), end=m_osmData.tagsEnd(); iter != end; ++iter) { | ||||
207 | const auto tag = StyleBuilder::OsmTag(iter.key(), iter.value()); | ||||
208 | if (isBuildingTag(tag)) { | ||||
209 | return true; | ||||
210 | } | ||||
211 | } | ||||
212 | | ||||
213 | return false; | ||||
214 | } | ||||
215 | | ||||
216 | bool OsmWay::isBuildingTag(const StyleBuilder::OsmTag &keyValue) | ||||
217 | { | ||||
218 | if (s_buildingTags.isEmpty()) { | ||||
219 | for (auto const & tag: StyleBuilder::buildingTags()) { | ||||
220 | s_buildingTags.insert(tag); | ||||
221 | } | ||||
222 | } | ||||
223 | | ||||
224 | return s_buildingTags.contains(keyValue); | ||||
225 | } | ||||
226 | | ||||
227 | QString OsmWay::extractBuildingName() const | ||||
228 | { | ||||
229 | auto tagIter = m_osmData.findTag(QStringLiteral("addr:housename")); | ||||
230 | if (tagIter != m_osmData.tagsEnd()) { | ||||
231 | return tagIter.value(); | ||||
232 | } | ||||
233 | | ||||
234 | tagIter = m_osmData.findTag(QStringLiteral("addr:housenumber")); | ||||
235 | if (tagIter != m_osmData.tagsEnd()) { | ||||
236 | return tagIter.value(); | ||||
237 | } | ||||
238 | | ||||
239 | return QString(); | ||||
240 | } | ||||
241 | | ||||
242 | double OsmWay::extractBuildingHeight() const | ||||
243 | { | ||||
244 | double height = 8.0; | ||||
245 | | ||||
246 | QHash<QString, QString>::const_iterator tagIter; | ||||
247 | if ((tagIter = m_osmData.findTag(QStringLiteral("height"))) != m_osmData.tagsEnd()) { | ||||
248 | height = GeoDataBuilding::parseBuildingHeight(tagIter.value()); | ||||
249 | } else if ((tagIter = m_osmData.findTag(QStringLiteral("building:levels"))) != m_osmData.tagsEnd()) { | ||||
250 | int const levels = tagIter.value().toInt(); | ||||
251 | int const skipLevels = m_osmData.tagValue(QStringLiteral("building:min_level")).toInt(); | ||||
252 | /** @todo Is 35 as an upper bound for the number of levels sane? */ | ||||
253 | height = 3.0 * qBound(1, 1+levels-skipLevels, 35); | ||||
254 | } | ||||
255 | | ||||
256 | return qBound(1.0, height, 1000.0); | ||||
257 | } | ||||
258 | | ||||
259 | QVector<GeoDataBuilding::NamedEntry> OsmWay::extractNamedEntries() const | ||||
260 | { | ||||
261 | QVector<GeoDataBuilding::NamedEntry> entries; | ||||
262 | | ||||
263 | const auto end = m_osmData.nodeReferencesEnd(); | ||||
264 | for (auto iter = m_osmData.nodeReferencesBegin(); iter != end; ++iter) { | ||||
265 | const auto tagIter = iter.value().findTag(QStringLiteral("addr:housenumber")); | ||||
266 | if (tagIter != iter.value().tagsEnd()) { | ||||
267 | GeoDataBuilding::NamedEntry entry; | ||||
268 | entry.point = iter.key(); | ||||
269 | entry.label = tagIter.value(); | ||||
270 | entries.push_back(entry); | ||||
271 | } | ||||
272 | } | ||||
273 | | ||||
274 | return entries; | ||||
275 | } | ||||
276 | | ||||
192 | } | 277 | } |