Marble

GeoDataRelation.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2017 Dennis Nienhüser <[email protected]>
4 
5 #include "GeoDataRelation.h"
6 
7 #include "GeoDataTypes.h"
8 #include "OsmPlacemarkData.h"
9 
10 #include <QSet>
11 
12 namespace Marble
13 {
14 
15 class GeoDataRelationPrivate
16 {
17 public:
18  QSet<const GeoDataFeature*> m_features;
19  OsmPlacemarkData m_osmData;
20  QSet<qint64> m_memberIds;
21 
22  mutable GeoDataRelation::RelationType m_relationType = GeoDataRelation::UnknownType;
23  mutable bool m_relationTypeDirty = true;
24  static QHash<QString, GeoDataRelation::RelationType> s_relationTypes;
25 };
26 
27 QHash<QString, GeoDataRelation::RelationType> GeoDataRelationPrivate::s_relationTypes;
28 
29 GeoDataRelation::GeoDataRelation() :
30  GeoDataFeature(),
31  d_ptr(new GeoDataRelationPrivate)
32 {
33  // nothing to do
34 }
35 
36 GeoDataRelation::~GeoDataRelation()
37 {
38  delete d_ptr;
39 }
40 
41 GeoDataRelation::GeoDataRelation(const GeoDataRelation &other) :
42  GeoDataFeature(other),
43  d_ptr(new GeoDataRelationPrivate)
44 {
45  Q_D(GeoDataRelation);
46  d->m_features = other.d_func()->m_features;
47  d->m_osmData = other.d_func()->m_osmData;
48  d->m_memberIds = other.d_func()->m_memberIds;
49  d->m_relationType = other.d_func()->m_relationType;
50  d->m_relationTypeDirty = other.d_func()->m_relationTypeDirty;
51 }
52 
53 GeoDataRelation &GeoDataRelation::operator=(GeoDataRelation other) // passed by value
54 {
55  GeoDataFeature::operator=(other);
56  std::swap(*this->d_ptr, *other.d_ptr);
57  return *this;
58 }
59 
60 bool GeoDataRelation::operator<(const GeoDataRelation &other) const
61 {
62  if (relationType() == other.relationType()) {
63  Q_D(const GeoDataRelation);
64  auto const refA = d->m_osmData.tagValue(QStringLiteral("ref"));
65  auto const refB = other.osmData().tagValue(QStringLiteral("ref"));
66  if (refA == refB) {
67  return name() < other.name();
68  }
69  return refA < refB;
70  }
71  return relationType() < other.relationType();
72 }
73 
74 const char *GeoDataRelation::nodeType() const
75 {
76  return GeoDataTypes::GeoDataRelationType;
77 }
78 
79 GeoDataFeature *GeoDataRelation::clone() const
80 {
81  return new GeoDataRelation(*this);
82 }
83 
84 void GeoDataRelation::addMember(const GeoDataFeature *feature, qint64 id, OsmType type, const QString &role)
85 {
86  Q_D(GeoDataRelation);
87  d->m_features << feature;
88  d->m_osmData.addRelation(id, type, role);
89  d->m_memberIds << id;
90 }
91 
92 QSet<const GeoDataFeature *> GeoDataRelation::members() const
93 {
94  Q_D(const GeoDataRelation);
95  return d->m_features;
96 }
97 
98 OsmPlacemarkData &GeoDataRelation::osmData()
99 {
100  Q_D(GeoDataRelation);
101  d->m_relationTypeDirty = true;
102  return d->m_osmData;
103 }
104 
105 const OsmPlacemarkData &GeoDataRelation::osmData() const
106 {
107  Q_D(const GeoDataRelation);
108  return d->m_osmData;
109 }
110 
111 GeoDataRelation::RelationType GeoDataRelation::relationType() const
112 {
113  Q_D(const GeoDataRelation);
114  if (!d->m_relationTypeDirty) {
115  return d->m_relationType;
116  }
117 
118  if (GeoDataRelationPrivate::s_relationTypes.isEmpty()) {
119  auto &map = GeoDataRelationPrivate::s_relationTypes;
120  map["road"] = RouteRoad;
121  map["detour"] = RouteDetour;
122  map["ferry"] = RouteFerry;
123  map["train"] = RouteTrain;
124  map["subway"] = RouteSubway;
125  map["tram"] = RouteTram;
126  map["bus"] = RouteBus;
127  map["trolleybus"] = RouteTrolleyBus;
128  map["bicycle"] = RouteBicycle;
129  map["mtb"] = RouteMountainbike;
130  map["foot"] = RouteFoot;
131  map["hiking"] = GeoDataRelation::RouteHiking;
132  map["horse"] = RouteHorse;
133  map["inline_skates"] = RouteInlineSkates;
134  }
135 
136  d->m_relationType = GeoDataRelation::UnknownType;
137  d->m_relationTypeDirty = false;
138  if (d->m_osmData.containsTag(QStringLiteral("type"), QStringLiteral("route"))) {
139  auto const route = d->m_osmData.tagValue(QStringLiteral("route"));
140  if (route == QStringLiteral("piste")) {
141  auto const piste = d->m_osmData.tagValue(QStringLiteral("piste:type"));
142  if (piste == QStringLiteral("downhill")) {
143  d->m_relationType = RouteSkiDownhill;
144  } else if (piste == QStringLiteral("nordic")) {
145  d->m_relationType = RouteSkiNordic;
146  } else if (piste == QStringLiteral("skitour")) {
147  d->m_relationType = RouteSkitour;
148  } else if (piste == QStringLiteral("sled")) {
149  d->m_relationType = RouteSled;
150  }
151  } else {
152  d->m_relationType = GeoDataRelationPrivate::s_relationTypes.value(route, UnknownType);
153  }
154  }
155 
156  return d->m_relationType;
157 }
158 
159 QSet<qint64> GeoDataRelation::memberIds() const
160 {
161  Q_D(const GeoDataRelation);
162  return d->m_memberIds;
163 }
164 
165 bool GeoDataRelation::containsAnyOf(const QSet<qint64> &memberIds) const
166 {
167  Q_D(const GeoDataRelation);
168  return d->m_memberIds.intersects(memberIds);
169 }
170 
171 Q_DECLARE_OPERATORS_FOR_FLAGS(GeoDataRelation::RelationTypes)
172 
173 }
const T value(const Key &key) const const
Binds a QML item to a specific geodetic location in screen coordinates.
const char * name(StandardAction id)
OsmType
Type of OSM element.
QFuture< void > map(Sequence &sequence, MapFunctor function)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Sep 27 2023 04:09:06 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.