File indexing completed on 2024-11-17 04:17:26

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KOSMINDOORMAP_SCENEGRAPH_H
0008 #define KOSMINDOORMAP_SCENEGRAPH_H
0009 
0010 #include "kosmindoormap_export.h"
0011 
0012 #include "scenegraphitem.h"
0013 
0014 #include <KOSM/Element>
0015 
0016 #include <QColor>
0017 
0018 #include <memory>
0019 #include <vector>
0020 
0021 class QPointF;
0022 
0023 namespace KOSMIndoorMap {
0024 
0025 class SceneGraphItem;
0026 
0027 /** Scene graph of the currently displayed level. */
0028 class KOSMINDOORMAP_EXPORT SceneGraph
0029 {
0030 public:
0031     explicit SceneGraph();
0032     SceneGraph(const SceneGraph&) = delete;
0033     SceneGraph(SceneGraph&&);
0034     ~SceneGraph();
0035 
0036     SceneGraph& operator=(const SceneGraph&) = delete;
0037     SceneGraph& operator=(SceneGraph &&other);
0038 
0039     /** Clears all data from the scene graph. */
0040     void clear();
0041 
0042     // scene builder interface
0043     void beginSwap();
0044     void addItem(SceneGraphItem &&item);
0045     template <typename T>
0046     std::unique_ptr<SceneGraphItemPayload> findOrCreatePayload(OSM::Element e, int level, LayerSelectorKey layerSelector);
0047     void zSort();
0048     void endSwap();
0049 
0050     // dirty state tracking
0051     int zoomLevel() const;
0052     void setZoomLevel(int zoom);
0053     int currentFloorLevel() const;
0054     void setCurrentFloorLevel(int level);
0055 
0056     /** Canvas background color. */
0057     QColor backgroundColor() const;
0058     void setBackgroundColor(const QColor &bg);
0059 
0060     // renderer interface
0061     typedef std::pair<std::size_t, std::size_t> LayerOffset;
0062     const std::vector<LayerOffset>& layerOffsets() const;
0063 
0064     typedef std::vector<SceneGraphItem>::const_iterator SceneGraphItemIter;
0065     SceneGraphItemIter itemsBegin(LayerOffset layer) const;
0066     SceneGraphItemIter itemsEnd(LayerOffset layer) const;
0067 
0068     // hit detector interface
0069     const std::vector<SceneGraphItem>& items() const;
0070 
0071 private:
0072     void recomputeLayerIndex();
0073 
0074     static bool itemPoolCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs);
0075     static bool zOrderCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs);
0076 
0077     std::vector<SceneGraphItem> m_items;
0078     std::vector<SceneGraphItem> m_previousItems;
0079     std::vector<std::pair<std::size_t, std::size_t>> m_layerOffsets;
0080     QColor m_bgColor;
0081 
0082     int m_zoomLevel = 0;
0083     int m_floorLevel = 0;
0084 };
0085 
0086 
0087 template<typename T>
0088 std::unique_ptr<SceneGraphItemPayload> SceneGraph::findOrCreatePayload(OSM::Element e, int level, LayerSelectorKey layerSelector)
0089 {
0090     SceneGraphItem ref;
0091     ref.element = e;
0092     ref.level = level;
0093     auto it = std::lower_bound(m_previousItems.begin(), m_previousItems.end(), ref, SceneGraph::itemPoolCompare);
0094     for (;it != m_previousItems.end() && (*it).element.type() == e.type() && (*it).element.id() == e.id() && (*it).layerSelector == layerSelector && (*it).level == level && (*it).payload; ++it) {
0095         if (dynamic_cast<T*>((*it).payload.get())) {
0096             return std::move((*it).payload);
0097         }
0098     }
0099     return std::make_unique<T>();
0100 }
0101 
0102 }
0103 
0104 #endif // KOSMINDOORMAP_SCENEGRAPH_H