Changeset View
Changeset View
Standalone View
Standalone View
src/plugins/runner/osm/OsmWay.cpp
Context not available. | |||||
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 | { | ||
Context not available. | |||||
45 | usedNodes << nodeId; | 47 | usedNodes << nodeId; | ||
46 | } | 48 | } | ||
47 | 49 | | |||
48 | geometry = new GeoDataLinearRing(linearRing.optimized()); | 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 { | ||||
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()); | ||
Context not available. | |||||
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 | if (tagIter.value().contains(QChar('m')) || | ||||
249 | tagIter.value().contains(QStringLiteral("meter")) || | ||||
250 | tagIter.value().contains(QStringLiteral("meters")) || | ||||
251 | tagIter.value().contains(QStringLiteral("metre")) || | ||||
252 | tagIter.value().contains(QStringLiteral("metres"))) { | ||||
253 | QString const heightValue = QString(tagIter.value()).remove(QChar('m')) | ||||
254 | .remove(QStringLiteral("meters")).remove(QStringLiteral("meter")) | ||||
255 | .remove(QStringLiteral("metre")).remove(QStringLiteral("metres")).trimmed(); | ||||
256 | bool extracted = false; | ||||
257 | double extractedHeight = heightValue.toDouble(&extracted); | ||||
258 | if (extracted) { | ||||
259 | height = extractedHeight; | ||||
260 | } | ||||
261 | } else { | ||||
262 | double extractedHeight = 0.0; // in inches | ||||
263 | if (tagIter.value().contains(QChar('\''))) { | ||||
264 | double heightInches = 0.0; | ||||
265 | QStringList const feetInches = tagIter.value().split(QChar('\'')); | ||||
266 | bool okFeet; | ||||
267 | double feet = feetInches[0].trimmed().toDouble(&okFeet); | ||||
268 | if (okFeet) { | ||||
269 | heightInches = feet * 12.0; | ||||
270 | } | ||||
271 | if (!feetInches[1].isEmpty()) { // has inches as unit as well | ||||
272 | bool okInches; | ||||
273 | double inches = QString(feetInches[1]).remove(QChar('\"')).trimmed().toDouble(&okInches); | ||||
274 | if (okInches) { | ||||
275 | heightInches += inches; | ||||
276 | } | ||||
277 | } | ||||
278 | extractedHeight = heightInches; | ||||
279 | } else if (tagIter.value().contains(QStringLiteral("feet"))) { | ||||
280 | bool ok; | ||||
281 | double feet = QString(tagIter.value()).remove(QStringLiteral("feet")).trimmed().toDouble(&ok); | ||||
282 | if (ok) { | ||||
283 | extractedHeight = feet * 12.0; | ||||
284 | } | ||||
285 | } | ||||
286 | if (extractedHeight > 0.0) { | ||||
287 | height = extractedHeight * 0.0254; // convert inches to meters | ||||
288 | } | ||||
289 | } | ||||
290 | } else if ((tagIter = m_osmData.findTag(QStringLiteral("building:levels"))) != m_osmData.tagsEnd()) { | ||||
291 | int const levels = tagIter.value().toInt(); | ||||
292 | int const skipLevels = m_osmData.tagValue(QStringLiteral("building:min_level")).toInt(); | ||||
293 | /** @todo Is 35 as an upper bound for the number of levels sane? */ | ||||
294 | height = 3.0 * qBound(1, 1+levels-skipLevels, 35); | ||||
295 | } | ||||
296 | | ||||
297 | return qBound(1.0, height, 1000.0); | ||||
298 | } | ||||
299 | | ||||
300 | QVector<GeoDataBuilding::NamedEntry> OsmWay::extractNamedEntries() const | ||||
301 | { | ||||
302 | QVector<GeoDataBuilding::NamedEntry> entries; | ||||
303 | | ||||
304 | const auto end = m_osmData.nodeReferencesEnd(); | ||||
305 | for (auto iter = m_osmData.nodeReferencesBegin(); iter != end; ++iter) { | ||||
306 | const auto tagIter = iter.value().findTag(QStringLiteral("addr:housenumber")); | ||||
307 | if (tagIter != iter.value().tagsEnd()) { | ||||
308 | GeoDataBuilding::NamedEntry entry; | ||||
309 | entry.point = iter.key(); | ||||
310 | entry.label = tagIter.value(); | ||||
311 | entries.push_back(entry); | ||||
312 | } | ||||
313 | } | ||||
314 | | ||||
315 | return entries; | ||||
316 | } | ||||
317 | | ||||
192 | } | 318 | } | ||
Context not available. |