1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 13:41:16 +01:00

Added support for WMS multi-layer maps

This commit is contained in:
Martin Tůma 2018-04-02 19:59:52 +02:00
parent 60cc869ade
commit e845e216bd
4 changed files with 96 additions and 37 deletions

View File

@ -8,6 +8,15 @@ void RangeF::resize(qreal size)
_max += adj; _max += adj;
} }
RangeF RangeF::operator|(const RangeF &r) const
{
if (isNull())
return r;
if (r.isNull())
return *this;
return RangeF(qMax(this->_min, r._min), qMin(this->_max, r._max));
}
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Range &range) QDebug operator<<(QDebug dbg, const Range &range)
{ {

View File

@ -29,10 +29,14 @@ public:
RangeF() {_min = 0; _max = 0;} RangeF() {_min = 0; _max = 0;}
RangeF(qreal min, qreal max) {_min = min, _max = max;} RangeF(qreal min, qreal max) {_min = min, _max = max;}
RangeF operator|(const RangeF &r) const;
RangeF &operator|=(const RangeF &r) {*this = *this | r; return *this;}
qreal min() const {return _min;} qreal min() const {return _min;}
qreal max() const {return _max;} qreal max() const {return _max;}
qreal size() const {return (_max - _min);} qreal size() const {return (_max - _min);}
bool isNull() const {return _min == 0 && _max == 0;}
bool isValid() const {return size() >= 0;} bool isValid() const {return size() >= 0;}
void setMin(qreal min) {_min = min;} void setMin(qreal min) {_min = min;}

View File

@ -8,12 +8,27 @@
Downloader *WMS::_downloader = 0; Downloader *WMS::_downloader = 0;
WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
{
QStringList ll = setup.layer().split(',');
QStringList sl = setup.style().split(',');
if (ll.size() != sl.size())
return;
for (int i = 0; i < ll.size(); i++) {
layers.append(Layer(ll.at(i), sl.at(i)));
if (sl.at(i) == "default")
layers[i].hasStyle = true;
}
}
void WMS::getMap(QXmlStreamReader &reader, CTX &ctx) void WMS::getMap(QXmlStreamReader &reader, CTX &ctx)
{ {
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == "Format") { if (reader.name() == "Format") {
if (reader.readElementText() == ctx.setup.format()) if (reader.readElementText() == ctx.setup.format())
ctx.format = true; ctx.formatSupported = true;
} else } else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
@ -72,6 +87,7 @@ void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
QList<QString> styles(pStyles); QList<QString> styles(pStyles);
RangeF scaleDenominator(pScaleDenominator); RangeF scaleDenominator(pScaleDenominator);
RectC boundingBox(pBoundingBox); RectC boundingBox(pBoundingBox);
int index;
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == "Name") if (reader.name() == "Name")
@ -100,12 +116,13 @@ void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
if (name == ctx.setup.layer()) { if ((index = ctx.layers.indexOf(name)) >= 0) {
ctx.scaleDenominator = scaleDenominator; Layer &layer = ctx.layers[index];
ctx.boundingBox = boundingBox; layer.scaleDenominator = scaleDenominator;
ctx.layer = true; layer.boundingBox = boundingBox;
ctx.style = styles.contains(ctx.setup.style()); layer.isDefined = true;
ctx.crs = CRSs.contains(ctx.setup.crs()); layer.hasStyle = styles.contains(layer.style);
layer.hasCRS = CRSs.contains(ctx.setup.crs());
} }
} }
@ -144,6 +161,12 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
CTX ctx(setup); CTX ctx(setup);
QXmlStreamReader reader; QXmlStreamReader reader;
if (ctx.layers.isEmpty()) {
_errorString = "Invalid layers definition";
return false;
}
if (!file.open(QFile::ReadOnly | QFile::Text)) { if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString(); _errorString = file.errorString();
return false; return false;
@ -163,38 +186,50 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
return false; return false;
} }
if (!ctx.layer) { if (!ctx.formatSupported) {
_errorString = ctx.setup.layer() + ": layer not provided";
return false;
}
if (!ctx.style && ctx.setup.style() != "default") {
_errorString = ctx.setup.style() + ": style not provided";
return false;
}
if (!ctx.format) {
_errorString = ctx.setup.format() + ": format not provided"; _errorString = ctx.setup.format() + ": format not provided";
return false; return false;
} }
if (!ctx.crs) {
_errorString = ctx.setup.crs() + ": CRS not provided"; for (int i = 0; i < ctx.layers.size(); i++) {
return false; const Layer &layer = ctx.layers.at(i);
if (!layer.isDefined) {
_errorString = ctx.setup.layer() + ": layer not provided";
return false;
}
if (!layer.hasStyle) {
_errorString = ctx.setup.style() + ": style not provided for layer "
+ layer.name;
return false;
}
if (!layer.hasCRS) {
_errorString = ctx.setup.crs() + ": CRS not provided for layer "
+ layer.name;
return false;
}
if (!layer.scaleDenominator.isValid()) {
_errorString = "Invalid scale denominator range for layer"
+ layer.name;
return false;
}
if (!layer.boundingBox.isValid()) {
_errorString = "Invalid/missing bounding box for layer"
+ layer.name;
return false;
}
} }
_projection = CRS::projection(ctx.setup.crs()); _projection = CRS::projection(ctx.setup.crs());
if (_projection.isNull()) { if (_projection.isNull()) {
_errorString = ctx.setup.crs() + ": unknown CRS"; _errorString = ctx.setup.crs() + ": unknown CRS";
return false; return false;
} }
if (!ctx.scaleDenominator.isValid()) {
_errorString = "Invalid scale denominator range";
return false;
}
if (ctx.boundingBox.isNull()) {
_errorString = "Missing bounding box";
return false;
}
_boundingBox = ctx.boundingBox; for (int i = 0; i < ctx.layers.size(); i++)
_scaleDenominator = ctx.scaleDenominator; _boundingBox |= ctx.layers.at(i).boundingBox;
for (int i = 0; i < ctx.layers.size(); i++)
_scaleDenominator |= ctx.layers.first().scaleDenominator;
return true; return true;
} }

View File

@ -55,17 +55,28 @@ public:
{_downloader = downloader;} {_downloader = downloader;}
private: private:
struct CTX { struct Layer {
const Setup &setup; QString name;
QString style;
RangeF scaleDenominator; RangeF scaleDenominator;
RectC boundingBox; RectC boundingBox;
bool layer; bool isDefined;
bool style; bool hasStyle;
bool format; bool hasCRS;
bool crs;
CTX(const Setup &setup) : setup(setup), layer(false), style(false), Layer(const QString &name, const QString &style = "default")
format(false), crs(false) {} : name(name), style(style), isDefined(false), hasStyle(false),
hasCRS(false) {}
bool operator==(const Layer &other) const
{return this->name == other.name;}
};
struct CTX {
const Setup &setup;
QList<Layer> layers;
bool formatSupported;
CTX(const Setup &setup);
}; };
RectC geographicBoundingBox(QXmlStreamReader &reader); RectC geographicBoundingBox(QXmlStreamReader &reader);