From 35703e3363e4124e5006fa6dab6f36e27cde639f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 22 Mar 2018 20:00:30 +0100 Subject: [PATCH] Refactoring --- src/map/geotiff.cpp | 54 ++++++++++++++++---------------------- src/map/geotiff.h | 9 ++++--- src/map/mapfile.cpp | 10 +++---- src/map/mapfile.h | 8 +++--- src/map/offlinemap.cpp | 59 +++++++++++++++++++----------------------- src/map/offlinemap.h | 13 ++++------ src/map/transform.cpp | 38 +++++++++++++++++++++++++-- src/map/transform.h | 14 +++++++--- src/map/wmtsmap.cpp | 8 +++--- src/map/wmtsmap.h | 4 +-- 10 files changed, 117 insertions(+), 100 deletions(-) diff --git a/src/map/geotiff.cpp b/src/map/geotiff.cpp index 431190c5..b8fb3ac8 100644 --- a/src/map/geotiff.cpp +++ b/src/map/geotiff.cpp @@ -448,7 +448,7 @@ bool GeoTIFF::geographicModel(QMap &kv) return true; } -bool GeoTIFF::load(const QString &path) +GeoTIFF::GeoTIFF(const QString &path) { quint32 ifd; QList points; @@ -462,86 +462,76 @@ bool GeoTIFF::load(const QString &path) if (!file.open(QIODevice::ReadOnly)) { _errorString = QString("Error opening TIFF file: %1") .arg(file.errorString()); - return false; + return; } if (!file.readHeader(ifd)) { _errorString = "Invalid TIFF header"; - return false; + return; } while (ifd) { if (!readIFD(file, ifd, ctx)) { _errorString = "Invalid IFD"; - return false; + return; } } if (!ctx.keys) { _errorString = "Not a GeoTIFF file"; - return false; + return; } if (ctx.scale) { if (!readScale(file, ctx.scale, scale)) { _errorString = "Error reading model pixel scale"; - return false; + return; } } if (ctx.tiepoints) { if (!readTiepoints(file, ctx.tiepoints, ctx.tiepointCount, points)) { _errorString = "Error reading raster->model tiepoint pairs"; - return false; + return; } } if (!readKeys(file, ctx, kv)) { _errorString = "Error reading Geo key/value"; - return false; + return; } switch (kv.value(GTModelTypeGeoKey).SHORT) { case ModelTypeProjected: if (!projectedModel(kv)) - return false; + return; break; case ModelTypeGeographic: if (!geographicModel(kv)) - return false; + return; break; case ModelTypeGeocentric: _errorString = "Geocentric models are not supported"; - return false; + return; default: _errorString = "Unknown/missing model type"; - return false; + return; } - if (ctx.scale && ctx.tiepoints) { - const ReferencePoint &p = points.first(); - _transform = QTransform(scale.x(), 0, 0, -scale.y(), p.pp.x() - p.xy.x() - / scale.x(), p.pp.y() + p.xy.x() / scale.y()).inverted(); - } else if (ctx.tiepointCount > 1) { - Transform t(points); - if (t.isNull()) { - _errorString = t.errorString(); - return false; - } - _transform = t.transform(); - } else if (ctx.matrix) { + if (ctx.scale && ctx.tiepoints) + _transform = Transform(points.first(), scale); + else if (ctx.tiepointCount > 1) + _transform = Transform(points); + else if (ctx.matrix) { double m[16]; if (!readMatrix(file, ctx.matrix, m)) { _errorString = "Error reading transformation matrix"; - return false; + return; } - if (m[2] != 0.0 || m[6] != 0.0 || m[8] != 0.0 || m[9] != 0.0 - || m[10] != 0.0 || m[11] != 0.0) { - _errorString = "Not a baseline transformation matrix"; - } - _transform = QTransform(m[0], m[1], m[4], m[5], m[3], m[7]).inverted(); + _transform = Transform(m); } else { _errorString = "Incomplete/missing model transformation info"; - return false; + return; } - return true; + if (!_transform.isValid()) + _errorString = _transform.errorString(); } diff --git a/src/map/geotiff.h b/src/map/geotiff.h index 2d663814..1d139053 100644 --- a/src/map/geotiff.h +++ b/src/map/geotiff.h @@ -3,7 +3,6 @@ #include #include -#include #include "transform.h" #include "projection.h" @@ -13,11 +12,13 @@ class GCS; class GeoTIFF { public: - bool load(const QString &path); + GeoTIFF(const QString &path); + + bool isValid() const {return _projection.isValid() && _transform.isValid();} const QString &errorString() const {return _errorString;} const Projection &projection() const {return _projection;} - const QTransform &transform() const {return _transform;} + const Transform &transform() const {return _transform;} private: union Value { @@ -52,7 +53,7 @@ private: bool geographicModel(QMap &kv); bool projectedModel(QMap &kv); - QTransform _transform; + Transform _transform; Projection _projection; QString _errorString; diff --git a/src/map/mapfile.cpp b/src/map/mapfile.cpp index f17ff0f3..b9b4194a 100644 --- a/src/map/mapfile.cpp +++ b/src/map/mapfile.cpp @@ -238,14 +238,12 @@ bool MapFile::computeTransformation(QList &points) rp.append(points.at(i).rp); } - Transform t(rp); - if (t.isNull()) { - _errorString = t.errorString(); + _transform = Transform(rp); + if (!_transform.isValid()) { + _errorString = _transform.errorString(); return false; } - _transform = t.transform(); - return true; } @@ -263,5 +261,5 @@ MapFile::MapFile(QIODevice &file) if (!createProjection(gcs, ct, setup, points)) return; if (!computeTransformation(points)) - _image = QString(); + return; } diff --git a/src/map/mapfile.h b/src/map/mapfile.h index d4b29cc8..cdf9e39c 100644 --- a/src/map/mapfile.h +++ b/src/map/mapfile.h @@ -1,7 +1,6 @@ #ifndef MAPFILE_H #define MAPFILE_H -#include #include "transform.h" #include "projection.h" @@ -13,11 +12,12 @@ class MapFile public: MapFile(QIODevice &file); - bool isValid() const {return !_image.isNull() && _projection.isValid();} + bool isValid() const + {return !_image.isNull() && _projection.isValid() && _transform.isValid();} const QString &errorString() const {return _errorString;} const Projection &projection() const {return _projection;} - const QTransform &transform() const {return _transform;} + const Transform &transform() const {return _transform;} const QString &name() const {return _name;} const QString &image() const {return _image;} @@ -44,7 +44,7 @@ private: QSize _size; Projection _projection; - QTransform _transform; + Transform _transform; QString _errorString; }; diff --git a/src/map/offlinemap.cpp b/src/map/offlinemap.cpp index 68eea6b2..21f11c56 100644 --- a/src/map/offlinemap.cpp +++ b/src/map/offlinemap.cpp @@ -139,8 +139,8 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) _transform = mf.transform(); } } else if (suffix == "tif" || suffix == "tiff") { - GeoTIFF gt; - if (!gt.load(fileName)) { + GeoTIFF gt(fileName); + if (!gt.isValid()) { _errorString = gt.errorString(); return; } else { @@ -168,8 +168,6 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) } } - _inverted = _transform.inverted(); - _valid = true; } @@ -198,7 +196,6 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) _map.size = mf.size(); _projection = mf.projection(); _transform = mf.transform(); - _inverted = _transform.inverted(); _tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar"); _valid = true; @@ -328,28 +325,23 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect) QPointF OfflineMap::ll2xy(const Coordinates &c) const { - if (_ozf) { - QPointF p(_transform.map(_projection.ll2xy(c))); - return QPointF(p.x() * _scale.x(), p.y() * _scale.y()); - } else - return _transform.map(_projection.ll2xy(c)); + QPointF p(_transform.proj2img(_projection.ll2xy(c))); + return _ozf ? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) : p; } Coordinates OfflineMap::xy2ll(const QPointF &p) const { - if (_ozf) { - return _projection.xy2ll(_inverted.map(QPointF(p.x() / _scale.x(), - p.y() / _scale.y()))); - } else - return _projection.xy2ll(_inverted.map(p)); + return _ozf + ? _projection.xy2ll(_transform.img2proj(QPointF(p.x() / _scale.x(), + p.y() / _scale.y()))) + : _projection.xy2ll(_transform.img2proj(p)); } QRectF OfflineMap::bounds() const { - if (_ozf) - return QRectF(QPointF(0, 0), _ozf->size(_zoom)); - else - return QRectF(QPointF(0, 0), _map.size); + return _ozf + ? QRectF(QPointF(0, 0), _ozf->size(_zoom)) + : QRectF(QPointF(0, 0), _map.size); } qreal OfflineMap::resolution(const QRectF &rect) const @@ -363,22 +355,23 @@ qreal OfflineMap::resolution(const QRectF &rect) const return ds/ps; } -int OfflineMap::zoomFit(const QSize &size, const RectC &br) +int OfflineMap::zoomFit(const QSize &size, const RectC &rect) { - if (_ozf) { - if (!br.isValid()) - rescale(0); - else { - QRect sbr(QRectF(_transform.map(_projection.ll2xy(br.topLeft())), - _transform.map(_projection.ll2xy(br.bottomRight()))) - .toRect().normalized()); + if (!_ozf) + return _zoom; - for (int i = 0; i < _ozf->zooms(); i++) { - rescale(i); - if (sbr.size().width() * _scale.x() <= size.width() - && sbr.size().height() * _scale.y() <= size.height()) - break; - } + if (!rect.isValid()) + rescale(0); + else { + QPointF tl(_transform.proj2img(_projection.ll2xy(rect.topLeft()))); + QPointF br(_transform.proj2img(_projection.ll2xy(rect.bottomRight()))); + QRect sbr(QRectF(tl, br).toRect().normalized()); + + for (int i = 0; i < _ozf->zooms(); i++) { + rescale(i); + if (sbr.size().width() * _scale.x() <= size.width() + && sbr.size().height() * _scale.y() <= size.height()) + break; } } diff --git a/src/map/offlinemap.h b/src/map/offlinemap.h index 2dc68faa..f8280425 100644 --- a/src/map/offlinemap.h +++ b/src/map/offlinemap.h @@ -1,7 +1,7 @@ #ifndef OFFLINEMAP_H #define OFFLINEMAP_H -#include +#include "transform.h" #include "projection.h" #include "map.h" @@ -24,7 +24,7 @@ public: qreal resolution(const QRectF &rect) const; int zoom() const {return _zoom;} - int zoomFit(const QSize &size, const RectC &br); + int zoomFit(const QSize &size, const RectC &rect); int zoomIn(); int zoomOut(); @@ -44,9 +44,9 @@ public: QPointF ll2pp(const Coordinates &c) const {return _projection.ll2xy(c);} QPointF xy2pp(const QPointF &p) const - {return _inverted.map(p);} + {return _transform.img2proj(p);} QPointF pp2xy(const QPointF &p) const - {return _transform.map(p);} + {return _transform.proj2img(p);} private: struct ImageInfo { @@ -69,15 +69,12 @@ private: void rescale(int zoom); QString _name; - Projection _projection; - QTransform _transform, _inverted; - + Transform _transform; QImage *_img; Tar *_tar; OZF *_ozf; ImageInfo _map, _tile; - int _zoom; QPointF _scale; diff --git a/src/map/transform.cpp b/src/map/transform.cpp index b732ec71..2393e23a 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -2,6 +2,9 @@ #include "matrix.h" #include "transform.h" + +#define NULL_QTRANSFORM 0,0,0,0,0,0,0,0,0 + void Transform::simple(const QList &points) { if (points.at(0).xy.x() == points.at(1).xy.x() @@ -18,7 +21,8 @@ void Transform::simple(const QList &points) dX = points.at(1).xy.x() - points.at(1).pp.x() * sX; dY = points.at(0).xy.y() - points.at(0).pp.y() * sY; - _transform = QTransform(sX, 0, 0, sY, dX, dY); + _proj2img = QTransform(sX, 0, 0, sY, dX, dY); + _img2proj = _proj2img.inverted(); } void Transform::affine(const QList &points) @@ -59,8 +63,15 @@ void Transform::affine(const QList &points) return; } - _transform = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3), + _proj2img = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3), M.m(2,4)); + _img2proj = _proj2img.inverted(); +} + + +Transform::Transform() + : _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM) +{ } Transform::Transform(const QList &points) @@ -73,6 +84,29 @@ Transform::Transform(const QList &points) affine(points); } +Transform::Transform(const ReferencePoint &p, const QPointF &scale) + : _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM) +{ + if (scale.x() == 0.0 || scale.y() == 0.0) { + _errorString = "Invalid scale factor"; + return; + } + + _img2proj = QTransform(scale.x(), 0, 0, -scale.y(), p.pp.x() - p.xy.x() + / scale.x(), p.pp.y() + p.xy.x() / scale.y()); + _proj2img = _img2proj.inverted(); +} + +Transform::Transform(double m[16]) + : _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM) +{ + _img2proj = QTransform(m[0], m[1], m[4], m[5], m[3], m[7]); + if (!_img2proj.isInvertible()) + _errorString = "Singular transformation matrix"; + else + _proj2img = _img2proj.inverted(); +} + #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const ReferencePoint &p) { diff --git a/src/map/transform.h b/src/map/transform.h index ffdde775..b9d88df7 100644 --- a/src/map/transform.h +++ b/src/map/transform.h @@ -3,7 +3,7 @@ #include #include -#include "common/coordinates.h" +#include struct ReferencePoint { QPoint xy; @@ -13,17 +13,23 @@ struct ReferencePoint { class Transform { public: + Transform(); Transform(const QList &points); + Transform(const ReferencePoint &p, const QPointF &scale); + Transform(double m[16]); - bool isNull() {return _transform.type() == QTransform::TxNone;} + QPointF proj2img(const QPointF &p) const {return _proj2img.map(p);} + QPointF img2proj(const QPointF &p) const {return _img2proj.map(p);} + + bool isValid() const + {return _proj2img.isInvertible() && _img2proj.isInvertible();} const QString &errorString() const {return _errorString;} - const QTransform &transform() const {return _transform;} private: void simple(const QList &points); void affine(const QList &points); - QTransform _transform; + QTransform _proj2img, _img2proj; QString _errorString; }; diff --git a/src/map/wmtsmap.cpp b/src/map/wmtsmap.cpp index f69fb2d5..87522cd7 100644 --- a/src/map/wmtsmap.cpp +++ b/src/map/wmtsmap.cpp @@ -61,9 +61,7 @@ void WMTSMap::updateTransform() QList points; points << tl << br; - Transform tr(points); - _transform = tr.transform(); - _inverted = _transform.inverted(); + _transform = Transform(points); } void WMTSMap::load() @@ -198,10 +196,10 @@ void WMTSMap::draw(QPainter *painter, const QRectF &rect) QPointF WMTSMap::ll2xy(const Coordinates &c) const { - return _transform.map(_projection.ll2xy(c)); + return _transform.proj2img(_projection.ll2xy(c)); } Coordinates WMTSMap::xy2ll(const QPointF &p) const { - return _projection.xy2ll(_inverted.map(p)); + return _projection.xy2ll(_transform.img2proj(p)); } diff --git a/src/map/wmtsmap.h b/src/map/wmtsmap.h index 48e93540..b0465d83 100644 --- a/src/map/wmtsmap.h +++ b/src/map/wmtsmap.h @@ -1,7 +1,7 @@ #ifndef WMTSMAP_H #define WMTSMAP_H -#include +#include "transform.h" #include "projection.h" #include "map.h" #include "wmts.h" @@ -57,7 +57,7 @@ private: RectC _bounds; QList _zooms; Projection _projection; - QTransform _transform, _inverted; + Transform _transform; int _zoom; bool _block;