KOSMIndoorMap

penwidthutil.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
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 
13 using namespace KOSMIndoorMap;
14 
15 struct {
16  const char* unit;
17  double factor;
18 } static constexpr const unit_conversion_table[] = {
19  { "cm", 0.01 },
20  { "ft", 0.3048 },
21 };
22 
23 double 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(*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 }
OSM-based multi-floor indoor maps for buildings.
A reference to any of OSM::Node/OSMWay/OSMRelation.
Definition: element.h:22
Unit
Unit for geometry sizes.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 23:04:00 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.