1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-01-31 09:05:14 +01:00

Try to break even less bounding box transformations

This commit is contained in:
Martin Tůma 2020-12-14 22:06:59 +01:00
parent 561d8362a9
commit 7d8dcec88b
7 changed files with 66 additions and 70 deletions

View File

@ -89,8 +89,6 @@ MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
_name = src->name(); _name = src->name();
_fileName = src->path(); _fileName = src->path();
// Zoom to the maximal zoom level to get the most accurate bounds
src->zoomFit(QSize(), RectC());
_bounds = src->llBounds(); _bounds = src->llBounds();
connect(this, SIGNAL(triggered()), action, SLOT(trigger())); connect(this, SIGNAL(triggered()), action, SLOT(trigger()));

View File

@ -454,4 +454,3 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
delete item; delete item;
} }
} }

View File

@ -171,7 +171,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
polyRect &= bounds(); polyRect &= bounds();
RectD polyRectD(_transform.img2proj(polyRect.topLeft()), RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
_transform.img2proj(polyRect.bottomRight())); _transform.img2proj(polyRect.bottomRight()));
_data.at(n)->polys(polyRectD.toRectC(_projection, 4), _zoom, _data.at(n)->polys(polyRectD.toRectC(_projection, 20), _zoom,
&polygons, &lines); &polygons, &lines);
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
@ -180,7 +180,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
pointRect &= bounds(); pointRect &= bounds();
RectD pointRectD(_transform.img2proj(pointRect.topLeft()), RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
_transform.img2proj(pointRect.bottomRight())); _transform.img2proj(pointRect.bottomRight()));
_data.at(n)->points(pointRectD.toRectC(_projection, 4), _data.at(n)->points(pointRectD.toRectC(_projection, 20),
_zoom, &points); _zoom, &points);
tiles.append(RasterTile(this, _data.at(n)->style(), _zoom, tiles.append(RasterTile(this, _data.at(n)->style(), _zoom,
@ -212,10 +212,18 @@ void IMGMap::setProjection(const Projection &projection)
return; return;
_projection = projection; _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!) // (world maps have N/S bounds up to 90/-90!)
_dataBounds = (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395)) if (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395))
? _data.first()->bounds() & OSM::BOUNDS : _data.first()->bounds(); _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(); updateTransform();
QPixmapCache::clear(); QPixmapCache::clear();

View File

@ -4,66 +4,30 @@
#include "rectd.h" #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)); PointD p(proj.ll2xy(c));
if (p.x() < rect.left()) if (p.x() < rect.left())
rect.setLeft(p.x()); 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()) if (p.x() > rect.right())
rect.setRight(p.x()); 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()) if (p.y() > rect.top())
rect.setTop(p.y()); 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()) if (p.y() < rect.bottom())
rect.setBottom(p.y()); 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)); Coordinates c(proj.xy2ll(p));
if (c.lon() < rect.left()) if (c.lon() < rect.left())
rect.setLeft(c.lon()); 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()) if (c.lon() > rect.right())
rect.setRight(c.lon()); 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()) if (c.lat() > rect.top())
rect.setTop(c.lat()); 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()) if (c.lat() < rect.bottom())
rect.setBottom(c.lat()); 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++) { for (int i = 0; i <= samples; i++) {
double x = remainder(rect.left() + i * dx, 360.0); double x = remainder(rect.left() + i * dx, 360.0);
growBottom(proj, Coordinates(x, rect.bottom()), prect); growRect(proj, Coordinates(x, rect.bottom()), prect);
growTop(proj, Coordinates(x, rect.top()), prect); growRect(proj, Coordinates(x, rect.top()), prect);
} }
for (int i = 0; i <= samples; i++) { for (int i = 0; i <= samples; i++) {
double y = rect.bottom() + i * dy; double y = rect.bottom() + i * dy;
growLeft(proj, Coordinates(rect.left(), y), prect); growRect(proj, Coordinates(rect.left(), y), prect);
growRight(proj, Coordinates(rect.right(), y), prect); growRect(proj, Coordinates(rect.right(), y), prect);
} }
*this = prect; *this = prect;
@ -103,20 +67,19 @@ RectC RectD::toRectC(const Projection &proj, int samples) const
double dx = width() / samples; double dx = width() / samples;
double dy = height() / samples; double dy = height() / samples;
Coordinates tl(proj.xy2ll(topLeft())); Coordinates c(proj.xy2ll(center()));
Coordinates br(proj.xy2ll(bottomRight())); RectC rect(c, c);
RectC rect(tl, br);
for (int i = 0; i <= samples; i++) { for (int i = 0; i <= samples; i++) {
double x = left() + i * dx; double x = left() + i * dx;
growBottom(proj, PointD(x, bottom()), rect); growRect(proj, PointD(x, bottom()), rect);
growTop(proj, PointD(x, top()), rect); growRect(proj, PointD(x, top()), rect);
} }
for (int i = 0; i <= samples; i++) { for (int i = 0; i <= samples; i++) {
double y = bottom() + i * dy; double y = bottom() + i * dy;
growLeft(proj, PointD(left(), y), rect); growRect(proj, PointD(left(), y), rect);
growRight(proj, PointD(right(), y), rect); growRect(proj, PointD(right(), y), rect);
} }
return rect; return rect;

