From 7d8dcec88b2870cf2e4b7dbc87a736c7ee047e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 14 Dec 2020 22:06:59 +0100 Subject: [PATCH] Try to break even less bounding box transformations --- src/GUI/mapitem.cpp | 2 -- src/map/IMG/rastertile.cpp | 1 - src/map/imgmap.cpp | 18 +++++++---- src/map/rectd.cpp | 61 ++++++++------------------------------ src/map/rectd.h | 3 ++ src/map/wmtsmap.cpp | 48 ++++++++++++++++++++++-------- src/map/wmtsmap.h | 3 ++ 7 files changed, 66 insertions(+), 70 deletions(-) diff --git a/src/GUI/mapitem.cpp b/src/GUI/mapitem.cpp index 47f56a61..a7a46d2c 100644 --- a/src/GUI/mapitem.cpp +++ b/src/GUI/mapitem.cpp @@ -89,8 +89,6 @@ MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent) _name = src->name(); _fileName = src->path(); - // Zoom to the maximal zoom level to get the most accurate bounds - src->zoomFit(QSize(), RectC()); _bounds = src->llBounds(); connect(this, SIGNAL(triggered()), action, SLOT(trigger())); diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index da4dcb5f..a4c54221 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -454,4 +454,3 @@ void RasterTile::processPoints(QList &textItems) delete item; } } - diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index b7173929..dc854a0e 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -171,7 +171,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) polyRect &= bounds(); RectD polyRectD(_transform.img2proj(polyRect.topLeft()), _transform.img2proj(polyRect.bottomRight())); - _data.at(n)->polys(polyRectD.toRectC(_projection, 4), _zoom, + _data.at(n)->polys(polyRectD.toRectC(_projection, 20), _zoom, &polygons, &lines); QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, @@ -180,7 +180,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) pointRect &= bounds(); RectD pointRectD(_transform.img2proj(pointRect.topLeft()), _transform.img2proj(pointRect.bottomRight())); - _data.at(n)->points(pointRectD.toRectC(_projection, 4), + _data.at(n)->points(pointRectD.toRectC(_projection, 20), _zoom, &points); tiles.append(RasterTile(this, _data.at(n)->style(), _zoom, @@ -212,10 +212,18 @@ void IMGMap::setProjection(const Projection &projection) return; _projection = projection; - // Limit the bounds for some well known Mercator projections + // Limit the bounds for some well known projections // (world maps have N/S bounds up to 90/-90!) - _dataBounds = (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395)) - ? _data.first()->bounds() & OSM::BOUNDS : _data.first()->bounds(); + if (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395)) + _dataBounds = _data.first()->bounds() & OSM::BOUNDS; + else if (_projection == PCS::pcs(3031) || _projection == PCS::pcs(3976)) + _dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, -60), + Coordinates(180, -90)); + else if (_projection == PCS::pcs(3995) || _projection == PCS::pcs(3413)) + _dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, 90), + Coordinates(180, 60)); + else + _dataBounds = _data.first()->bounds(); updateTransform(); QPixmapCache::clear(); diff --git a/src/map/rectd.cpp b/src/map/rectd.cpp index b0b4f995..fba279b2 100644 --- a/src/map/rectd.cpp +++ b/src/map/rectd.cpp @@ -4,66 +4,30 @@ #include "rectd.h" -static void growLeft(const Projection &proj, const Coordinates &c, RectD &rect) +static void growRect(const Projection &proj, const Coordinates &c, RectD &rect) { PointD p(proj.ll2xy(c)); if (p.x() < rect.left()) rect.setLeft(p.x()); -} - -static void growRight(const Projection &proj, const Coordinates &c, RectD &rect) -{ - PointD p(proj.ll2xy(c)); - if (p.x() > rect.right()) rect.setRight(p.x()); -} - -static void growTop(const Projection &proj, const Coordinates &c, RectD &rect) -{ - PointD p(proj.ll2xy(c)); - if (p.y() > rect.top()) rect.setTop(p.y()); -} - -static void growBottom(const Projection &proj, const Coordinates &c, RectD &rect) -{ - PointD p(proj.ll2xy(c)); - if (p.y() < rect.bottom()) rect.setBottom(p.y()); } -static void growLeft(const Projection &proj, const PointD &p, RectC &rect) +static void growRect(const Projection &proj, const PointD &p, RectC &rect) { Coordinates c(proj.xy2ll(p)); if (c.lon() < rect.left()) rect.setLeft(c.lon()); -} - -static void growRight(const Projection &proj, const PointD &p, RectC &rect) -{ - Coordinates c(proj.xy2ll(p)); - if (c.lon() > rect.right()) rect.setRight(c.lon()); -} - -static void growTop(const Projection &proj, const PointD &p, RectC &rect) -{ - Coordinates c(proj.xy2ll(p)); - if (c.lat() > rect.top()) rect.setTop(c.lat()); -} - -static void growBottom(const Projection &proj, const PointD &p, RectC &rect) -{ - Coordinates c(proj.xy2ll(p)); - if (c.lat() < rect.bottom()) rect.setBottom(c.lat()); } @@ -82,14 +46,14 @@ RectD::RectD(const RectC &rect, const Projection &proj, int samples) for (int i = 0; i <= samples; i++) { double x = remainder(rect.left() + i * dx, 360.0); - growBottom(proj, Coordinates(x, rect.bottom()), prect); - growTop(proj, Coordinates(x, rect.top()), prect); + growRect(proj, Coordinates(x, rect.bottom()), prect); + growRect(proj, Coordinates(x, rect.top()), prect); } for (int i = 0; i <= samples; i++) { double y = rect.bottom() + i * dy; - growLeft(proj, Coordinates(rect.left(), y), prect); - growRight(proj, Coordinates(rect.right(), y), prect); + growRect(proj, Coordinates(rect.left(), y), prect); + growRect(proj, Coordinates(rect.right(), y), prect); } *this = prect; @@ -103,20 +67,19 @@ RectC RectD::toRectC(const Projection &proj, int samples) const double dx = width() / samples; double dy = height() / samples; - Coordinates tl(proj.xy2ll(topLeft())); - Coordinates br(proj.xy2ll(bottomRight())); - RectC rect(tl, br); + Coordinates c(proj.xy2ll(center())); + RectC rect(c, c); for (int i = 0; i <= samples; i++) { double x = left() + i * dx; - growBottom(proj, PointD(x, bottom()), rect); - growTop(proj, PointD(x, top()), rect); + growRect(proj, PointD(x, bottom()), rect); + growRect(proj, PointD(x, top()), rect); } for (int i = 0; i <= samples; i++) { double y = bottom() + i * dy; - growLeft(proj, PointD(left(), y), rect); - growRight(proj, PointD(right(), y), rect); + growRect(proj, PointD(left(), y), rect); + growRect(proj, PointD(right(), y), rect); } return rect; diff --git a/src/map/rectd.h b/src/map/rectd.h index e41140c3..c8355b40 100644 --- a/src/map/rectd.h +++ b/src/map/rectd.h @@ -16,6 +16,9 @@ public: PointD topLeft() const {return _tl;} PointD bottomRight() const {return _br;} + PointD center() const + {return PointD((_tl.x() + _br.x()) / 2.0, + (_tl.y() + _br.y()) / 2.0);} double left() const {return _tl.x();} double right() const {return _br.x();} diff --git a/src/map/wmtsmap.cpp b/src/map/wmtsmap.cpp index c6bb2b8e..92ce6f71 100644 --- a/src/map/wmtsmap.cpp +++ b/src/map/wmtsmap.cpp @@ -55,9 +55,9 @@ double WMTSMap::sd2res(double scaleDenominator) const * _wmts->projection().units().fromMeters(1.0); } -void WMTSMap::updateTransform() +Transform WMTSMap::transform(int zoom) const { - const WMTS::Zoom &z = _wmts->zooms().at(_zoom); + const WMTS::Zoom &z = _wmts->zooms().at(zoom); PointD topLeft = (_wmts->cs().axisOrder() == CoordinateSystem::YX) ? PointD(z.topLeft().y(), z.topLeft().x()) : z.topLeft(); @@ -65,28 +65,50 @@ void WMTSMap::updateTransform() double pixelSpan = sd2res(z.scaleDenominator()); if (_wmts->projection().isGeographic()) pixelSpan /= deg2rad(WGS84_RADIUS); - _transform = Transform(ReferencePoint(PointD(0, 0), topLeft), + return Transform(ReferencePoint(PointD(0, 0), topLeft), PointD(pixelSpan, pixelSpan)); } -QRectF WMTSMap::bounds() +QRectF WMTSMap::tileBounds(int zoom) const { - const WMTS::Zoom &z = _wmts->zooms().at(_zoom); - QRectF tileBounds, bounds; + const WMTS::Zoom &z = _wmts->zooms().at(zoom); - tileBounds = (z.limits().isNull()) ? - QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(), + return (z.limits().isNull()) + ? QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(), z.tile().height() * z.matrix().height())) : QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top() * z.tile().height()), QSize(z.tile().width() * z.limits().width(), z.tile().height() * z.limits().height())); +} - if (_bounds.isValid()) - bounds = QRectF(_transform.proj2img(_bounds.topLeft()) - / coordinatesRatio(), _transform.proj2img( - _bounds.bottomRight()) / coordinatesRatio()); +void WMTSMap::updateTransform() +{ + _transform = transform(_zoom); +} - return bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds; +QRectF WMTSMap::bounds() +{ + QRectF tb(tileBounds(_zoom)); + QRectF lb = _bounds.isValid() + ? QRectF(_transform.proj2img(_bounds.topLeft()) / coordinatesRatio(), + _transform.proj2img(_bounds.bottomRight()) / coordinatesRatio()) + : QRectF(); + + return lb.isValid() ? lb & tb : tb; +} + +RectC WMTSMap::llBounds() +{ + if (_wmts->bbox().isValid()) + return _wmts->bbox(); + else { + int maxZoom = _wmts->zooms().size() - 1; + QRectF tb(tileBounds(maxZoom)); + Transform t(transform(maxZoom)); + RectD rect(t.img2proj(tb.topLeft() * coordinatesRatio()), + t.img2proj(tb.bottomRight() * coordinatesRatio())); + return rect.toRectC(_wmts->projection()); + } } int WMTSMap::zoomFit(const QSize &size, const RectC &rect) diff --git a/src/map/wmtsmap.h b/src/map/wmtsmap.h index ad67b28a..4b23c7e2 100644 --- a/src/map/wmtsmap.h +++ b/src/map/wmtsmap.h @@ -20,6 +20,7 @@ public: QString name() const {return _name;} QRectF bounds(); + RectC llBounds(); int zoom() const {return _zoom;} void setZoom(int zoom); @@ -45,6 +46,8 @@ private slots: private: double sd2res(double scaleDenominator) const; + Transform transform(int zoom) const; + QRectF tileBounds(int zoom) const; void updateTransform(); QSizeF tileSize(const WMTS::Zoom &zoom) const; qreal coordinatesRatio() const;