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:
parent
561d8362a9
commit
7d8dcec88b
@ -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()));
|
||||||
|
@ -454,4 +454,3 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
|
|||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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();}
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user