3 #include "common/wgs84.h"
4 #include "common/rectc.h"
6 #include "downloader.h"
7 #include "tileloader.h"
11 #define CAPABILITIES_FILE "capabilities.xml"
14 double WMSMap::sd2res(double scaleDenominator
) const
16 return scaleDenominator
* 0.28e-3 * _projection
.units().fromMeters(1.0);
19 QString
WMSMap::tileUrl(const QString
&version
) const
23 url
= QString("%1?version=%2&request=GetMap&bbox=$bbox"
24 "&width=%3&height=%4&layers=%5&styles=%6&format=%7&transparent=true")
25 .arg(_setup
.url(), version
, QString::number(TILE_SIZE
),
26 QString::number(TILE_SIZE
), _setup
.layer(), _setup
.style(),
29 if (version
>= "1.3.0")
30 url
.append(QString("&CRS=%1").arg(_setup
.crs()));
32 url
.append(QString("&SRS=%1").arg(_setup
.crs()));
34 for (int i
= 0; i
< _setup
.dimensions().size(); i
++) {
35 const QPair
<QString
, QString
> &dim
= _setup
.dimensions().at(i
);
36 url
.append(QString("&%1=%2").arg(dim
.first
, dim
.second
));
42 QString
WMSMap::tilesDir() const
44 return QString(TILES_DIR
+ "/" + _name
);
47 void WMSMap::computeZooms(const RangeF
&scaleDenominator
)
51 if (scaleDenominator
.size() > 0) {
52 double ld
= log2(scaleDenominator
.max()) - log2(scaleDenominator
.min());
54 double step
= ld
/ (qreal
)cld
;
55 qreal lmax
= log2(scaleDenominator
.max());
56 for (int i
= 0; i
<= cld
; i
++)
57 _zooms
.append(pow(2.0, lmax
- i
* step
));
59 _zooms
.append(scaleDenominator
.min());
62 void WMSMap::updateTransform()
64 double pixelSpan
= sd2res(_zooms
.at(_zoom
));
65 if (_projection
.isGeographic())
66 pixelSpan
/= deg2rad(WGS84_RADIUS
);
67 double sx
= _bbox
.width() / pixelSpan
;
68 double sy
= _bbox
.height() / pixelSpan
;
70 ReferencePoint
tl(PointD(0, 0), _bbox
.topLeft());
71 ReferencePoint
br(PointD(sx
, sy
), _bbox
.bottomRight());
72 _transform
= Transform(tl
, br
);
75 bool WMSMap::loadWMS()
77 QString file
= tilesDir() + "/" + CAPABILITIES_FILE
;
79 WMS
wms(file
, _setup
);
81 _errorString
= wms
.errorString();
85 _projection
= wms
.projection();
86 _bbox
= RectD(_projection
.ll2xy(wms
.boundingBox().topLeft()),
87 _projection
.ll2xy(wms
.boundingBox().bottomRight()));
88 _tileLoader
->setUrl(tileUrl(wms
.version()));
90 if (wms
.version() >= "1.3.0") {
91 if (_setup
.coordinateSystem().axisOrder() == CoordinateSystem::Unknown
)
92 _cs
= _projection
.coordinateSystem();
94 _cs
= _setup
.coordinateSystem();
96 _cs
= CoordinateSystem::XY
;
98 computeZooms(wms
.scaleDenominator());
104 WMSMap::WMSMap(const QString
&name
, const WMS::Setup
&setup
, QObject
*parent
)
105 : Map(parent
), _name(name
), _setup(setup
), _zoom(0), _valid(false)
107 if (!QDir().mkpath(tilesDir())) {
108 _errorString
= "Error creating tiles dir";
112 _tileLoader
= new TileLoader(this);
113 _tileLoader
->setDir(tilesDir());
114 _tileLoader
->setAuthorization(_setup
.authorization());
115 connect(_tileLoader
, SIGNAL(finished()), this, SIGNAL(loaded()));
120 void WMSMap::clearCache()
122 _tileLoader
->clearCache();
126 qWarning("%s: %s\n", qPrintable(_name
), qPrintable(_errorString
));
129 QRectF
WMSMap::bounds() const
131 return QRectF(_transform
.proj2img(_bbox
.topLeft()),
132 _transform
.proj2img(_bbox
.bottomRight()));
135 int WMSMap::zoomFit(const QSize
&size
, const RectC
&rect
)
137 if (rect
.isValid()) {
138 PointD
tl(_projection
.ll2xy(rect
.topLeft()));
139 PointD
br(_projection
.ll2xy(rect
.bottomRight()));
140 PointD
sc((br
.x() - tl
.x()) / size
.width(), (tl
.y() - br
.y())
142 double resolution
= qMax(qAbs(sc
.x()), qAbs(sc
.y()));
143 if (_projection
.isGeographic())
144 resolution
*= deg2rad(WGS84_RADIUS
);
147 for (int i
= 0; i
< _zooms
.size(); i
++) {
148 if (sd2res(_zooms
.at(i
)) < resolution
)
153 _zoom
= _zooms
.size() - 1;
159 void WMSMap::setZoom(int zoom
)
167 _zoom
= qMin(_zoom
+ 1, _zooms
.size() - 1);
172 int WMSMap::zoomOut()
174 _zoom
= qMax(_zoom
- 1, 0);
179 QPointF
WMSMap::ll2xy(const Coordinates
&c
)
181 return _transform
.proj2img(_projection
.ll2xy(c
));
184 Coordinates
WMSMap::xy2ll(const QPointF
&p
)
186 return _projection
.xy2ll(_transform
.img2proj(p
));
189 void WMSMap::draw(QPainter
*painter
, const QRectF
&rect
, bool block
)
191 QPoint tl
= QPoint((int)floor(rect
.left() / (qreal
)TILE_SIZE
),
192 (int)floor(rect
.top() / (qreal
)TILE_SIZE
));
193 QPoint br
= QPoint((int)ceil(rect
.right() / (qreal
)TILE_SIZE
),
194 (int)ceil(rect
.bottom() / (qreal
)TILE_SIZE
));
197 for (int i
= tl
.x(); i
< br
.x(); i
++) {
198 for (int j
= tl
.y(); j
< br
.y(); j
++) {
199 PointD
ttl(_transform
.img2proj(QPointF(i
* TILE_SIZE
,
201 PointD
tbr(_transform
.img2proj(QPointF(i
* TILE_SIZE
+ TILE_SIZE
202 - 1, j
* TILE_SIZE
+ TILE_SIZE
- 1)));
203 RectD bbox
= (_cs
.axisOrder() == CoordinateSystem::YX
)
204 ? RectD(PointD(tbr
.y(), tbr
.x()), PointD(ttl
.y(), ttl
.x()))
207 tiles
.append(Tile(QPoint(i
, j
), _zoom
, bbox
));
212 _tileLoader
->loadTilesSync(tiles
);
214 _tileLoader
->loadTilesAsync(tiles
);
216 for (int i
= 0; i
< tiles
.count(); i
++) {
218 QPoint
tp(t
.xy().x() * TILE_SIZE
, t
.xy().y() * TILE_SIZE
);
219 if (!t
.pixmap().isNull())
220 painter
->drawPixmap(tp
, t
.pixmap());