KOSMIndoorMap

penwidthutil.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 "penwidthutil_p.h"
8#include "logging.h"
9#include "style/mapcssdeclaration_p.h"
10
11#include <cmath>
12
13using namespace KOSMIndoorMap;
14
15struct {
16 const char* unit;
17 double factor;
18} static constexpr const unit_conversion_table[] = {
19 { "cm", 0.01 },
20 { "ft", 0.3048 },
21};
22
23double PenWidthUtil::penWidth(OSM::Element e, const MapCSSDeclaration *decl, Unit &unit)
24{
25 // literal value, possibly with a unit
26 if (decl->keyValue().isEmpty()) {
27 if (decl->unit() != MapCSSDeclaration::NoUnit) {
28 unit = decl->unit() == MapCSSDeclaration::Meters ? Unit::Meter : Unit::Pixel;
29 }
30 return decl->doubleValue();
31 }
32
33 // referenced value from a tag value
34 // see https://wiki.openstreetmap.org/wiki/Map_Features/Units
35 double unitConversionFactor = 1.0;
36 double num = NAN;
37
38 const auto value = e.tagValue(decl->keyValue().constData()).constData();
39 const auto valueLen = std::strlen(value);
40 const auto valueEnd = value + valueLen;
41 const char* it = value;
42
43 while (it < valueEnd) {
44 char* numEnd;
45 num = std::isnan(num) ? std::strtod(it, &numEnd) : std::max(num, std::strtod(it, &numEnd));
46 if (it == numEnd) {
47 break;
48 }
49 it = numEnd;
50
51 while (it != valueEnd && std::isspace(static_cast<unsigned char>(*it))) {
52 ++it;
53 }
54
55 // there is an explicit unit suffix;
56 for (const auto &unit : unit_conversion_table) {
57 const auto unitLen = std::strlen(unit.unit);
58 if (std::strncmp(it, unit.unit, unitLen) == 0) {
59 unitConversionFactor = unit.factor;
60 it += unitLen;
61 break;
62 }
63 }
64
65 if (it != valueEnd && (*it) == ';') {
66 ++it;
67 continue;
68 }
69 break;
70 }
71
72 if (std::isnan(num)) {
73 qCDebug(Log) << "Failed to parse width from tag value:" << value << decl->keyValue() << e.url();
74 return 0.0;
75 }
76
77 // no explicit unit, use default unit for this tag
78 if (it == value + valueLen) {
79 if (std::strcmp(decl->keyValue().constData(), "gauge") == 0) {
80 unitConversionFactor = 0.001;
81 }
82 }
83
84 unit = Unit::Meter;
85 return num * unitConversionFactor;
86}
A reference to any of OSM::Node/OSM::Way/OSM::Relation.
Definition element.h:24
OSM-based multi-floor indoor maps for buildings.
Unit
Unit for geometry sizes.
const char * constData() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.