7#include "equipmentmodel.h"
8#include "../loader/levelparser_p.h"
10#include <osm/geomath.h>
16float Equipment::distanceTo(
const OSM::DataSet &dataSet,
float lat,
float lon)
const
18 if (sourceElements.empty()) {
19 return std::numeric_limits<float>::max();
22 switch (sourceElements[0].type()) {
24 return std::numeric_limits<float>::max();
28 case OSM::Type::Relation:
30 const auto path = sourceElements[0].outerPath(dataSet);
35 return std::numeric_limits<float>::max();
39EquipmentModel::EquipmentModel(
QObject* parent)
44EquipmentModel::~EquipmentModel() =
default;
46MapData EquipmentModel::mapData()
const
51void EquipmentModel::setMapData(
const MapData &data)
60 if (!m_data.isEmpty()) {
61 m_tagKeys.building = m_data.dataSet().
tagKey(
"building");
62 m_tagKeys.buildling_part = m_data.dataSet().
tagKey(
"building:part");
63 m_tagKeys.conveying = m_data.dataSet().
tagKey(
"conveying");
64 m_tagKeys.elevator = m_data.dataSet().
tagKey(
"elevator");
65 m_tagKeys.highway = m_data.dataSet().
tagKey(
"highway");
66 m_tagKeys.indoor = m_data.dataSet().
tagKey(
"indoor");
67 m_tagKeys.level = m_data.dataSet().
tagKey(
"level");
68 m_tagKeys.room = m_data.dataSet().
tagKey(
"room");
69 m_tagKeys.stairwell = m_data.dataSet().
tagKey(
"stairwell");
71 m_tagKeys.mxoid = m_data.dataSet().
makeTagKey(
"mx:oid");
72 m_tagKeys.realtimeStatus = m_data.dataSet().
makeTagKey(
"mx:realtime_status");
76 for (
const auto &eq : m_equipment) {
77 qDebug() <<
" E" << eq.sourceElements.size() << eq.levels << eq.type;
85 for (
const auto &eq : m_equipment) {
86 if (!eq.syntheticElement || std::find_if(eq.levels.begin(), eq.levels.end(), [floorLevel](
int lvl) { return std::abs(floorLevel - lvl) < 10; }) == eq.levels.end()) {
89 func(eq.syntheticElement, floorLevel);
95 for (
const auto &eq : m_equipment) {
96 if (!eq.syntheticElement) {
99 elems.insert(elems.end(), eq.sourceElements.begin(), eq.sourceElements.end());
105 return b ==
"yes" || b ==
"forward" || b ==
"backward" || b ==
"reversible";
108void EquipmentModel::findEquipment()
110 OSM::for_each(m_data.dataSet(), [
this](
OSM::Element e) {
116 const auto highway = e.tagValue(m_tagKeys.highway);
117 const auto conveying = e.tagValue(m_tagKeys.conveying);
118 if ((highway ==
"footway" || highway ==
"steps") && isConveying(conveying)) {
120 escalator.type = Equipment::Escalator;
121 escalator.sourceElements.push_back(e);
122 LevelParser::parse(e.tagValue(m_tagKeys.level), e, [&escalator](
int level,
OSM::Element) {
123 escalator.levels.push_back(level);
125 m_equipment.push_back(std::move(escalator));
129 const auto building = e.tagValue(m_tagKeys.building);
130 const auto buildling_part = e.tagValue(m_tagKeys.buildling_part);
131 const auto elevator = e.tagValue(m_tagKeys.elevator);
132 const auto indoor = e.tagValue(m_tagKeys.indoor);
133 const auto room = e.tagValue(m_tagKeys.room);
134 const auto stairwell = e.tagValue(m_tagKeys.stairwell);
136 if (building ==
"elevator"
137 || buildling_part ==
"elevator" || (buildling_part ==
"yes" && elevator ==
"yes")
138 || highway ==
"elevator"
139 || room ==
"elevator"
140 || stairwell ==
"elevator"
141 || (indoor ==
"room" && elevator ==
"yes"))
144 elevator.type = Equipment::Elevator;
145 elevator.sourceElements.push_back(e);
146 LevelParser::parse(e.tagValue(m_tagKeys.level), e, [&elevator](
int level,
OSM::Element) {
147 elevator.levels.push_back(level);
149 if (elevator.levels.empty()) {
150 elevator.levels.push_back(0);
154 for (
auto &e : m_equipment) {
155 if (e.type != Equipment::Elevator) {
158 if (OSM::intersects(e.sourceElements[0].boundingBox(), elevator.sourceElements[0].boundingBox())) {
160 qDebug() <<
"merging elevator elements:" << elevator.sourceElements[0].url() << e.sourceElements[0].url();
161 e.sourceElements.push_back(elevator.sourceElements[0]);
162 e.levels.insert(e.levels.end(), elevator.levels.begin(), elevator.levels.end());
167 m_equipment.push_back(std::move(elevator));
170 }, OSM::IncludeNodes | OSM::IncludeWays);
173 for (
auto &elevator : m_equipment) {
174 if (elevator.type != Equipment::Elevator || elevator.sourceElements.size() < 2) {
178 std::sort(elevator.levels.begin(), elevator.levels.end());
179 elevator.levels.erase(std::unique(elevator.levels.begin(), elevator.levels.end()), elevator.levels.end());
180 if (elevator.levels.size() < 2) {
184 std::sort(elevator.sourceElements.begin(), elevator.sourceElements.end(), [](
auto lhs,
auto rhs) { return lhs.type() > rhs.type(); });
185 createSyntheticElement(elevator);
189void EquipmentModel::createSyntheticElement(
Equipment& eq)
const
191 if (eq.syntheticElement) {
196 eq.syntheticElement.setTagValue(m_tagKeys.mxoid,
QByteArray::number((qlonglong)eq.syntheticElement.element().id()));
200 for (
auto it = std::next(eq.sourceElements.begin()); it != eq.sourceElements.end(); ++it) {
201 for (
auto tagIt = (*it).tagsBegin(); tagIt != (*it).tagsEnd(); ++tagIt) {
202 if ((*tagIt).key == m_tagKeys.level) {
206 if (eq.syntheticElement.element().
hasTag((*tagIt).key)) {
208 if (eq.syntheticElement.element().tagValue((*tagIt).key) != (*tagIt).value) {
209 qDebug() <<
" tag value conflict:" << (*tagIt).key.name() << (*tagIt).value << eq.sourceElements[0].url() << eq.syntheticElement.element().tagValue((*tagIt).key);
213 eq.syntheticElement.setTagValue((*tagIt).key,
QByteArray((*tagIt).value));
217 if (eq.levels.size() > 1) {
219 for (
auto it = std::next(eq.levels.begin()); it != eq.levels.end(); ++it) {
222 eq.syntheticElement.setTagValue(m_tagKeys.level, std::move(levelValue));
226#include "moc_equipmentmodel.cpp"
A source for overlay elements, drawn on top of the static map data.
void update()
Trigger map re-rendering when the source changes.
void hiddenElements(std::vector< OSM::Element > &elems) const override
Adds hidden elements to.
void forEach(int floorLevel, const std::function< void(OSM::Element, int)> &func) const override
Iteration interface with floor level filtering.
Elevator or escalator element.
Raw OSM map data, separated by levels.
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
A set of nodes, ways and relations.
TagKey tagKey(const char *keyName) const
Look up a tag key for the given tag name, if it exists.
Id nextInternalId() const
Create a unique id for internal use (ie.
TagKey makeTagKey(const char *keyName, StringMemory keyMemOpt=StringMemory::Transient)
Create a tag key for the given tag name.
A reference to any of OSM::Node/OSM::Way/OSM::Relation.
bool hasTag(TagKey key) const
Returns true if this element has a tag with key key.
QString path(const QString &relativePath)
OSM-based multi-floor indoor maps for buildings.
KOSM_EXPORT double distance(double lat1, double lon1, double lat2, double lon2)
Distance between two coordinates.
KOSM_EXPORT UniqueElement copy_element(Element e)
Creates a copy of element.
QByteArray number(double n, char format, int precision)
QTextStream & center(QTextStream &stream)