mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Various KMZ map fixes
This commit is contained in:
parent
86dd6ed772
commit
07894f3a55
@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
WARNING: This code uses internal Qt API - the QZipReader class for reading
|
WARNING: This code uses internal Qt API - the QZipReader class for reading
|
||||||
ZIP files - and things may break if Qt changes the API. For Qt5 this is not
|
ZIP files - and things may break if Qt changes the API. For Qt5 this is not
|
||||||
a problem as we can "see the feature" now and there are no changes in all
|
a problem as we can "see the future" now and there are no changes in all
|
||||||
the supported Qt5 versions up to the last one (5.15). In Qt6 the class
|
the supported Qt5 versions up to the last one (5.15). In Qt6 the class
|
||||||
might change or even disappear in the future, but this is very unlikely
|
might change or even disappear in the future, but this is very unlikely
|
||||||
as there were no changes for several years and The Qt Company's politics
|
as there were no changes for several years and The Qt Company's politics
|
||||||
is: "do not invest any resources into any desktop platform stuff unless
|
is: "do not invest any resources into any desktop related stuff unless
|
||||||
absolutely necessary". There is an issue (QTBUG-3897) since year 2009 to
|
absolutely necessary". There is an issue (QTBUG-3897) since the year 2009 to
|
||||||
include the ZIP reader into the public API, which aptly illustrates the
|
include the ZIP reader into the public API, which aptly illustrates the
|
||||||
effort The Qt Company is willing to make about anything desktop related...
|
effort The Qt Company is willing to make about anything desktop related...
|
||||||
*/
|
*/
|
||||||
@ -25,24 +25,24 @@
|
|||||||
|
|
||||||
#define ZOOM_THRESHOLD 0.9
|
#define ZOOM_THRESHOLD 0.9
|
||||||
|
|
||||||
#define TL(m) ((m).bbox.topLeft())
|
#define TL(m) ((m).bbox().topLeft())
|
||||||
#define BR(m) ((m).bbox.bottomRight())
|
#define BR(m) ((m).bbox().bottomRight())
|
||||||
|
|
||||||
const Projection &KMZMap::Overlay::projection()
|
|
||||||
{
|
|
||||||
static Projection p = Projection(PCS::pcs(3857));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
KMZMap::Overlay::Overlay(const QString &path, const QSize &size,
|
KMZMap::Overlay::Overlay(const QString &path, const QSize &size,
|
||||||
const RectC &bbox, double rotation) : path(path), size(size), bbox(bbox),
|
const RectC &bbox, double rotation) : _path(path), _bbox(bbox),
|
||||||
rotation(rotation), img(0)
|
_rotation(rotation), _img(0)
|
||||||
{
|
{
|
||||||
ReferencePoint tl(PointD(0, 0), projection().ll2xy(bbox.topLeft()));
|
ReferencePoint tl(PointD(0, 0), PointD(bbox.left(), bbox.top()));
|
||||||
ReferencePoint br(PointD(size.width(), size.height()),
|
ReferencePoint br(PointD(size.width(), size.height()),
|
||||||
projection().ll2xy(bbox.bottomRight()));
|
PointD(bbox.right(), bbox.bottom()));
|
||||||
|
|
||||||
transform = Transform(tl, br);
|
QTransform t;
|
||||||
|
t.rotate(-rotation);
|
||||||
|
QRectF b(0, 0, size.width(), size.height());
|
||||||
|
QPolygonF ma = t.map(b);
|
||||||
|
_bounds = ma.boundingRect();
|
||||||
|
|
||||||
|
_transform = Transform(tl, br);
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal KMZMap::Overlay::resolution(const QRectF &rect) const
|
qreal KMZMap::Overlay::resolution(const QRectF &rect) const
|
||||||
@ -59,32 +59,34 @@ qreal KMZMap::Overlay::resolution(const QRectF &rect) const
|
|||||||
|
|
||||||
void KMZMap::Overlay::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
void KMZMap::Overlay::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||||
{
|
{
|
||||||
if (img) {
|
if (_img) {
|
||||||
if (rotation) {
|
if (_rotation) {
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->rotate(-rotation);
|
painter->rotate(-_rotation);
|
||||||
img->draw(painter, rect.adjusted(-10, -10, 10, 10), flags);
|
_img->draw(painter, rect, flags);
|
||||||
painter->restore();
|
painter->restore();
|
||||||
} else
|
} else
|
||||||
img->draw(painter, rect, flags);
|
_img->draw(painter, rect, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//painter->setPen(Qt::red);
|
||||||
|
//painter->drawRect(_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KMZMap::Overlay::load(QZipReader *zip)
|
void KMZMap::Overlay::load(QZipReader *zip)
|
||||||
{
|
{
|
||||||
if (!img) {
|
if (!_img) {
|
||||||
QByteArray ba(zip->fileData(path));
|
QByteArray ba(zip->fileData(_path));
|
||||||
img = new Image(QImage::fromData(ba));
|
_img = new Image(QImage::fromData(ba));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KMZMap::Overlay::unload()
|
void KMZMap::Overlay::unload()
|
||||||
{
|
{
|
||||||
delete img;
|
delete _img;
|
||||||
img = 0;
|
_img = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool KMZMap::resCmp(const Overlay &m1, const Overlay &m2)
|
bool KMZMap::resCmp(const Overlay &m1, const Overlay &m2)
|
||||||
{
|
{
|
||||||
qreal r1, r2;
|
qreal r1, r2;
|
||||||
@ -130,24 +132,30 @@ void KMZMap::computeBounds()
|
|||||||
m.append(_maps.at(i));
|
m.append(_maps.at(i));
|
||||||
|
|
||||||
std::sort(m.begin(), m.end(), xCmp);
|
std::sort(m.begin(), m.end(), xCmp);
|
||||||
offsets[_maps.indexOf(m.first())].setX(0);
|
offsets[_maps.indexOf(m.first())].setX(m.first().bounds().left());
|
||||||
for (int i = 1; i < m.size(); i++) {
|
for (int i = 1; i < m.size(); i++) {
|
||||||
qreal w = m.first().ll2xy(TL(m.at(i))).x();
|
qreal w = m.first().ll2xy(TL(m.at(i))).x();
|
||||||
offsets[_maps.indexOf(m.at(i))].setX(w);
|
offsets[_maps.indexOf(m.at(i))].setX(w + m.at(i).bounds().left());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(m.begin(), m.end(), yCmp);
|
std::sort(m.begin(), m.end(), yCmp);
|
||||||
offsets[_maps.indexOf(m.first())].setY(0);
|
offsets[_maps.indexOf(m.first())].setY(m.first().bounds().top());
|
||||||
for (int i = 1; i < m.size(); i++) {
|
for (int i = 1; i < m.size(); i++) {
|
||||||
qreal h = m.first().ll2xy(TL(m.at(i))).y();
|
qreal h = m.first().ll2xy(TL(m.at(i))).y();
|
||||||
offsets[_maps.indexOf(m.at(i))].setY(h);
|
offsets[_maps.indexOf(m.at(i))].setY(h + m.at(i).bounds().top());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_adjust = 0;
|
||||||
_bounds = QVector<Bounds>(_maps.count());
|
_bounds = QVector<Bounds>(_maps.count());
|
||||||
for (int i = 0; i < _maps.count(); i++)
|
for (int i = 0; i < _maps.count(); i++) {
|
||||||
_bounds[i] = Bounds(_maps.at(i).bbox,
|
QRectF xy(offsets.at(i), _maps.at(i).bounds().size());
|
||||||
QRectF(offsets.at(i), _maps.at(i).size));
|
|
||||||
|
_bounds[i] = Bounds(_maps.at(i).bbox(), xy);
|
||||||
|
_adjust = qMin(qMin(_maps.at(i).bounds().left(),
|
||||||
|
_maps.at(i).bounds().top()), _adjust);
|
||||||
|
}
|
||||||
|
_adjust = -_adjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -243,7 +251,7 @@ void KMZMap::document(QXmlStreamReader &reader, QZipReader &zip)
|
|||||||
void KMZMap::folder(QXmlStreamReader &reader, QZipReader &zip)
|
void KMZMap::folder(QXmlStreamReader &reader, QZipReader &zip)
|
||||||
{
|
{
|
||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == QLatin1String("Placemark"))
|
if (reader.name() == QLatin1String("GroundOverlay"))
|
||||||
groundOverlay(reader, zip);
|
groundOverlay(reader, zip);
|
||||||
else if (reader.name() == QLatin1String("Folder"))
|
else if (reader.name() == QLatin1String("Folder"))
|
||||||
folder(reader, zip);
|
folder(reader, zip);
|
||||||
@ -268,7 +276,7 @@ void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip)
|
|||||||
|
|
||||||
|
|
||||||
KMZMap::KMZMap(const QString &fileName, QObject *parent)
|
KMZMap::KMZMap(const QString &fileName, QObject *parent)
|
||||||
: Map(fileName, parent), _zip(0)
|
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0)
|
||||||
{
|
{
|
||||||
QZipReader zip(fileName, QIODevice::ReadOnly);
|
QZipReader zip(fileName, QIODevice::ReadOnly);
|
||||||
QByteArray xml(zip.fileData("doc.kml"));
|
QByteArray xml(zip.fileData("doc.kml"));
|
||||||
@ -305,16 +313,13 @@ QString KMZMap::name() const
|
|||||||
|
|
||||||
QRectF KMZMap::bounds()
|
QRectF KMZMap::bounds()
|
||||||
{
|
{
|
||||||
QSizeF s(0, 0);
|
QRectF rect;
|
||||||
|
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++)
|
||||||
if (_bounds.at(i).xy.right() > s.width())
|
rect |= _bounds.at(i).xy;
|
||||||
s.setWidth(_bounds.at(i).xy.right());
|
|
||||||
if (_bounds.at(i).xy.bottom() > s.height())
|
|
||||||
s.setHeight(_bounds.at(i).xy.bottom());
|
|
||||||
}
|
|
||||||
|
|
||||||
return QRectF(QPointF(0, 0), s);
|
rect.moveTopLeft(rect.topLeft() * 2);
|
||||||
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KMZMap::zoomFit(const QSize &size, const RectC &br)
|
int KMZMap::zoomFit(const QSize &size, const RectC &br)
|
||||||
@ -382,7 +387,12 @@ QPointF KMZMap::ll2xy(const Coordinates &c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPointF p = _maps.at(_mapIndex).ll2xy(c);
|
QPointF p = _maps.at(_mapIndex).ll2xy(c);
|
||||||
return p + _bounds.at(_mapIndex).xy.topLeft();
|
if (_maps.at(_mapIndex).rotation()) {
|
||||||
|
QTransform matrix;
|
||||||
|
matrix.rotate(-_maps.at(_mapIndex).rotation());
|
||||||
|
return matrix.map(p) + _bounds.at(_mapIndex).xy.topLeft();
|
||||||
|
} else
|
||||||
|
return p + _bounds.at(_mapIndex).xy.topLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
Coordinates KMZMap::xy2ll(const QPointF &p)
|
Coordinates KMZMap::xy2ll(const QPointF &p)
|
||||||
@ -397,22 +407,29 @@ Coordinates KMZMap::xy2ll(const QPointF &p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPointF p2 = p - _bounds.at(idx).xy.topLeft();
|
QPointF p2 = p - _bounds.at(idx).xy.topLeft();
|
||||||
return _maps.at(idx).xy2ll(p2);
|
if (_maps.at(idx).rotation()) {
|
||||||
|
QTransform matrix;
|
||||||
|
matrix.rotate(_maps.at(idx).rotation());
|
||||||
|
return _maps.at(idx).xy2ll(matrix.map(p2));
|
||||||
|
} else
|
||||||
|
return _maps.at(idx).xy2ll(p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||||
{
|
{
|
||||||
|
QRectF er = rect.adjusted(-_adjust, -_adjust, _adjust, _adjust);
|
||||||
|
|
||||||
// All in one map
|
// All in one map
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
if (_bounds.at(i).xy.contains(rect)) {
|
if (_bounds.at(i).xy.contains(er)) {
|
||||||
draw(painter, rect, i, flags);
|
draw(painter, er, i, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple maps
|
// Multiple maps
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
QRectF ir = rect.intersected(_bounds.at(i).xy);
|
QRectF ir = er.intersected(_bounds.at(i).xy);
|
||||||
if (!ir.isNull())
|
if (!ir.isNull())
|
||||||
draw(painter, ir, i, flags);
|
draw(painter, ir, i, flags);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef KMZMAP_H
|
#ifndef KMZMAP_H
|
||||||
#define KMZMAP_H
|
#define KMZMAP_H
|
||||||
|
|
||||||
#include "projection.h"
|
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "rectd.h"
|
#include "rectd.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
@ -39,34 +38,39 @@ public:
|
|||||||
QString errorString() const {return _errorString;}
|
QString errorString() const {return _errorString;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Overlay {
|
class Overlay {
|
||||||
QString path;
|
public:
|
||||||
QSize size;
|
|
||||||
RectC bbox;
|
|
||||||
double rotation;
|
|
||||||
Image *img;
|
|
||||||
|
|
||||||
Transform transform;
|
|
||||||
|
|
||||||
Overlay(const QString &path, const QSize &size, const RectC &bbox,
|
Overlay(const QString &path, const QSize &size, const RectC &bbox,
|
||||||
double rotation);
|
double rotation);
|
||||||
bool operator==(const Overlay &other) const
|
bool operator==(const Overlay &other) const
|
||||||
{return path == other.path;}
|
{return _path == other._path;}
|
||||||
|
|
||||||
QPointF ll2xy(const Coordinates &c) const
|
QPointF ll2xy(const Coordinates &c) const
|
||||||
{return QPointF(transform.proj2img(projection().ll2xy(c)));}
|
{return QPointF(_transform.proj2img(QPointF(c.lon(), c.lat())));}
|
||||||
Coordinates xy2ll(const QPointF &p) const
|
Coordinates xy2ll(const QPointF &p) const
|
||||||
{return projection().xy2ll(transform.img2proj(p));}
|
{
|
||||||
|
PointD pp(_transform.img2proj(p));
|
||||||
|
return Coordinates(pp.x(), pp.y());
|
||||||
|
}
|
||||||
|
|
||||||
QRectF bounds() const {return QRectF(QPointF(0, 0), size);}
|
const RectC &bbox() const {return _bbox;}
|
||||||
|
const QRectF &bounds() const {return _bounds;}
|
||||||
qreal resolution(const QRectF &rect) const;
|
qreal resolution(const QRectF &rect) const;
|
||||||
|
qreal rotation() const {return _rotation;}
|
||||||
|
|
||||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||||
|
|
||||||
void load(QZipReader *zip);
|
void load(QZipReader *zip);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
static const Projection &projection();
|
private:
|
||||||
|
QString _path;
|
||||||
|
QRectF _bounds;
|
||||||
|
RectC _bbox;
|
||||||
|
qreal _rotation;
|
||||||
|
Image *_img;
|
||||||
|
|
||||||
|
Transform _transform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Zoom {
|
struct Zoom {
|
||||||
@ -107,6 +111,7 @@ private:
|
|||||||
int _zoom;
|
int _zoom;
|
||||||
int _mapIndex;
|
int _mapIndex;
|
||||||
QZipReader *_zip;
|
QZipReader *_zip;
|
||||||
|
qreal _adjust;
|
||||||
|
|
||||||
bool _valid;
|
bool _valid;
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
|
Loading…
Reference in New Issue
Block a user