mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 11:45:53 +01:00
Added support for WMS multi-layer maps
This commit is contained in:
parent
60cc869ade
commit
e845e216bd
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user