SWMMVis  6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
xyztilelayer.h
Go to the documentation of this file.
1
7#ifndef XYZTILELAYER_H
8#define XYZTILELAYER_H
9
13
14#include <QCache>
15#include <QImage>
16#include <QMutex>
17#include <QSet>
18#include <QSize>
19#include <QString>
20
21#include <atomic>
22#include <limits>
23
24class QNetworkAccessManager;
25class QNetworkReply;
26class OGRSpatialReference;
27class OGRCoordinateTransformation;
28
41{
42 Q_OBJECT
43
44public:
56 explicit XYZTileLayer(const QString &urlTemplate,
57 int tileSizePx = 256,
58 QObject *parent = nullptr);
59 ~XYZTileLayer() override;
60
61 // ----- OpenSWMMVisLayer interface ---------------------------------------
62
63 [[nodiscard]] bool isRasterLayer() const override { return true; }
64
68 [[nodiscard]] bool isBasemapLayer() const override { return true; }
69
70 void fetchCache(const MapExtent &extent,
71 const QSize &viewportSize,
72 const SpatialReferenceSystem *canvasSRS) override;
73
74 void render(QPainter *painter,
75 const MapExtent &extent,
76 const QSize &imageSize,
77 const SpatialReferenceSystem *canvasSRS) override;
78
79 // Raster layers don't add QGraphicsItems.
80 void populateScene(QGraphicsScene *, const MapExtent &,
81 const SpatialReferenceSystem *) override {}
82
83 void onCanvasCRSChanged(const SpatialReferenceSystem *newCanvasSRS) override;
84
85 // ----- Configuration ---------------------------------------------------
86
87 int tileCacheMaxSize() const { return m_tileCache.maxCost(); }
88 void setTileCacheMaxSize(int count); // locks the cache; can evict → bumps epoch
89
90 void setTilePixelRatio(int ratio) { m_tilePixelRatio = ratio; }
91 void setAxisOrder(TileAxisOrder order) { m_axisOrder = order; }
92
93 [[nodiscard]] QString urlTemplate() const { return m_urlTemplate; }
94 [[nodiscard]] int tilePixelRatio() const { return m_tilePixelRatio; }
95 [[nodiscard]] TileAxisOrder axisOrder() const { return m_axisOrder; }
96
97 [[nodiscard]] QString sourceDescription() const override { return m_urlTemplate; }
98
102 [[nodiscard]] const OpenSWMM::Render::BasemapRenderParams &basemapRenderParams() const { return m_renderParams; }
104
105signals:
107
108private slots:
109 void onTileReply(QNetworkReply *reply, const QString &key);
110
111private:
112 // Tile coordinate math (OSM / Web Mercator convention)
113 int bestZoom(const QRectF &wgs84Extent, int vpWidth) const;
114 QRectF tileBoundsWGS84(int z, int x, int y) const;
115 void latLonToTileXY(double lat, double lon, int z, int &tx, int &ty) const;
116 QRectF wgs84ExtentOfCanvasExtent(const MapExtent &extent,
117 const SpatialReferenceSystem *canvasSRS) const;
118 QRectF tileCanvasBounds(const QRectF &wgs84Bounds,
119 const SpatialReferenceSystem *canvasSRS) const;
120
121 void rebuildTransforms(const SpatialReferenceSystem *canvasSRS);
122 void fetchTile(int z, int x, int y);
123 QString buildUrl(int z, int x, int y) const;
124
126
127 QString m_urlTemplate;
128 QNetworkAccessManager *m_nam = nullptr;
129 QCache<QString, QImage> m_tileCache; // key "z/x/y"
130 QSet<QString> m_inflight; // keys being fetched
131
132 // P1 — m_tileCache/m_inflight are written on the GUI thread while the
133 // MapRenderJob worker reads them in render() (QCache eviction deletes a
134 // QImage the worker may be mid-sampling), so every touch point locks
135 // m_tileCacheMutex. m_tileEpoch counts content changes; render() memoizes
136 // its final output keyed on (extent, devSize, zoom, epoch) so repeat
137 // renders at an unchanged view (selection repaints, other layers' tile
138 // arrivals) skip the reprojection entirely. Memo fields are only touched
139 // inside render()/under m_transformMutex (held for its whole body).
140 mutable QMutex m_tileCacheMutex;
141 std::atomic<quint64> m_tileEpoch {0};
142 QImage m_renderMemo;
143 MapExtent m_memoExtent;
144 QSize m_memoDevSize;
145 int m_memoZoom = -1;
146 quint64 m_memoEpoch = std::numeric_limits<quint64>::max();
147 int m_subdomainIdx = 0; // rotates a/b/c
148 int m_tileSizePx = 256; // 256 standard, 512 for @2x
149 int m_tilePixelRatio = 0; // 0=undefined,1=standard,2=HiDPI
150 TileAxisOrder m_axisOrder = TileAxisOrder::ZXY;
153 // Cached GDAL transforms (rebuilt on CRS change). Mutex guards the
154 // render() ↔ rebuildTransforms() race: render runs in the MapRenderJob
155 // worker thread, rebuildTransforms can fire from the main thread when
156 // the canvas CRS changes. Without this, the worker can dereference a
157 // freed OGRCoordinateTransformation* and crash.
158 OGRSpatialReference *m_wgs84 = nullptr;
159 OGRSpatialReference *m_merc3857 = nullptr; // P1 — same-CRS fast path
160 OGRCoordinateTransformation *m_toWGS84 = nullptr; // canvas → WGS84
161 OGRCoordinateTransformation *m_fromWGS84 = nullptr; // WGS84 → canvas
162 mutable QMutex m_transformMutex;
163};
164
165#endif // XYZTILELAYER_H
Plain data structs for all supported basemap connection types.
TileAxisOrder
Controls how {x}/{y} tile coordinates are ordered in the URL.
Definition basemapconnection.h:40
Shared visual-adjustment parameters for raster basemaps.
An axis-aligned bounding box in the coordinate space of a given CRS.
Definition mapextent.h:26
Abstract base class for all layers displayed in the MapCanvas.
Definition openswmmvislayer.h:116
MapExtent extent() const
Returns the layer extent in the layer's own CRS.
Definition openswmmvislayer.cpp:252
Represents a coordinate reference system backed by a GDAL OGRSpatialReference.
Definition spatialreferencesystem.h:28
Renders a standard XYZ (slippy-map) tile service as a raster basemap.
Definition xyztilelayer.h:41
void onCanvasCRSChanged(const SpatialReferenceSystem *newCanvasSRS) override
Called when the user changes the canvas CRS so layers can pre-compute any CRS-dependent transform cac...
Definition xyztilelayer.cpp:108
void setTilePixelRatio(int ratio)
Definition xyztilelayer.h:90
bool isBasemapLayer() const override
Definition xyztilelayer.h:68
void basemapRenderParamsChanged()
QString sourceDescription() const override
Human-readable source of this layer: a file path, a service URL, or a description for in-memory / der...
Definition xyztilelayer.h:97
bool isRasterLayer() const override
Returns true for layers that render into a raster buffer (WMS, WMTS, GISRaster) rather than populatin...
Definition xyztilelayer.h:63
void setAxisOrder(TileAxisOrder order)
Definition xyztilelayer.h:91
int tilePixelRatio() const
Definition xyztilelayer.h:94
QString urlTemplate() const
Definition xyztilelayer.h:93
TileAxisOrder axisOrder() const
Definition xyztilelayer.h:95
friend class XYZTileLayerAccessor
Definition xyztilelayer.h:125
int tileCacheMaxSize() const
Definition xyztilelayer.h:87
void populateScene(QGraphicsScene *, const MapExtent &, const SpatialReferenceSystem *) override
Creates / updates QGraphicsItems representing this layer in the scene.
Definition xyztilelayer.h:80
void setBasemapRenderParams(const OpenSWMM::Render::BasemapRenderParams &p)
Definition xyztilelayer.cpp:899
void render(QPainter *painter, const MapExtent &extent, const QSize &imageSize, const SpatialReferenceSystem *canvasSRS) override
Renders this layer's content directly into painter.
Definition xyztilelayer.cpp:469
~XYZTileLayer() override
Definition xyztilelayer.cpp:96
const OpenSWMM::Render::BasemapRenderParams & basemapRenderParams() const
Definition xyztilelayer.h:102
void fetchCache(const MapExtent &extent, const QSize &viewportSize, const SpatialReferenceSystem *canvasSRS) override
Triggers any asynchronous (or synchronous) tile/data fetch needed to populate this layer's internal c...
Definition xyztilelayer.cpp:420
void setTileCacheMaxSize(int count)
Definition xyztilelayer.cpp:909
ArrowPlacement p
Definition linesymbollayer.cpp:27
const char * key
Definition meshcellparams.cpp:24
int count
Definition numberformat.cpp:101
Abstract base class for all map layers displayed in the MapCanvas.
QVector< int > parent
union-find
Definition pslgminsize.cpp:176
Brightness / contrast / saturation / resampling for a basemap.
Definition basemaprenderparams.h:32