KOSMIndoorMap

scenegraph.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 "scenegraph.h"
8
9#include <QDebug>
10#include <QGuiApplication>
11#include <QPalette>
12
13using namespace KOSMIndoorMap;
14
15SceneGraph::SceneGraph() = default;
16SceneGraph::SceneGraph(SceneGraph&&) = default;
17SceneGraph::~SceneGraph() = default;
18SceneGraph& SceneGraph::operator=(SceneGraph &&other) = default;
19
21{
22 m_items.clear();
23 m_previousItems.clear();
24 m_layerOffsets.clear();
25 m_bgColor = {};
26 m_floorLevel = 0;
27 m_zoomLevel = 0;
28}
29
30void SceneGraph::addItem(SceneGraphItem &&item)
31{
32 m_items.push_back(std::move(item));
33}
34
35void SceneGraph::zSort()
36{
37 std::stable_sort(m_items.begin(), m_items.end(), SceneGraph::zOrderCompare);
38 recomputeLayerIndex();
39}
40
41static inline uint64_t area(const SceneGraphItem &item)
42{
43 return (uint64_t)item.element.boundingBox().width() * (uint64_t)item.element.boundingBox().height();
44}
45
46bool SceneGraph::zOrderCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs)
47{
48 /* The MapCSS spec says we have to render in the following order:
49 * - Objects with lower layer should always be rendered first.
50 * - Within a layer, first all fills are rendered, then all casings, then all strokes, then all icons and labels.
51 * - Within each of those categories, objects are ordered according to z-index.
52 * - If all of the above are equal, the order is undefined.
53 */
54 if (lhs.level == rhs.level) {
55 if (lhs.layer == rhs.layer) {
56 if (lhs.payload->z == rhs.payload->z) {
57 return area(lhs) > area(rhs);
58 }
59 return lhs.payload->z < rhs.payload->z;
60 }
61 return lhs.layer < rhs.layer;
62 }
63 return lhs.level < rhs.level;
64}
65
66void SceneGraph::beginSwap()
67{
68 std::swap(m_items, m_previousItems);
69 m_items.clear();
70 std::sort(m_previousItems.begin(), m_previousItems.end(), SceneGraph::itemPoolCompare);
71 m_layerOffsets.clear();
72}
73
74void SceneGraph::endSwap()
75{
76 m_previousItems.clear();
77}
78
79int SceneGraph::zoomLevel() const
80{
81 return m_zoomLevel;
82}
83
84void SceneGraph::setZoomLevel(int zoom)
85{
86 m_zoomLevel = zoom;
87}
88
89int SceneGraph::currentFloorLevel() const
90{
91 return m_floorLevel;
92}
93
94void SceneGraph::setCurrentFloorLevel(int level)
95{
96 m_floorLevel = level;
97}
98
100{
101 return m_bgColor;
102}
103
104void SceneGraph::setBackgroundColor(const QColor &bg)
105{
106 m_bgColor = bg;
107}
108
109void SceneGraph::recomputeLayerIndex()
110{
111 m_layerOffsets.clear();
112 if (m_items.empty()) {
113 return;
114 }
115
116 auto prevIndex = 0;
117 for (auto it = m_items.begin(); it != m_items.end();) {
118 it = std::upper_bound(it, m_items.end(), *it, [](const auto &lhs, const auto &rhs) {
119 if (lhs.level == rhs.level) {
120 return lhs.layer < rhs.layer;
121 }
122 return lhs.level < rhs.level;
123 });
124 const auto nextIndex = std::distance(m_items.begin(), it);
125 m_layerOffsets.push_back(std::make_pair(prevIndex, nextIndex));
126 prevIndex = nextIndex;
127 }
128}
129
130const std::vector<SceneGraph::LayerOffset>& SceneGraph::layerOffsets() const
131{
132 return m_layerOffsets;
133}
134
135SceneGraph::SceneGraphItemIter SceneGraph::itemsBegin(SceneGraph::LayerOffset layer) const
136{
137 return m_items.begin() + layer.first;
138}
139
140SceneGraph::SceneGraphItemIter SceneGraph::itemsEnd(SceneGraph::LayerOffset layer) const
141{
142 return m_items.begin() + layer.second;
143}
144
145const std::vector<SceneGraphItem>& SceneGraph::items() const
146{
147 return m_items;
148}
149
150bool SceneGraph::itemPoolCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs)
151{
152 if (lhs.element.type() == rhs.element.type()) {
153 if (lhs.element.id() == rhs.element.id()) {
154 if (lhs.layerSelector == rhs.layerSelector) {
155 return lhs.level < rhs.level;
156 }
157 return lhs.layerSelector < rhs.layerSelector;
158 }
159 return lhs.element.id() < rhs.element.id();
160 }
161 return lhs.element.type() < rhs.element.type();
162}
Scene graph item description and handle for its content.
OSM::Element element
The OSM::Element this item refers to.
Scene graph of the currently displayed level.
Definition scenegraph.h:29
void clear()
Clears all data from the scene graph.
QColor backgroundColor() const
Canvas background color.
OSM-based multi-floor indoor maps for buildings.
QStringView level(QStringView ifopt)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:16:37 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.