View File

@ -16,6 +16,9 @@ public:
PointD topLeft() const {return _tl;} PointD topLeft() const {return _tl;}
PointD bottomRight() const {return _br;} 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 left() const {return _tl.x();}
double right() const {return _br.x();} double right() const {return _br.x();}

View File

@ -55,9 +55,9 @@ double WMTSMap::sd2res(double scaleDenominator) const
* _wmts->projection().units().fromMeters(1.0); * _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 topLeft = (_wmts->cs().axisOrder() == CoordinateSystem::YX)
? PointD(z.topLeft().y(), z.topLeft().x()) : z.topLeft(); ? PointD(z.topLeft().y(), z.topLeft().x()) : z.topLeft();
@ -65,28 +65,50 @@ void WMTSMap::updateTransform()
double pixelSpan = sd2res(z.scaleDenominator()); double pixelSpan = sd2res(z.scaleDenominator());
if (_wmts->projection().isGeographic()) if (_wmts->projection().isGeographic())
pixelSpan /= deg2rad(WGS84_RADIUS); pixelSpan /= deg2rad(WGS84_RADIUS);
_transform = Transform(ReferencePoint(PointD(0, 0), topLeft), return Transform(ReferencePoint(PointD(0, 0), topLeft),
PointD(pixelSpan, pixelSpan)); PointD(pixelSpan, pixelSpan));
} }
QRectF WMTSMap::bounds() QRectF WMTSMap::tileBounds(int zoom) const
{ {
const WMTS::Zoom &z = _wmts->zooms().at(_zoom); const WMTS::Zoom &z = _wmts->zooms().at(zoom);
QRectF tileBounds, bounds;
tileBounds = (z.limits().isNull()) ? return (z.limits().isNull())
QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(), ? QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(),
z.tile().height() * z.matrix().height())) z.tile().height() * z.matrix().height()))
: QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top() : QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top()
* z.tile().height()), QSize(z.tile().width() * z.limits().width(), * z.tile().height()), QSize(z.tile().width() * z.limits().width(),
z.tile().height() * z.limits().height())); z.tile().height() * z.limits().height()));
}
if (_bounds.isValid()) void WMTSMap::updateTransform()
bounds = QRectF(_transform.proj2img(_bounds.topLeft()) {
/ coordinatesRatio(), _transform.proj2img( _transform = transform(_zoom);
_bounds.bottomRight()) / coordinatesRatio()); }
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) int WMTSMap::zoomFit(const QSize &size, const RectC &rect)

View File

@ -20,6 +20,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds();
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -45,6 +46,8 @@ private slots:
private: private:
double sd2res(double scaleDenominator) const; double sd2res(double scaleDenominator) const;
Transform transform(int zoom) const;
QRectF tileBounds(int zoom) const;
void updateTransform(); void updateTransform();
QSizeF tileSize(const WMTS::Zoom &zoom) const; QSizeF tileSize(const WMTS::Zoom &zoom) const;
qreal coordinatesRatio() const; qreal coordinatesRatio() const;