mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-05 23:22:51 +02:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
1de9c6ef5d | |||
54b6225c6c | |||
48c7299ba6 | |||
c284b9fa7c | |||
2c503a2406 | |||
27edc4d6b5 | |||
f333a76ef7 | |||
2c114f43c5 | |||
29e29591f8 | |||
e4ac9fda0e | |||
26229e5871 | |||
64bee2f2f4 | |||
e4288ee95c | |||
c9b3c2eedd | |||
42e4b0769f | |||
ce043ef8fa | |||
8c7050e273 | |||
d670107a11 | |||
7b03c4d852 | |||
2002b828dd | |||
71f0e1d0ac | |||
eb9767f2dd | |||
8d06ab6208 | |||
187cb77858 | |||
8167a995f6 |
@ -1,4 +1,4 @@
|
||||
version: 7.21.{build}
|
||||
version: 7.23.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
@ -4,7 +4,7 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common G
|
||||
## Features
|
||||
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV and geotagged JPEG files.
|
||||
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles).
|
||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images).
|
||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images).
|
||||
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
||||
* Support for DEM files (SRTM HGT).
|
||||
* Support for multiple tracks in one view.
|
||||
|
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 7.21
|
||||
VERSION = 7.23
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -383,7 +383,8 @@ macx {
|
||||
lang/gpxsee_tr.qm \
|
||||
lang/gpxsee_es.qm \
|
||||
lang/gpxsee_pt_BR.qm \
|
||||
lang/gpxsee_uk.qm
|
||||
lang/gpxsee_uk.qm \
|
||||
lang/gpxsee_hu.qm
|
||||
csv.path = Contents/Resources
|
||||
csv.files = pkg/csv
|
||||
maps.path = Contents/Resources
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.21"
|
||||
!define VERSION "7.23"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.21"
|
||||
!define VERSION "7.23"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -112,7 +112,7 @@ void GUI::loadMaps()
|
||||
QString mapDir(ProgramPaths::mapDir());
|
||||
|
||||
if (!mapDir.isNull() && !_ml->loadDir(mapDir))
|
||||
qWarning("%s", qPrintable(_ml->errorString()));
|
||||
qWarning("%s", qPrintable(_ml->errorPath() + ": " + _ml->errorString()));
|
||||
|
||||
_map = new EmptyMap(this);
|
||||
}
|
||||
@ -1325,7 +1325,10 @@ bool GUI::loadMap(const QString &fileName)
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
if (_ml->loadFile(fileName)) {
|
||||
QFileInfo fi(fileName);
|
||||
bool res = fi.isDir() ? _ml->loadDir(fileName) : _ml->loadFile(fileName);
|
||||
|
||||
if (res) {
|
||||
QAction *a = createMapAction(_ml->maps().last());
|
||||
_mapMenu->insertAction(_mapsEnd, a);
|
||||
_showMapAction->setEnabled(true);
|
||||
|
@ -14,8 +14,8 @@ double Coordinates::distanceTo(const Coordinates &c) const
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c)
|
||||
{
|
||||
dbg.nospace() << qSetRealNumberPrecision(10) << "Coordinates(" << c.lat()
|
||||
<< ", " << c.lon() << ")";
|
||||
dbg.nospace() << qSetRealNumberPrecision(10) << "Coordinates(" << c.lon()
|
||||
<< ", " << c.lat() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -3,14 +3,16 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#define LS(val, bits) ((qint32)(((quint32)(val))<<(bits)))
|
||||
|
||||
inline double toWGS32(qint32 v)
|
||||
{
|
||||
return (double)(((double)v / (double)(1U<<31)) * (double)180);
|
||||
return ((double)v / (double)(1U<<31)) * 180.0;
|
||||
}
|
||||
|
||||
inline double toWGS24(qint32 v)
|
||||
{
|
||||
return toWGS32(v<<8);
|
||||
return toWGS32(LS(v, 8));
|
||||
}
|
||||
|
||||
#endif // GARMIN_H
|
||||
|
@ -28,6 +28,9 @@ public:
|
||||
double left() const {return _tl.lon();}
|
||||
double right() const {return _br.lon();}
|
||||
|
||||
double width() const {return (right() - left());}
|
||||
double height() const {return (top() - bottom());}
|
||||
|
||||
void setLeft(double val) {_tl.rlon() = val;}
|
||||
void setRight(double val) {_br.rlon() = val;}
|
||||
void setTop(double val) {_tl.rlat() = val;}
|
||||
|
@ -44,37 +44,37 @@ static CUPParser cup;
|
||||
static GPIParser gpi;
|
||||
static SMLParser sml;
|
||||
|
||||
static QHash<QString, Parser*> parsers()
|
||||
static QMap<QString, Parser*> parsers()
|
||||
{
|
||||
QHash<QString, Parser*> hash;
|
||||
QMap<QString, Parser*> map;
|
||||
|
||||
hash.insert("gpx", &gpx);
|
||||
hash.insert("tcx", &tcx);
|
||||
hash.insert("kml", &kml);
|
||||
hash.insert("fit", &fit);
|
||||
hash.insert("csv", &csv);
|
||||
hash.insert("igc", &igc);
|
||||
hash.insert("nmea", &nmea);
|
||||
hash.insert("plt", &plt);
|
||||
hash.insert("wpt", &wpt);
|
||||
hash.insert("rte", &rte);
|
||||
hash.insert("loc", &loc);
|
||||
hash.insert("slf", &slf);
|
||||
map.insert("gpx", &gpx);
|
||||
map.insert("tcx", &tcx);
|
||||
map.insert("kml", &kml);
|
||||
map.insert("fit", &fit);
|
||||
map.insert("csv", &csv);
|
||||
map.insert("igc", &igc);
|
||||
map.insert("nmea", &nmea);
|
||||
map.insert("plt", &plt);
|
||||
map.insert("wpt", &wpt);
|
||||
map.insert("rte", &rte);
|
||||
map.insert("loc", &loc);
|
||||
map.insert("slf", &slf);
|
||||
#ifdef ENABLE_GEOJSON
|
||||
hash.insert("json", &geojson);
|
||||
hash.insert("geojson", &geojson);
|
||||
map.insert("json", &geojson);
|
||||
map.insert("geojson", &geojson);
|
||||
#endif // ENABLE_GEOJSON
|
||||
hash.insert("jpeg", &exif);
|
||||
hash.insert("jpg", &exif);
|
||||
hash.insert("cup", &cup);
|
||||
hash.insert("gpi", &gpi);
|
||||
hash.insert("sml", &sml);
|
||||
map.insert("jpeg", &exif);
|
||||
map.insert("jpg", &exif);
|
||||
map.insert("cup", &cup);
|
||||
map.insert("gpi", &gpi);
|
||||
map.insert("sml", &sml);
|
||||
|
||||
return hash;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
QHash<QString, Parser*> Data::_parsers = parsers();
|
||||
QMap<QString, Parser*> Data::_parsers = parsers();
|
||||
bool Data::_useDEM = false;
|
||||
|
||||
void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData)
|
||||
@ -130,7 +130,7 @@ Data::Data(const QString &fileName, bool poi)
|
||||
return;
|
||||
}
|
||||
|
||||
QHash<QString, Parser*>::iterator it;
|
||||
QMap<QString, Parser*>::iterator it;
|
||||
if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) {
|
||||
if (it.value()->parse(&file, trackData, routeData, _polygons,
|
||||
_waypoints)) {
|
||||
@ -166,17 +166,8 @@ Data::Data(const QString &fileName, bool poi)
|
||||
|
||||
QString Data::formats()
|
||||
{
|
||||
QStringList l(filter());
|
||||
qSort(l);
|
||||
QString supported;
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
supported += l.at(i);
|
||||
if (i != l.size() - 1)
|
||||
supported += " ";
|
||||
}
|
||||
|
||||
return
|
||||
qApp->translate("Data", "Supported files") + " (" + supported + ");;"
|
||||
qApp->translate("Data", "Supported files") + " (" + filter().join(" ") + ");;"
|
||||
+ qApp->translate("Data", "CSV files") + " (*.csv);;"
|
||||
+ qApp->translate("Data", "CUP files") + " (*.cup);;"
|
||||
+ qApp->translate("Data", "FIT files") + " (*.fit);;"
|
||||
@ -200,10 +191,10 @@ QString Data::formats()
|
||||
QStringList Data::filter()
|
||||
{
|
||||
QStringList filter;
|
||||
QHash<QString, Parser*>::iterator it;
|
||||
|
||||
for (it = _parsers.begin(); it != _parsers.end(); it++)
|
||||
filter << QString("*.%1").arg(it.key());
|
||||
for (QMap<QString, Parser*>::iterator it = _parsers.begin();
|
||||
it != _parsers.end(); it++)
|
||||
filter << "*." + it.key();
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define DATA_H
|
||||
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include "waypoint.h"
|
||||
@ -42,7 +42,7 @@ private:
|
||||
QList<Area> _polygons;
|
||||
QVector<Waypoint> _waypoints;
|
||||
|
||||
static QHash<QString, Parser*> _parsers;
|
||||
static QMap<QString, Parser*> _parsers;
|
||||
static bool _useDEM;
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
#include <QtCore/qmath.h>
|
||||
#else // QT5
|
||||
#include <QtMath>
|
||||
#endif // QT5
|
||||
#include "bitmapline.h"
|
||||
|
||||
|
||||
static QImage img2line(const QImage &img, int width)
|
||||
{
|
||||
Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied);
|
||||
@ -32,8 +38,8 @@ void BitmapLine::draw(QPainter *painter, const QPolygonF &line,
|
||||
painter->save();
|
||||
painter->translate(segment.p1());
|
||||
painter->rotate(-segment.angle());
|
||||
painter->drawImage(0, -img.height()/2, img2line(img, segment.length()));
|
||||
painter->drawImage(0.0, -img.height()/2.0, img2line(img,
|
||||
qCeil(segment.length())));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDir>
|
||||
#include "map/osm.h"
|
||||
#include "vectortile.h"
|
||||
#include "gmap.h"
|
||||
|
||||
@ -84,11 +85,13 @@ bool GMAP::loadTile(const QDir &dir, bool baseMap)
|
||||
tile->addFile(fi.absoluteFilePath(), tileType(fi.suffix()));
|
||||
}
|
||||
|
||||
if (!tile->init(baseMap)) {
|
||||
if (!tile->init()) {
|
||||
qWarning("%s: Invalid map tile", qPrintable(dir.path()));
|
||||
delete tile;
|
||||
return false;
|
||||
}
|
||||
if (baseMap)
|
||||
tile->markAsBasemap();
|
||||
|
||||
double min[2], max[2];
|
||||
min[0] = tile->bounds().left();
|
||||
@ -98,6 +101,13 @@ bool GMAP::loadTile(const QDir &dir, bool baseMap)
|
||||
_tileTree.Insert(min, max, tile);
|
||||
|
||||
_bounds |= tile->bounds();
|
||||
if (tile->zooms().min() < _zooms.min())
|
||||
_zooms.setMin(tile->zooms().min());
|
||||
|
||||
// Limit world maps bounds so that the maps can be projected using
|
||||
// the default Web Mercator projection
|
||||
if (_bounds.height() > 120)
|
||||
_bounds &= OSM::BOUNDS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <QMap>
|
||||
#include <QtEndian>
|
||||
#include "map/osm.h"
|
||||
#include "vectortile.h"
|
||||
#include "img.h"
|
||||
|
||||
@ -132,11 +133,13 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
||||
}
|
||||
|
||||
// Create tile tree
|
||||
|
||||
int minMapZoom = 24;
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
|
||||
if (!tile->init(false)) {
|
||||
if (!tile->init()) {
|
||||
qWarning("%s: %s: Invalid map tile", qPrintable(_file.fileName()),
|
||||
qPrintable(it.key()));
|
||||
delete tile;
|
||||
@ -151,8 +154,26 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
||||
_tileTree.Insert(min, max, tile);
|
||||
|
||||
_bounds |= tile->bounds();
|
||||
if (tile->zooms().min() < _zooms.min())
|
||||
_zooms.setMin(tile->zooms().min());
|
||||
if (tile->zooms().min() < minMapZoom)
|
||||
minMapZoom = tile->zooms().min();
|
||||
}
|
||||
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
if (tile->zooms().min() > minMapZoom)
|
||||
_baseMap = true;
|
||||
if (tile->zooms().min() == minMapZoom)
|
||||
tile->markAsBasemap();
|
||||
}
|
||||
|
||||
// Limit world maps bounds so that the maps can be projected using
|
||||
// the default Web Mercator projection
|
||||
if (_bounds.height() > 120)
|
||||
_bounds &= OSM::BOUNDS;
|
||||
|
||||
if (!_tileTree.Count())
|
||||
_errorString = "No usable map tile found";
|
||||
else
|
||||
|
@ -30,15 +30,20 @@ static quint8 SPECIAL_CHARS[] = {
|
||||
'8', '9', '~', '~', '~', '~', '~', '~'
|
||||
};
|
||||
|
||||
static QString capitalize(const QString &str)
|
||||
static bool isAllUpperCase(const QString &str)
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return str;
|
||||
return false;
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (str.at(i).isLetter() && !(str.at(i).isUpper()
|
||||
|| str.at(i) == QChar(0x00DF)))
|
||||
return str;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static QString capitalized(const QString &str)
|
||||
{
|
||||
QString ret(str);
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (i && !str.at(i-1).isSpace())
|
||||
@ -77,7 +82,7 @@ bool LBLFile::init(Handle &hdl)
|
||||
return true;
|
||||
}
|
||||
|
||||
Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
|
||||
{
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
@ -95,9 +100,12 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F};
|
||||
|
||||
for (int cpt = 0; cpt < 4; cpt++) {
|
||||
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d))
|
||||
return Label(capitalize(QString::fromLatin1(label)),
|
||||
Label::Shield(shieldType, shieldLabel));
|
||||
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d)) {
|
||||
QString text(QString::fromLatin1(label));
|
||||
return Label(capitalize && isAllUpperCase(text)
|
||||
? capitalized(text) : text, Label::Shield(shieldType,
|
||||
shieldLabel));
|
||||
}
|
||||
switch (curCharSet) {
|
||||
case Normal:
|
||||
if (c[cpt] == 0x1c)
|
||||
@ -127,7 +135,7 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
}
|
||||
}
|
||||
|
||||
Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
|
||||
{
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
@ -157,12 +165,15 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
bap->append(c);
|
||||
}
|
||||
|
||||
return Label(capitalize(_codec ? _codec->toUnicode(label)
|
||||
: QString::fromLatin1(label)), Label::Shield(shieldType, _codec
|
||||
? _codec->toUnicode(shieldLabel) : QString::fromLatin1(shieldLabel)));
|
||||
QString text(_codec ? _codec->toUnicode(label) : QString::fromLatin1(label));
|
||||
QString shieldText(_codec ? _codec->toUnicode(shieldLabel)
|
||||
: QString::fromLatin1(shieldLabel));
|
||||
|
||||
return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text,
|
||||
Label::Shield(shieldType, shieldText));
|
||||
}
|
||||
|
||||
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
|
||||
{
|
||||
if (!_multiplier && !init(hdl))
|
||||
return QString();
|
||||
@ -183,10 +194,10 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
|
||||
switch (_encoding) {
|
||||
case 6:
|
||||
return label6b(hdl, labelOffset);
|
||||
return label6b(hdl, labelOffset, capitalize);
|
||||
case 9:
|
||||
case 10:
|
||||
return label8b(hdl, labelOffset);
|
||||
return label8b(hdl, labelOffset, capitalize);
|
||||
default:
|
||||
return Label();
|
||||
}
|
||||
|
@ -19,13 +19,14 @@ public:
|
||||
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
|
||||
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
||||
|
||||
Label label(Handle &hdl, quint32 offset, bool poi = false);
|
||||
Label label(Handle &hdl, quint32 offset, bool poi = false,
|
||||
bool capitalize = true);
|
||||
|
||||
private:
|
||||
bool init(Handle &hdl);
|
||||
|
||||
Label label6b(Handle &hdl, quint32 offset) const;
|
||||
Label label8b(Handle &hdl, quint32 offset) const;
|
||||
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
|
||||
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
|
||||
|
||||
QTextCodec *_codec;
|
||||
quint32 _offset;
|
||||
|
@ -54,7 +54,8 @@ inline bool pointCb(VectorTile *tile, void *context)
|
||||
}
|
||||
|
||||
|
||||
MapData::MapData() : _typ(0), _style(0), _baseMap(false), _valid(false)
|
||||
MapData::MapData() : _typ(0), _style(0), _zooms(15, 28), _baseMap(false),
|
||||
_valid(false)
|
||||
{
|
||||
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||
_pointCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||
@ -104,8 +105,12 @@ void MapData::load()
|
||||
if (_typ)
|
||||
_style = new Style(_typ);
|
||||
else {
|
||||
SubFile typ(ProgramPaths::typFile());
|
||||
_style = new Style(&typ);
|
||||
QString typFile(ProgramPaths::typFile());
|
||||
if (!typFile.isEmpty()) {
|
||||
SubFile typ(typFile);
|
||||
_style = new Style(&typ);
|
||||
} else
|
||||
_style = new Style();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QDebug>
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
#include "common/range.h"
|
||||
#include "label.h"
|
||||
|
||||
class Style;
|
||||
@ -58,6 +59,7 @@ public:
|
||||
|
||||
const QString &name() const {return _name;}
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
const Range &zooms() const {return _zooms;}
|
||||
const Style *style() const {return _style;}
|
||||
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
QList<Poly> *lines);
|
||||
@ -79,6 +81,7 @@ protected:
|
||||
SubFile *_typ;
|
||||
Style *_style;
|
||||
TileTree _tileTree;
|
||||
Range _zooms;
|
||||
bool _baseMap;
|
||||
|
||||
bool _valid;
|
||||
|
@ -8,6 +8,20 @@
|
||||
#include "rgnfile.h"
|
||||
|
||||
|
||||
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
|
||||
{
|
||||
quint64 id;
|
||||
|
||||
uint hash = qHash(QPair<uint,uint>(qHash(QPair<int, int>(pos.x(),
|
||||
pos.y())), labelPtr & 0x3FFFFF));
|
||||
id = ((quint64)type)<<32 | hash;
|
||||
// Make country labels precedent over city labels
|
||||
if (!(type >= 0x1400 && type <= 0x153f))
|
||||
id |= 1ULL<<63;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
bool RGNFile::skipClassFields(Handle &hdl) const
|
||||
{
|
||||
quint8 flags;
|
||||
@ -154,8 +168,8 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
|
||||
|
||||
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.boundingRect = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
@ -164,8 +178,10 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
DeltaStream stream(*this, hdl, len, bitstreamInfo, labelPtr & 0x400000,
|
||||
false);
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
pos.rx() += LS(lonDelta, (24-subdiv->bits()));
|
||||
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffff;
|
||||
pos.ry() += LS(latDelta, (24-subdiv->bits()));
|
||||
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
@ -219,8 +235,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
labelPtr = 0;
|
||||
|
||||
if (!_huffmanTable.isNull()) {
|
||||
pos = QPoint((subdiv->lon()<<8) + ((qint32)lon<<(32-subdiv->bits())),
|
||||
(subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits())));
|
||||
pos = QPoint(LS(subdiv->lon(), 8) + LS(lon, 32-subdiv->bits()),
|
||||
LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits())));
|
||||
|
||||
qint32 lonDelta, latDelta;
|
||||
HuffmanStream stream(*this, hdl, len, _huffmanTable,
|
||||
@ -229,16 +245,18 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
if (shift) {
|
||||
if (!stream.readOffset(lonDelta, latDelta))
|
||||
return false;
|
||||
pos = QPoint(pos.x() | lonDelta<<(32-subdiv->bits()-shift),
|
||||
pos.y() | latDelta<<(32-subdiv->bits()-shift));
|
||||
pos = QPoint(pos.x() | LS(lonDelta, 32-subdiv->bits()-shift),
|
||||
pos.y() | LS(latDelta, 32-subdiv->bits()-shift));
|
||||
}
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.boundingRect = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(32-subdiv->bits()-shift);
|
||||
pos.ry() += latDelta<<(32-subdiv->bits()-shift);
|
||||
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
|
||||
if (pos.rx() < 0 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffffff;
|
||||
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
|
||||
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
@ -248,8 +266,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
if (!(stream.atEnd() && stream.flush()))
|
||||
return false;
|
||||
} else {
|
||||
pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
pos = QPoint(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.boundingRect = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
@ -262,8 +280,10 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
DeltaStream stream(*this, hdl, len - 1, bitstreamInfo, false, true);
|
||||
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
pos.rx() += LS(lonDelta, 24-subdiv->bits());
|
||||
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffff;
|
||||
pos.ry() += LS(latDelta, 24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
@ -294,9 +314,6 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const
|
||||
{
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
|
||||
? subdiv->idxPoints() : subdiv->points();
|
||||
|
||||
@ -307,6 +324,9 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
|
||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
@ -317,20 +337,17 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
} else
|
||||
subtype = 0;
|
||||
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
|
||||
point.type = (quint16)type<<8 | subtype;
|
||||
|
||||
qint32 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint32 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
|
||||
uint hash = qHash(QPair<uint,uint>(qHash(QPair<qint32, qint32>
|
||||
(subdiv->lon() + lonOffset, subdiv->lat() + latOffset)),
|
||||
labelPtr & 0x3FFFFF));
|
||||
point.id = ((quint64)point.type)<<32 | hash;
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi,
|
||||
!(point.type == 0x1400 || point.type == 0x1500
|
||||
|| point.type == 0x1e00));
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
@ -341,12 +358,8 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
Handle &lblHdl, QList<IMG::Point> *points) const
|
||||
{
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
const SubDiv::Segment &segment = subdiv->extPoints();
|
||||
|
||||
|
||||
if (!segment.isValid())
|
||||
return true;
|
||||
if (!seek(hdl, segment.offset()))
|
||||
@ -354,19 +367,14 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
qint16 lon, lat;
|
||||
quint8 type, subtype;
|
||||
quint32 labelPtr = 0;
|
||||
|
||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
|
||||
qint32 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint32 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
labelPtr = 0;
|
||||
|
||||
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||
@ -374,15 +382,17 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
|
||||
return false;
|
||||
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
// Discard NT points breaking style draw order logic (and causing huge
|
||||
// performance drawback)
|
||||
if (point.type == 0x11400)
|
||||
continue;
|
||||
|
||||
uint hash = qHash(QPair<uint,uint>(qHash(QPair<qint32, qint32>
|
||||
(subdiv->lon() + lonOffset, subdiv->lat() + latOffset)),
|
||||
labelPtr & 0x3FFFFF));
|
||||
point.id = ((quint64)point.type)<<32 | hash;
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include "style.h"
|
||||
|
||||
|
||||
@ -79,13 +80,19 @@ void Style::defaultPolygonStyle()
|
||||
<< TYPE(0x13);
|
||||
}
|
||||
|
||||
static QImage railroad()
|
||||
{
|
||||
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(QColor("#717171"));
|
||||
QPainter p(&img);
|
||||
p.setPen(QPen(Qt::white, 2));
|
||||
p.drawLine(9, 2, 15, 2);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void Style::defaultLineStyle()
|
||||
{
|
||||
QVector<qreal> pattern;
|
||||
pattern << 4 << 4;
|
||||
QPen rr(QColor("#717171"), 3, Qt::CustomDashLine);
|
||||
rr.setDashPattern(pattern);
|
||||
|
||||
_lines[TYPE(0x01)] = Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#72a35a"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x02)] = Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
@ -109,13 +116,13 @@ void Style::defaultLineStyle()
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x0c)] = Line(QPen(QColor("#ffffff"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x14)] = Line(rr, QPen(Qt::white, 3, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x14)] = Line(railroad());
|
||||
_lines[TYPE(0x16)] = Line(QPen(QColor("#aba083"), 1, Qt::DotLine));
|
||||
_lines[TYPE(0x18)] = Line(QPen(QColor("#9fc4e1"), 2, Qt::SolidLine));
|
||||
_lines[TYPE(0x18)].setTextColor(QColor("#9fc4e1"));
|
||||
//_lines[TYPE(0x1a)] = Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1b)] = Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1c)] = Line(QPen(QColor("#505145"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1e)] = Line(QPen(QColor("#505145"), 2, Qt::DashDotLine));
|
||||
_lines[TYPE(0x1f)] = Line(QPen(QColor("#9fc4e1"), 3, Qt::SolidLine));
|
||||
_lines[TYPE(0x1f)].setTextColor(QColor("#9fc4e1"));
|
||||
@ -145,6 +152,17 @@ void Style::defaultLineStyle()
|
||||
|
||||
void Style::defaultPointStyle()
|
||||
{
|
||||
// Countries
|
||||
_points[TYPE(0x14)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x14)].setTextFontSize(Small);
|
||||
_points[TYPE(0x15)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x15)].setTextFontSize(Small);
|
||||
|
||||
// Regions
|
||||
_points[TYPE(0x1e)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x1e)].setTextFontSize(ExtraSmall);
|
||||
_points[TYPE(0x28)].setTextFontSize(Small);
|
||||
|
||||
// Cities
|
||||
_points[TYPE(0x01)].setTextFontSize(Large);
|
||||
_points[TYPE(0x02)].setTextFontSize(Large);
|
||||
|
@ -16,7 +16,8 @@ public:
|
||||
None = 1,
|
||||
Small = 2,
|
||||
Normal = 3,
|
||||
Large = 4
|
||||
Large = 4,
|
||||
ExtraSmall = 5
|
||||
};
|
||||
|
||||
enum POIClass {
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define SUBFILE_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include "img.h"
|
||||
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include "trefile.h"
|
||||
|
||||
|
||||
static inline double RB(qint32 val)
|
||||
{
|
||||
return (val == -0x800000 || val == 0x800000) ? 180.0 : toWGS24(val);
|
||||
}
|
||||
|
||||
static void demangle(quint8 *data, quint32 size, quint32 key)
|
||||
{
|
||||
static const unsigned char shuf[] = {
|
||||
@ -37,12 +42,13 @@ TREFile::~TREFile()
|
||||
clear();
|
||||
}
|
||||
|
||||
bool TREFile::init(bool baseMap)
|
||||
bool TREFile::init()
|
||||
{
|
||||
Handle hdl(this);
|
||||
quint8 locked;
|
||||
quint16 hdrLen;
|
||||
|
||||
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||
&& seek(hdl, _gmpOffset + 0x0D) && readUInt8(hdl, locked)))
|
||||
return false;
|
||||
@ -53,7 +59,8 @@ bool TREFile::init(bool baseMap)
|
||||
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
|
||||
return false;
|
||||
_bounds = RectC(Coordinates(toWGS24(west), toWGS24(north)),
|
||||
Coordinates(toWGS24(east), toWGS24(south)));
|
||||
Coordinates(RB(east), toWGS24(south)));
|
||||
Q_ASSERT(_bounds.left() <= _bounds.right());
|
||||
|
||||
// Levels & subdivs info
|
||||
quint32 levelsOffset, levelsSize, subdivSize;
|
||||
@ -108,7 +115,7 @@ bool TREFile::init(bool baseMap)
|
||||
}
|
||||
}
|
||||
|
||||
_isBaseMap = baseMap;
|
||||
_isBaseMap = false;
|
||||
|
||||
return (_firstLevel >= 0);
|
||||
}
|
||||
@ -132,8 +139,8 @@ bool TREFile::load(int idx)
|
||||
|
||||
for (int j = 0; j < _levels.at(idx).subdivs; j++) {
|
||||
quint32 oo;
|
||||
qint32 lon, lat;
|
||||
quint16 width, height, nextLevel;
|
||||
qint32 lon, lat, width, height;
|
||||
quint16 nextLevel;
|
||||
|
||||
if (!(readUInt32(hdl, oo) && readInt24(hdl, lon) && readInt24(hdl, lat)
|
||||
&& readUInt16(hdl, width) && readUInt16(hdl, height)))
|
||||
@ -149,17 +156,16 @@ bool TREFile::load(int idx)
|
||||
s->setEnd(offset);
|
||||
|
||||
width &= 0x7FFF;
|
||||
width <<= (24 - _levels.at(idx).bits);
|
||||
height <<= (24 - _levels.at(idx).bits);
|
||||
|
||||
width = LS(width, 24 - _levels.at(idx).bits);
|
||||
height = LS(height, 24 - _levels.at(idx).bits);
|
||||
|
||||
s = new SubDiv(offset, lon, lat, _levels.at(idx).bits, objects);
|
||||
sl.append(s);
|
||||
|
||||
double min[2], max[2];
|
||||
RectC bounds(Coordinates(toWGS24(lon - width),
|
||||
toWGS24(lat + height + 1)), Coordinates(toWGS24(lon + width + 1),
|
||||
toWGS24(lat - height)));
|
||||
RectC bounds(Coordinates(toWGS24(lon - width), toWGS24(lat + height)),
|
||||
Coordinates(RB(lon + width), toWGS24(lat - height)));
|
||||
Q_ASSERT(bounds.left() <= bounds.right());
|
||||
|
||||
min[0] = bounds.left();
|
||||
min[1] = bounds.bottom();
|
||||
@ -240,15 +246,15 @@ void TREFile::clear()
|
||||
|
||||
int TREFile::level(int bits, bool baseMap)
|
||||
{
|
||||
int idx = _firstLevel;
|
||||
|
||||
if (baseMap) {
|
||||
if (!_isBaseMap && _levels.at(idx).bits > bits)
|
||||
if (!_isBaseMap && _levels.first().bits > bits)
|
||||
return -1;
|
||||
if (_isBaseMap && bits > _levels.last().bits)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int idx = _firstLevel;
|
||||
|
||||
for (int i = idx + 1; i < _levels.size(); i++) {
|
||||
if (_levels.at(i).bits > bits)
|
||||
break;
|
||||
|
@ -18,13 +18,16 @@ public:
|
||||
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
|
||||
~TREFile();
|
||||
|
||||
bool init(bool baseMap);
|
||||
bool init();
|
||||
void markAsBasemap() {_isBaseMap = true;}
|
||||
void clear();
|
||||
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
QList<SubDiv*> subdivs(const RectC &rect, int bits, bool baseMap);
|
||||
quint32 shift(quint8 bits) const
|
||||
{return (bits == _levels.last().bits) ? (_flags >> 0xb) & 7 : 0;}
|
||||
Range zooms() const
|
||||
{return Range(_levels.at(_firstLevel).bits, _levels.last().bits);}
|
||||
|
||||
private:
|
||||
struct MapLevel {
|
||||
|
@ -82,12 +82,12 @@ SubFile *VectorTile::addFile(const QString &path, SubFile::Type type)
|
||||
}
|
||||
}
|
||||
|
||||
bool VectorTile::init(bool baseMap)
|
||||
bool VectorTile::init()
|
||||
{
|
||||
if (_gmp && !initGMP())
|
||||
return false;
|
||||
|
||||
if (!(_tre && _tre->init(baseMap) && _rgn))
|
||||
if (!(_tre && _tre->init() && _rgn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -15,10 +15,12 @@ public:
|
||||
delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;
|
||||
}
|
||||
|
||||
bool init(bool baseMap);
|
||||
bool init();
|
||||
void markAsBasemap() {_tre->markAsBasemap();}
|
||||
void clear() {_tre->clear();}
|
||||
|
||||
const RectC &bounds() const {return _tre->bounds();}
|
||||
Range zooms() const {return _tre->zooms();}
|
||||
|
||||
SubFile *file(SubFile::Type type);
|
||||
SubFile *addFile(IMG *img, SubFile::Type type);
|
||||
|
@ -79,8 +79,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
static const Range zooms(12, 28);
|
||||
|
||||
static const QColor shieldColor(Qt::white);
|
||||
static const QColor shieldBgColor1("#dd3e3e");
|
||||
static const QColor shieldBgColor2("#379947");
|
||||
@ -129,6 +127,7 @@ static QFont *font(Style::FontSize size, Style::FontSize defaultSize
|
||||
static QFont large = pixelSizeFont(16);
|
||||
static QFont normal = pixelSizeFont(14);
|
||||
static QFont small = pixelSizeFont(12);
|
||||
static QFont extraSmall = pixelSizeFont(10);
|
||||
|
||||
switch (size) {
|
||||
case Style::None:
|
||||
@ -139,6 +138,8 @@ static QFont *font(Style::FontSize size, Style::FontSize defaultSize
|
||||
return &normal;
|
||||
case Style::Small:
|
||||
return &small;
|
||||
case Style::ExtraSmall:
|
||||
return &extraSmall;
|
||||
default:
|
||||
return font(defaultSize);
|
||||
}
|
||||
@ -243,7 +244,7 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
_zoom = zooms.min();
|
||||
_zoom = _data->zooms().min();
|
||||
updateTransform();
|
||||
|
||||
_valid = true;
|
||||
@ -271,8 +272,8 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
if (rect.isValid()) {
|
||||
RectD pr(rect, _projection, 10);
|
||||
|
||||
_zoom = zooms.min();
|
||||
for (int i = zooms.min() + 1; i <= zooms.max(); i++) {
|
||||
_zoom = _data->zooms().min();
|
||||
for (int i = _data->zooms().min() + 1; i <= _data->zooms().max(); i++) {
|
||||
Transform t(transform(i));
|
||||
QRectF r(t.proj2img(pr.topLeft()), t.proj2img(pr.bottomRight()));
|
||||
if (size.width() < r.width() || size.height() < r.height())
|
||||
@ -280,7 +281,7 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
_zoom = i;
|
||||
}
|
||||
} else
|
||||
_zoom = zooms.max();
|
||||
_zoom = _data->zooms().max();
|
||||
|
||||
updateTransform();
|
||||
|
||||
@ -289,14 +290,14 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
|
||||
int IMGMap::zoomIn()
|
||||
{
|
||||
_zoom = qMin(_zoom + 1, zooms.max());
|
||||
_zoom = qMin(_zoom + 1, _data->zooms().max());
|
||||
updateTransform();
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
int IMGMap::zoomOut()
|
||||
{
|
||||
_zoom = qMax(_zoom - 1, zooms.min());
|
||||
_zoom = qMax(_zoom - 1, _data->zooms().min());
|
||||
updateTransform();
|
||||
return _zoom;
|
||||
}
|
||||
@ -590,15 +591,21 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
tiles.append(RasterTile(this, ttl, key));
|
||||
RasterTile &tile = tiles.last();
|
||||
|
||||
RectD polyRect(_transform.img2proj(ttl), _transform.img2proj(
|
||||
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
|
||||
_data->polys(polyRect.toRectC(_projection, 4), _zoom,
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE,
|
||||
ttl.y() + TILE_SIZE));
|
||||
polyRect &= bounds().adjusted(0.5, 0.5, -0.5, -0.5);
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
_data->polys(polyRectD.toRectC(_projection, 4), _zoom,
|
||||
&(tile.polygons()), &(tile.lines()));
|
||||
|
||||
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
|
||||
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
|
||||
_data->points(pointRect.toRectC(_projection, 4), _zoom,
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE
|
||||
+ TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT));
|
||||
pointRect &= bounds().adjusted(0.5, 0.5, -0.5, -0.5);
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data->points(pointRectD.toRectC(_projection, 4), _zoom,
|
||||
&(tile.points()));
|
||||
}
|
||||
}
|
||||
|
@ -12,56 +12,46 @@
|
||||
#include "maplist.h"
|
||||
|
||||
|
||||
bool MapList::loadMap(Map *map, const QString &path, bool dir)
|
||||
bool MapList::loadMap(Map *map, const QString &path)
|
||||
{
|
||||
if (map && map->isValid()) {
|
||||
_maps.append(map);
|
||||
return true;
|
||||
} else if (map) {
|
||||
if (dir)
|
||||
_errorString += path + ": " + map->errorString() + "\n";
|
||||
else
|
||||
_errorString = map->errorString();
|
||||
return false;
|
||||
} else {
|
||||
if (dir)
|
||||
_errorString += path + ": " + "Unknown map format\n";
|
||||
else
|
||||
_errorString = "Unknown map format";
|
||||
_errorPath = path;
|
||||
_errorString = (map) ? map->errorString() : "Unknown file format";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map *MapList::loadSource(const QString &path, bool dir)
|
||||
Map *MapList::loadSource(const QString &path)
|
||||
{
|
||||
QString err;
|
||||
Map *map = MapSource::loadMap(path, err);
|
||||
Map *map = MapSource::loadMap(path, _errorString);
|
||||
|
||||
if (!map) {
|
||||
if (dir)
|
||||
_errorString += path + ": " + err + "\n";
|
||||
else
|
||||
_errorString = err;
|
||||
} else
|
||||
if (!map)
|
||||
_errorPath = path;
|
||||
else
|
||||
map->setParent(this);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
bool MapList::loadFile(const QString &path, bool *terminate, bool dir)
|
||||
bool MapList::loadFile(const QString &path, bool *terminate)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
Map *map = 0;
|
||||
|
||||
if (Atlas::isAtlas(path)) {
|
||||
*terminate = true;
|
||||
if (terminate)
|
||||
*terminate = true;
|
||||
map = new Atlas(path, this);
|
||||
} else if (suffix == "xml") {
|
||||
if (MapSource::isMap(path) && !(map = loadSource(path, dir)))
|
||||
if (MapSource::isMap(path) && !(map = loadSource(path)))
|
||||
return false;
|
||||
else if (GMAP::isGMAP(path)) {
|
||||
*terminate = true;
|
||||
if (terminate)
|
||||
*terminate = true;
|
||||
map = new IMGMap(path);
|
||||
}
|
||||
} else if (suffix == "jnx")
|
||||
@ -74,10 +64,10 @@ bool MapList::loadFile(const QString &path, bool *terminate, bool dir)
|
||||
map = new RMap(path, this);
|
||||
else if (suffix == "img")
|
||||
map = new IMGMap(path, this);
|
||||
else
|
||||
else if (suffix == "map" || suffix == "tar")
|
||||
map = new OziMap(path, this);
|
||||
|
||||
if (!loadMap(map, path, dir)) {
|
||||
if (!loadMap(map, path)) {
|
||||
delete map;
|
||||
return false;
|
||||
}
|
||||
@ -85,7 +75,7 @@ bool MapList::loadFile(const QString &path, bool *terminate, bool dir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapList::loadDirR(const QString &path)
|
||||
bool MapList::loadDir(const QString &path)
|
||||
{
|
||||
QDir md(path);
|
||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -99,10 +89,10 @@ bool MapList::loadDirR(const QString &path)
|
||||
bool terminate = false;
|
||||
|
||||
if (fi.isDir() && fi.fileName() != "set") {
|
||||
if (!loadDirR(fi.absoluteFilePath()))
|
||||
if (!loadDir(fi.absoluteFilePath()))
|
||||
ret = false;
|
||||
} else if (filter().contains("*." + suffix)) {
|
||||
if (!loadFile(fi.absoluteFilePath(), &terminate, true))
|
||||
if (!loadFile(fi.absoluteFilePath(), &terminate))
|
||||
ret = false;
|
||||
if (terminate)
|
||||
break;
|
||||
@ -112,26 +102,11 @@ bool MapList::loadDirR(const QString &path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MapList::loadFile(const QString &path)
|
||||
{
|
||||
bool atlas;
|
||||
|
||||
_errorString.clear();
|
||||
return loadFile(path, &atlas, false);
|
||||
}
|
||||
|
||||
bool MapList::loadDir(const QString &path)
|
||||
{
|
||||
_errorString.clear();
|
||||
return loadDirR(path);
|
||||
}
|
||||
|
||||
QString MapList::formats()
|
||||
{
|
||||
return
|
||||
tr("Supported files")
|
||||
+ " (*.img *.jnx *.map *.mbtiles *.rmap *.rtmap *.tar *.tba *.tif *.tiff *.xml);;"
|
||||
+ tr("Garmin IMG maps") + " (*.img *.xml);;"
|
||||
tr("Supported files") + " (" + filter().join(" ") + ");;"
|
||||
+ tr("Garmin IMG maps") + " (*.gmap *.gmapi *.img *.xml);;"
|
||||
+ tr("Garmin JNX maps") + " (*.jnx);;"
|
||||
+ tr("OziExplorer maps") + " (*.map);;"
|
||||
+ tr("MBTiles maps") + " (*.mbtiles);;"
|
||||
@ -144,7 +119,8 @@ QString MapList::formats()
|
||||
QStringList MapList::filter()
|
||||
{
|
||||
QStringList filter;
|
||||
filter << "*.img" << "*.jnx" << "*.map" << "*.tba" << "*.tar" << "*.xml"
|
||||
<< "*.tif" << "*.tiff" << "*.mbtiles" << "*.rmap" << "*.rtmap" << "*.img";
|
||||
filter << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.map"
|
||||
<< "*.mbtiles" << "*.rmap" << "*.rtmap" << "*.tar" << "*.tba" << "*.tif"
|
||||
<< "*.tiff" << "*.xml";
|
||||
return filter;
|
||||
}
|
||||
|
@ -13,23 +13,24 @@ class MapList : public QObject
|
||||
public:
|
||||
MapList(QObject *parent = 0) : QObject(parent) {}
|
||||
|
||||
bool loadFile(const QString &path);
|
||||
bool loadFile(const QString &path, bool *terminate = 0);
|
||||
bool loadDir(const QString &path);
|
||||
|
||||
const QList<Map*> &maps() const {return _maps;}
|
||||
|
||||
const QString &errorString() const {return _errorString;}
|
||||
const QString &errorPath() const {return _errorPath;}
|
||||
|
||||
static QString formats();
|
||||
static QStringList filter();
|
||||
|
||||
private:
|
||||
bool loadFile(const QString &path, bool *terminate, bool dir);
|
||||
bool loadDirR(const QString &path);
|
||||
Map *loadSource(const QString &path, bool dir);
|
||||
bool loadMap(Map *map, const QString &path, bool dir);
|
||||
Map *loadSource(const QString &path);
|
||||
bool loadMap(Map *map, const QString &path);
|
||||
|
||||
QList<Map*> _maps;
|
||||
QString _errorString;
|
||||
QString _errorPath;
|
||||
};
|
||||
|
||||
#endif // MAPLIST_H
|
||||
|
Reference in New Issue
Block a user