equipmentmodel.cpp 4.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
    SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "equipmentmodel.h"
#include "../loader/levelparser_p.h"

#include <osm/geomath.h>

#include <QDebug>

using namespace KOSMIndoorMap;

float Equipment::distanceTo(const OSM::DataSet &dataSet, float lat, float lon) const
{
    if (sourceElements.empty()) {
        return std::numeric_limits<float>::max();
    }

    switch (sourceElements[0].type()) {
        case OSM::Type::Null:
            return std::numeric_limits<float>::max();
        case OSM::Type::Node:
            return OSM::distance(sourceElements[0].center(), OSM::Coordinate(lat, lon));
        case OSM::Type::Way:
        case OSM::Type::Relation:
        {
            const auto path = sourceElements[0].outerPath(dataSet);
            return OSM::distance(path, OSM::Coordinate(lat, lon));
        }
    }
    Q_UNREACHABLE();
    return std::numeric_limits<float>::max();
}


EquipmentModel::EquipmentModel(QObject* parent)
    : AbstractOverlaySource(nullptr, parent)
{
}

EquipmentModel::~EquipmentModel() = default;

MapData EquipmentModel::mapData() const
{
    return m_data;
}

void EquipmentModel::setMapData(const MapData &data)
{
    if (m_data == data) {
        return;
    }

    m_equipment.clear();
    m_data = data;

    if (!m_data.isEmpty()) {
        m_tagKeys.building = m_data.dataSet().tagKey("building");
Volker Krause's avatar
Volker Krause committed
62
        m_tagKeys.buildling_part = m_data.dataSet().tagKey("building:part");
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
        m_tagKeys.conveying = m_data.dataSet().tagKey("conveying");
        m_tagKeys.elevator = m_data.dataSet().tagKey("elevator");
        m_tagKeys.highway = m_data.dataSet().tagKey("highway");
        m_tagKeys.indoor = m_data.dataSet().tagKey("indoor");
        m_tagKeys.level = m_data.dataSet().tagKey("level");
        m_tagKeys.room = m_data.dataSet().tagKey("room");
        m_tagKeys.stairwell = m_data.dataSet().tagKey("stairwell");

        m_tagKeys.mxoid = m_data.dataSet().makeTagKey("mx:oid");
        m_tagKeys.realtimeStatus = m_data.dataSet().makeTagKey("mx:realtime_status");
        findEquipment();
    }

    for (const auto &eq : m_equipment) {
        qDebug() << "  E" << eq.sourceElements.size() << eq.levels << eq.type;
    }

    emit update();
}

void EquipmentModel::forEach(int floorLevel, const std::function<void (OSM::Element, int)> &func) const
{
    for (const auto &eq : m_equipment) {
        if (!eq.syntheticElement || std::find(eq.levels.begin(), eq.levels.end(), floorLevel) == eq.levels.end()) {
            continue;
        }
        func(eq.syntheticElement, floorLevel);
    }
}

void EquipmentModel::hiddenElements(std::vector<OSM::Element> &elems) const
{
    // TODO
}

void EquipmentModel::findEquipment()
{
    OSM::for_each(m_data.dataSet(), [this](OSM::Element e) {
        if (!e.hasTags()) {
            return;
        }

        // escalators
        const auto highway = e.tagValue(m_tagKeys.highway);
        const auto conveying = e.tagValue(m_tagKeys.conveying);
        if ((highway == "footway" || highway == "steps") && (!conveying.isEmpty() && conveying != "no")) {
            Equipment escalator;
            escalator.type = Equipment::Escalator;
            escalator.sourceElements.push_back(e);
            LevelParser::parse(e.tagValue(m_tagKeys.level), e, [&escalator](int level, OSM::Element) {
                escalator.levels.push_back(level);
            });
            m_equipment.push_back(std::move(escalator));
        }

        // elevators
        const auto building = e.tagValue(m_tagKeys.building);
        const auto buildling_part = e.tagValue(m_tagKeys.buildling_part);
        const auto elevator = e.tagValue(m_tagKeys.elevator);
        const auto indoor = e.tagValue(m_tagKeys.indoor);
        const auto room = e.tagValue(m_tagKeys.room);
        const auto stairwell = e.tagValue(m_tagKeys.stairwell);

        if (building == "elevator"
         || buildling_part == "elevator" || (buildling_part == "yes" && elevator == "yes")
         || highway == "elevator"
         || room == "elevator"
         || stairwell == "elevator"
         || (indoor == "room" && elevator == "yes"))
        {
            // TODO single level elevators need to be merged with duplicates on other levels
            Equipment elevator;
            elevator.type = Equipment::Elevator;
            elevator.sourceElements.push_back(e);
            LevelParser::parse(e.tagValue(m_tagKeys.level), e, [&elevator](int level, OSM::Element) {
                elevator.levels.push_back(level);
            });
            if (elevator.levels.empty()) {
                elevator.levels.push_back(0);
            }
            m_equipment.push_back(std::move(elevator));
        }

    }, OSM::IncludeNodes | OSM::IncludeWays);
}