Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
0531389cd8 | |||
a281a68cbd | |||
2e7f8dc341 | |||
1304fd5c3c | |||
d310399b4f | |||
845a4b2921 | |||
00fff55cd3 | |||
722f3acb1e | |||
b38cf31920 | |||
2884c39367 | |||
1124a1adb4 | |||
8c67df7bbd | |||
d1e632523a | |||
2549ca2c90 | |||
abd01933ab |
@ -1,4 +1,4 @@
|
||||
version: 13.8.{build}
|
||||
version: 13.9.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
@ -8,10 +8,13 @@ image:
|
||||
|
||||
environment:
|
||||
NSISDIR: C:\Program Files (x86)\NSIS
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
matrix:
|
||||
- QTDIR: C:\Qt\5.15\msvc2019_64
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
OPENSSLVERSION: 1_1
|
||||
- QTDIR: C:\Qt\6.5\msvc2019_64
|
||||
OPENSSLDIR: C:\OpenSSL-v30-Win64\bin
|
||||
OPENSSLVERSION: 3
|
||||
NSISDEF: /DQT6
|
||||
|
||||
install:
|
||||
@ -34,8 +37,8 @@ build_script:
|
||||
xcopy lang\*.qm installer\translations\ /sy
|
||||
xcopy icons\symbols installer\symbols /i
|
||||
copy licence.txt installer
|
||||
copy %OPENSSLDIR%\libcrypto-1_1-x64.dll installer
|
||||
copy %OPENSSLDIR%\libssl-1_1-x64.dll installer
|
||||
copy %OPENSSLDIR%\libcrypto-%OPENSSLVERSION%-x64.dll installer
|
||||
copy %OPENSSLDIR%\libssl-%OPENSSLVERSION%-x64.dll installer
|
||||
|
||||
makensis.exe %NSISDEF% installer\gpxsee64.nsi
|
||||
|
||||
|
@ -3,7 +3,7 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 13.8
|
||||
VERSION = 13.9
|
||||
|
||||
|
||||
QT += core \
|
||||
@ -134,6 +134,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/encmap.h \
|
||||
src/map/ENC/iso8211.h \
|
||||
src/map/gemfmap.h \
|
||||
src/map/gmifile.h \
|
||||
src/map/oruxmap.h \
|
||||
src/map/osmdroidmap.h \
|
||||
src/map/proj/polyconic.h \
|
||||
@ -347,6 +348,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/encmap.cpp \
|
||||
src/map/ENC/iso8211.cpp \
|
||||
src/map/gemfmap.cpp \
|
||||
src/map/gmifile.cpp \
|
||||
src/map/oruxmap.cpp \
|
||||
src/map/osmdroidmap.cpp \
|
||||
src/map/proj/polyconic.cpp \
|
||||
|
@ -188,6 +188,7 @@
|
||||
<file alias="radar.png">icons/map/marine/radar.png</file>
|
||||
<file alias="radar-transponder.png">icons/map/marine/radar-transponder.png</file>
|
||||
<file alias="silo.png">icons/map/marine/silo.png</file>
|
||||
<file alias="tank.png">icons/map/marine/tank.png</file>
|
||||
<file alias="turning-basin.png">icons/map/marine/turning-basin.png</file>
|
||||
<file alias="entry-prohibited-line.png">icons/map/marine/entry-prohibited-line.png</file>
|
||||
<file alias="safety-zone-line.png">icons/map/marine/safety-zone-line.png</file>
|
||||
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 170 B |
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 205 B |
Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 221 B |
BIN
icons/map/marine/tank.png
Normal file
After Width: | Height: | Size: 230 B |
@ -1648,7 +1648,7 @@
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>int.iho.s57-catalogue</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://iho.int/uploads/user/pubs/standards/s-57/31Main.pdf</string>
|
||||
<string>https://iho.int/uploads/user/pubs/standards/s-57/20ApB1.pdf</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>IHO S-57 Electronic Navigation Catalogue</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
|
@ -37,7 +37,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "13.8"
|
||||
!define VERSION "13.9"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -302,8 +302,13 @@ Section "OpenSSL" SEC_OPENSSL
|
||||
|
||||
SectionIn RO
|
||||
|
||||
!ifdef QT6
|
||||
File "libcrypto-3-x64.dll"
|
||||
File "libssl-3-x64.dll"
|
||||
!else
|
||||
File "libcrypto-1_1-x64.dll"
|
||||
File "libssl-1_1-x64.dll"
|
||||
!endif
|
||||
|
||||
SectionEnd
|
||||
|
||||
|
@ -1750,7 +1750,7 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
|
||||
|
||||
bool GUI::loadMap(const QString &fileName, MapAction *&action, int &showError)
|
||||
{
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName, _mapView->inputProjection()));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
|
||||
return loadMapNode(maps, action, existingActions, showError);
|
||||
@ -1854,7 +1854,7 @@ void GUI::loadMapDir()
|
||||
return;
|
||||
|
||||
QFileInfo fi(dir);
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir, _mapView->inputProjection()));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
QList<MapAction*> actions;
|
||||
QMenu *menu = new QMenu(maps.name());
|
||||
@ -2985,7 +2985,7 @@ void GUI::loadInitialMaps(const QString &selected)
|
||||
if (mapDir.isNull())
|
||||
return;
|
||||
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir, _mapView->inputProjection()));
|
||||
createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd);
|
||||
|
||||
// Select the active map according to the user settings
|
||||
|
@ -81,15 +81,15 @@ ToolTip MapItem::info() const
|
||||
return tt;
|
||||
}
|
||||
|
||||
MapItem::MapItem(MapAction *action, Map *map, const Projection &proj,
|
||||
GraphicsItem *parent) : PlaneItem(parent)
|
||||
MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
|
||||
: PlaneItem(parent)
|
||||
{
|
||||
Map *src = action->data().value<Map*>();
|
||||
Q_ASSERT(map->isReady());
|
||||
|
||||
_name = src->name();
|
||||
_fileName = src->path();
|
||||
_bounds = src->llBounds(proj);
|
||||
_bounds = src->llBounds();
|
||||
|
||||
connect(this, &MapItem::triggered, action, &MapAction::trigger);
|
||||
|
||||
|
@ -11,8 +11,7 @@ class MapItem : public QObject, public PlaneItem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapItem(MapAction *action, Map *map, const Projection &proj,
|
||||
GraphicsItem *parent = 0);
|
||||
MapItem(MapAction *action, Map *map, GraphicsItem *parent = 0);
|
||||
|
||||
QPainterPath shape() const {return _painterPath;}
|
||||
QRectF boundingRect() const {return _painterPath.boundingRect();}
|
||||
|
@ -250,7 +250,7 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
|
||||
|
||||
MapItem *MapView::addMap(MapAction *map)
|
||||
{
|
||||
MapItem *mi = new MapItem(map, _map, _inputProjection);
|
||||
MapItem *mi = new MapItem(map, _map);
|
||||
mi->setColor(_palette.nextColor());
|
||||
mi->setWidth(_areaWidth);
|
||||
mi->setPenStyle(_areaStyle);
|
||||
@ -331,7 +331,7 @@ int MapView::fitMapZoom() const
|
||||
RectC br = _tr | _rr | _wr | _ar;
|
||||
|
||||
return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
|
||||
br.isNull() ? _map->llBounds(_inputProjection) : br);
|
||||
br.isNull() ? _map->llBounds() : br);
|
||||
}
|
||||
|
||||
QPointF MapView::contentCenter() const
|
||||
|
@ -98,6 +98,7 @@ public:
|
||||
void fitContentToSize();
|
||||
|
||||
RectC boundingRect() const;
|
||||
const Projection &inputProjection() const {return _inputProjection;}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
signals:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define CATTRK 54
|
||||
#define CATREA 56
|
||||
#define CATSIT 61
|
||||
#define CATSIL 63
|
||||
#define CATSCF 65
|
||||
#define CATWAT 69
|
||||
#define CATWRK 71
|
||||
|
@ -28,12 +28,23 @@ struct DR {
|
||||
char FieldTagSize;
|
||||
};
|
||||
|
||||
|
||||
const QVariant *ISO8211::Field::data(const QByteArray &name, int idx) const
|
||||
{
|
||||
const QVector<QVariant> &v = _data.at(idx);
|
||||
|
||||
for (int i = 0; i < _subFields.size(); i++)
|
||||
if (_subFields.at(i) == name)
|
||||
return &v.at(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ISO8211::Field::subfield(const char *name, int *val, int idx) const
|
||||
{
|
||||
const QVariant *v;
|
||||
bool ok;
|
||||
|
||||
v = data().field(name, idx);
|
||||
const QVariant *v = data(name, idx);
|
||||
if (!v)
|
||||
return false;
|
||||
*val = v->toInt(&ok);
|
||||
@ -43,10 +54,9 @@ bool ISO8211::Field::subfield(const char *name, int *val, int idx) const
|
||||
|
||||
bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const
|
||||
{
|
||||
const QVariant *v;
|
||||
bool ok;
|
||||
|
||||
v = data().field(name, idx);
|
||||
const QVariant *v = data(name, idx);
|
||||
if (!v)
|
||||
return false;
|
||||
*val = v->toUInt(&ok);
|
||||
@ -56,9 +66,7 @@ bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const
|
||||
|
||||
bool ISO8211::Field::subfield(const char *name, QByteArray *val, int idx) const
|
||||
{
|
||||
const QVariant *v;
|
||||
|
||||
v = data().field(name, idx);
|
||||
const QVariant *v = data(name, idx);
|
||||
if (!v)
|
||||
return false;
|
||||
*val = v->toByteArray();
|
||||
@ -66,25 +74,24 @@ bool ISO8211::Field::subfield(const char *name, QByteArray *val, int idx) const
|
||||
return true;
|
||||
}
|
||||
|
||||
ISO8211::SubFieldDefinition ISO8211::fieldType(const QString &str, int cnt,
|
||||
const QByteArray &tag)
|
||||
ISO8211::SubFieldDefinition ISO8211::fieldType(const QString &str, int cnt)
|
||||
{
|
||||
if (str == "A" || str == "I" || str == "R")
|
||||
return SubFieldDefinition(tag, String, cnt);
|
||||
return SubFieldDefinition(String, cnt);
|
||||
else if (str == "B")
|
||||
return SubFieldDefinition(tag, Array, cnt / 8);
|
||||
return SubFieldDefinition(Array, cnt / 8);
|
||||
else if (str == "b11")
|
||||
return SubFieldDefinition(tag, U8, 1);
|
||||
return SubFieldDefinition(U8, 1);
|
||||
else if (str == "b12")
|
||||
return SubFieldDefinition(tag, U16, 2);
|
||||
return SubFieldDefinition(U16, 2);
|
||||
else if (str == "b14")
|
||||
return SubFieldDefinition(tag, U32, 4);
|
||||
return SubFieldDefinition(U32, 4);
|
||||
else if (str == "b21")
|
||||
return SubFieldDefinition(tag, S8, 1);
|
||||
return SubFieldDefinition(S8, 1);
|
||||
else if (str == "b22")
|
||||
return SubFieldDefinition(tag, S16, 2);
|
||||
return SubFieldDefinition(S16, 2);
|
||||
else if (str == "b24")
|
||||
return SubFieldDefinition(tag, S32, 4);
|
||||
return SubFieldDefinition(S32, 4);
|
||||
else
|
||||
return SubFieldDefinition();
|
||||
}
|
||||
@ -138,6 +145,7 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
|
||||
QByteArray ba;
|
||||
bool repeat = false;
|
||||
QVector<SubFieldDefinition> defs;
|
||||
QVector<QByteArray> defTags;
|
||||
|
||||
ba.resize(def.size);
|
||||
if (!(_file.seek(def.pos) && _file.read(ba.data(), ba.size()) == ba.size()))
|
||||
@ -155,6 +163,7 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
|
||||
int tag = 0;
|
||||
|
||||
defs.resize(tags.size());
|
||||
defTags.resize(tags.size());
|
||||
|
||||
while (it.hasNext()) {
|
||||
QRegularExpressionMatch match = it.next();
|
||||
@ -176,16 +185,17 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
|
||||
}
|
||||
|
||||
for (uint i = 0; i < cnt; i++) {
|
||||
SubFieldDefinition sfd(fieldType(typeStr, size, tags.at(tag)));
|
||||
SubFieldDefinition sfd(fieldType(typeStr, size));
|
||||
if (sfd.type() == Unknown)
|
||||
return false;
|
||||
defs[tag] = sfd;
|
||||
defTags[tag] = tags.at(tag);
|
||||
tag++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fields = SubFields(defs, repeat);
|
||||
fields = SubFields(defTags, defs, repeat);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -223,7 +233,8 @@ bool ISO8211::readDDR()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def, Data &data)
|
||||
bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
|
||||
const QVector<SubFieldDefinition> &fields, bool repeat, Data &data)
|
||||
{
|
||||
QByteArray ba;
|
||||
|
||||
@ -238,10 +249,10 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def, Data &data)
|
||||
|
||||
do {
|
||||
QVector<QVariant> row;
|
||||
row.resize(data.fields()->size());
|
||||
row.resize(fields.size());
|
||||
|
||||
for (int i = 0; i < data.fields()->size(); i++) {
|
||||
const SubFieldDefinition &f = data.fields()->at(i);
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
const SubFieldDefinition &f = fields.at(i);
|
||||
|
||||
switch (f.type()) {
|
||||
case String:
|
||||
@ -287,7 +298,7 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def, Data &data)
|
||||
}
|
||||
|
||||
data.append(row);
|
||||
} while (data.fields()->repeat() && dp < ep);
|
||||
} while (repeat && dp < ep);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -299,9 +310,9 @@ bool ISO8211::readRecord(Record &record)
|
||||
|
||||
QVector<FieldDefinition> fields;
|
||||
qint64 pos = _file.pos();
|
||||
int len = readDR(fields);
|
||||
|
||||
if (len < 0) {
|
||||
|
||||
if (readDR(fields) < 0) {
|
||||
_errorString = "Error reading DR";
|
||||
return false;
|
||||
}
|
||||
@ -310,6 +321,7 @@ bool ISO8211::readRecord(Record &record)
|
||||
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
const FieldDefinition &def = fields.at(i);
|
||||
Data data;
|
||||
|
||||
FieldsMap::const_iterator it = _map.find(def.tag);
|
||||
if (it == _map.constEnd()) {
|
||||
@ -317,15 +329,13 @@ bool ISO8211::readRecord(Record &record)
|
||||
return false;
|
||||
}
|
||||
|
||||
Data data(&it.value());
|
||||
|
||||
if (!readUDA(pos, def, data)) {
|
||||
if (!readUDA(pos, def, it->defs(), it->repeat(), data)) {
|
||||
_errorString = QString("Error reading %1 record")
|
||||
.arg(QString(def.tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
record[i] = Field(def.tag, data);
|
||||
record[i] = Field(def.tag, it->tags(), data);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -17,87 +17,17 @@ namespace ENC {
|
||||
class ISO8211
|
||||
{
|
||||
public:
|
||||
enum FieldType {Unknown, String, Array, S8, S16, S32, U8, U16, U32};
|
||||
|
||||
struct FieldDefinition
|
||||
{
|
||||
QByteArray tag;
|
||||
int pos;
|
||||
int size;
|
||||
};
|
||||
|
||||
class SubFieldDefinition
|
||||
{
|
||||
public:
|
||||
SubFieldDefinition() : _type(Unknown), _size(0) {}
|
||||
SubFieldDefinition(const QByteArray &tag, FieldType type, int size)
|
||||
: _tag(tag), _type(type), _size(size) {}
|
||||
|
||||
const QByteArray &tag() const {return _tag;}
|
||||
FieldType type() const {return _type;}
|
||||
int size() const {return _size;}
|
||||
|
||||
private:
|
||||
QByteArray _tag;
|
||||
FieldType _type;
|
||||
int _size;
|
||||
};
|
||||
|
||||
class SubFields
|
||||
{
|
||||
public:
|
||||
SubFields() : _repeat(false) {}
|
||||
SubFields(const QVector<SubFieldDefinition> &defs, bool repeat)
|
||||
: _defs(defs), _repeat(repeat) {}
|
||||
|
||||
int size() const {return _defs.size();}
|
||||
const SubFieldDefinition &at(int i) const {return _defs.at(i);}
|
||||
|
||||
bool repeat() const {return _repeat;}
|
||||
|
||||
private:
|
||||
QVector<SubFieldDefinition> _defs;
|
||||
bool _repeat;
|
||||
};
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
Data() : _fields(0) {}
|
||||
Data(const SubFields *fields) : _fields(fields) {}
|
||||
|
||||
int size() const {return _data.size();}
|
||||
const QVector<QVariant> &at(int i) const {return _data.at(i);}
|
||||
|
||||
const SubFields *fields() const {return _fields;}
|
||||
const QVariant *field(const QByteArray &name, int idx = 0) const
|
||||
{
|
||||
const QVector<QVariant> &v = _data.at(idx);
|
||||
|
||||
for (int i = 0; i < _fields->size(); i++)
|
||||
if (_fields->at(i).tag() == name)
|
||||
return &v.at(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ISO8211;
|
||||
|
||||
void append(QVector<QVariant> &row) {_data.append(row);}
|
||||
|
||||
QVector<QVector<QVariant> > _data;
|
||||
const SubFields *_fields;
|
||||
};
|
||||
typedef QVector<QVector<QVariant> > Data;
|
||||
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
Field() {}
|
||||
Field(const QByteArray &tag, const Data &data)
|
||||
: _tag(tag), _data(data) {}
|
||||
Field(const QByteArray &tag, const QVector<QByteArray> &subFields,
|
||||
const Data &data) : _tag(tag), _subFields(subFields), _data(data) {}
|
||||
|
||||
const QByteArray &tag() const {return _tag;}
|
||||
const QVector<QByteArray> subFields() const {return _subFields;}
|
||||
const Data &data() const {return _data;}
|
||||
|
||||
bool subfield(const char *name, int *val, int idx = 0) const;
|
||||
@ -105,7 +35,10 @@ public:
|
||||
bool subfield(const char *name, QByteArray *val, int idx = 0) const;
|
||||
|
||||
private:
|
||||
const QVariant *data(const QByteArray &name, int idx = 0) const;
|
||||
|
||||
QByteArray _tag;
|
||||
QVector<QByteArray> _subFields;
|
||||
Data _data;
|
||||
};
|
||||
|
||||
@ -120,14 +53,57 @@ public:
|
||||
static const Field *field(const Record &record, const QByteArray &name);
|
||||
|
||||
private:
|
||||
enum FieldType {Unknown, String, Array, S8, S16, S32, U8, U16, U32};
|
||||
|
||||
struct FieldDefinition
|
||||
{
|
||||
QByteArray tag;
|
||||
int pos;
|
||||
int size;
|
||||
};
|
||||
|
||||
class SubFieldDefinition
|
||||
{
|
||||
public:
|
||||
SubFieldDefinition() : _type(Unknown), _size(0) {}
|
||||
SubFieldDefinition(FieldType type, int size)
|
||||
: _type(type), _size(size) {}
|
||||
|
||||
FieldType type() const {return _type;}
|
||||
int size() const {return _size;}
|
||||
|
||||
private:
|
||||
FieldType _type;
|
||||
int _size;
|
||||
};
|
||||
|
||||
class SubFields
|
||||
{
|
||||
public:
|
||||
SubFields() : _repeat(false) {}
|
||||
SubFields(const QVector<QByteArray> &tags,
|
||||
const QVector<SubFieldDefinition> &defs, bool repeat)
|
||||
: _tags(tags), _defs(defs), _repeat(repeat) {}
|
||||
|
||||
const QVector<QByteArray> &tags() const {return _tags;}
|
||||
const QVector<SubFieldDefinition> &defs() const {return _defs;}
|
||||
|
||||
bool repeat() const {return _repeat;}
|
||||
|
||||
private:
|
||||
QVector<QByteArray> _tags;
|
||||
QVector<SubFieldDefinition> _defs;
|
||||
bool _repeat;
|
||||
};
|
||||
|
||||
typedef QMap<QByteArray, SubFields> FieldsMap;
|
||||
|
||||
static SubFieldDefinition fieldType(const QString &str, int cnt,
|
||||
const QByteArray &tag);
|
||||
static SubFieldDefinition fieldType(const QString &str, int cnt);
|
||||
|
||||
int readDR(QVector<FieldDefinition> &fields);
|
||||
bool readDDA(const FieldDefinition &def, SubFields &fields);
|
||||
bool readUDA(quint64 pos, const FieldDefinition &def, Data &data);
|
||||
bool readUDA(quint64 pos, const FieldDefinition &def,
|
||||
const QVector<SubFieldDefinition> &fields, bool repeat, Data &data);
|
||||
|
||||
QFile _file;
|
||||
FieldsMap _map;
|
||||
@ -135,22 +111,9 @@ private:
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const ISO8211::FieldDefinition &def)
|
||||
{
|
||||
dbg.nospace() << "FieldDefinition(" << def.tag << ", " << def.size << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const ISO8211::SubFieldDefinition &def)
|
||||
{
|
||||
dbg.nospace() << "SubField(" << def.tag() << ", " << def.type() << ", "
|
||||
<< def.size() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const ISO8211::Field &field)
|
||||
{
|
||||
dbg.nospace() << "Field(" << field.tag() << ")";
|
||||
dbg.nospace() << "Field(" << field.tag() << ", " << field.subFields() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -560,7 +560,8 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
|
||||
|| (OBJL == SISTAT && key == CATSIT)
|
||||
|| (OBJL == I_SISTAT && key == I_CATSIT)
|
||||
|| (OBJL == RDOCAL && key == TRAFIC)
|
||||
|| (OBJL == I_RDOCAL && key == TRAFIC))
|
||||
|| (OBJL == I_RDOCAL && key == TRAFIC)
|
||||
|| (OBJL == SILTNK && key == CATSIL))
|
||||
subtype = av.at(1).toByteArray().toUInt();
|
||||
else if (OBJL == I_DISMAR && key == CATDIS)
|
||||
subtype |= av.at(1).toByteArray().toUInt();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define CANALS 23
|
||||
#define CGUSTA 29
|
||||
#define COALNE 30
|
||||
#define CONZNE 31
|
||||
#define CONVYR 34
|
||||
#define CRANES 35
|
||||
#define CURENT 36
|
||||
|
@ -104,6 +104,8 @@ void Style::polygonStyle()
|
||||
_polygons[SUBTYPE(MARKUL, 3)] = Polygon(QImage(":/marine/fishing-farm-line.png"));
|
||||
_polygons[SUBTYPE(I_BERTHS, 6)] = Polygon(Qt::NoBrush, QPen(QColor("#eb49eb"),
|
||||
1, Qt::DashLine));
|
||||
_polygons[TYPE(CONZNE)] = Polygon(Qt::NoBrush, QPen(QColor("#eb49eb"), 1,
|
||||
Qt::DashDotLine));
|
||||
|
||||
_drawOrder
|
||||
<< TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0)
|
||||
@ -122,7 +124,7 @@ void Style::polygonStyle()
|
||||
<< SUBTYPE(RESARE, 9) << SUBTYPE(RESARE, 2) << SUBTYPE(I_RESARE, 2)
|
||||
<< SUBTYPE(RESARE, 17) << SUBTYPE(I_RESARE, 17) << SUBTYPE(RESARE, 12)
|
||||
<< SUBTYPE(I_RESARE, 12) << SUBTYPE(RESARE, 1) << TYPE(CBLARE)
|
||||
<< TYPE(PIPARE) << TYPE(PRCARE) << SUBTYPE(MARKUL, 3);
|
||||
<< TYPE(PIPARE) << TYPE(PRCARE) << SUBTYPE(MARKUL, 3) << TYPE(CONZNE);
|
||||
}
|
||||
|
||||
void Style::lineStyle()
|
||||
@ -254,7 +256,11 @@ void Style::pointStyle()
|
||||
_points[TYPE(RDOSTA)] = Point(QImage(":/marine/radio.png"));
|
||||
_points[TYPE(RADSTA)] = Point(QImage(":/marine/radar.png"));
|
||||
_points[TYPE(RTPBCN)] = Point(QImage(":/marine/radar-transponder.png"));
|
||||
_points[TYPE(SILTNK)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[SUBTYPE(SILTNK, 0)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[SUBTYPE(SILTNK, 1)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[SUBTYPE(SILTNK, 2)] = Point(QImage(":/marine/tank.png"));
|
||||
_points[SUBTYPE(SILTNK, 3)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[SUBTYPE(SILTNK, 4)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[TYPE(I_TRNBSN)] = Point(QImage(":/marine/turning-basin.png"));
|
||||
_points[TYPE(I_TRNBSN)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(I_WTWGAG)] = Point(QImage(":/marine/gauge.png"), Small);
|
||||
|
@ -405,8 +405,10 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
}
|
||||
|
||||
Map *AQMMap::create(const QString &path, bool *isDir)
|
||||
Map *AQMMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -38,7 +38,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
struct File {
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "atlas.h"
|
||||
|
||||
|
||||
#define ZOOM_THRESHOLD 0.9
|
||||
#define ZOOM_THRESHOLD 0.8
|
||||
|
||||
#define TL(m) ((m)->xy2pp((m)->bounds().topLeft()))
|
||||
#define BR(m) ((m)->xy2pp((m)->bounds().bottomRight()))
|
||||
@ -27,6 +27,34 @@ static bool yCmp(OziMap *m1, OziMap *m2)
|
||||
return TL(m1).y() > TL(m2).y();
|
||||
}
|
||||
|
||||
static QString calibrationFile(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
QFileInfoList files = dir.entryInfoList(QDir::Files);
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const QFileInfo &fi = files.at(i);
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (suffix == "map" || suffix == "gmi")
|
||||
return fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QString tbaFile(const QStringList &files)
|
||||
{
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
QFileInfo fi(files.at(i));
|
||||
|
||||
if (fi.path() == "." && fi.suffix().toLower() == "tba")
|
||||
return files.at(i);
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void Atlas::computeZooms()
|
||||
{
|
||||
std::sort(_maps.begin(), _maps.end(), resCmp);
|
||||
@ -72,8 +100,9 @@ void Atlas::computeBounds()
|
||||
QRectF(offsets.at(i), _maps.at(i)->bounds().size()));
|
||||
}
|
||||
|
||||
Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _valid(false)
|
||||
Atlas::Atlas(const QString &fileName, bool TAR, const Projection &proj,
|
||||
QObject *parent) : Map(fileName, parent), _zoom(0), _mapIndex(-1),
|
||||
_valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QByteArray ba;
|
||||
@ -86,7 +115,11 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
QString tbaFileName = fi.completeBaseName() + ".tba";
|
||||
QString tbaFileName(tbaFile(tar.files()));
|
||||
if (tbaFileName.isNull()) {
|
||||
_errorString = "No tba file found";
|
||||
return;
|
||||
}
|
||||
ba = tar.file(tbaFileName);
|
||||
} else {
|
||||
QFile tbaFile(fileName);
|
||||
@ -97,7 +130,7 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
ba = tbaFile.readAll();
|
||||
}
|
||||
if (!ba.startsWith("Atlas 1.0")) {
|
||||
_errorString = "Missing or invalid tba file";
|
||||
_errorString = "Invalid tba file";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -108,38 +141,41 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
QFileInfoList maps = zdir.entryInfoList(QDir::Dirs
|
||||
| QDir::NoDotAndDotDot);
|
||||
for (int i = 0; i < maps.count(); i++) {
|
||||
QString mapFile = maps.at(i).absoluteFilePath() + "/"
|
||||
+ maps.at(i).fileName() + ".map";
|
||||
|
||||
OziMap *map;
|
||||
if (tar.isOpen())
|
||||
map = new OziMap(mapFile, tar, this);
|
||||
else
|
||||
map = new OziMap(mapFile, TAR, this);
|
||||
if (TAR)
|
||||
map = new OziMap(maps.at(i).absoluteFilePath(), tar, proj, this);
|
||||
else {
|
||||
QString cf(calibrationFile(maps.at(i).absoluteFilePath()));
|
||||
if (cf.isNull()) {
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
map = new OziMap(cf, proj, this);
|
||||
}
|
||||
|
||||
if (map->isValid())
|
||||
_maps.append(map);
|
||||
else {
|
||||
_errorString = QString("Error loading map: %1: %2")
|
||||
.arg(mapFile, map->errorString());
|
||||
return;
|
||||
qWarning("%s: %s", qPrintable(map->path()),
|
||||
qPrintable(map->errorString()));
|
||||
delete map;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_maps.isEmpty()) {
|
||||
_errorString = "No maps found in atlas";
|
||||
_errorString = "No usable map found in atlas";
|
||||
return;
|
||||
}
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
RectC Atlas::llBounds(const Projection &proj)
|
||||
RectC Atlas::llBounds()
|
||||
{
|
||||
RectC bounds;
|
||||
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
bounds |= _maps.at(i)->llBounds(proj);
|
||||
bounds |= _maps.at(i)->llBounds();
|
||||
|
||||
return bounds;
|
||||
}
|
||||
@ -295,18 +331,34 @@ void Atlas::unload()
|
||||
_bounds.clear();
|
||||
}
|
||||
|
||||
Map *Atlas::createTAR(const QString &path, bool *isDir)
|
||||
Map *Atlas::createTAR(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
||||
return new Atlas(path, true);
|
||||
return new Atlas(path, true, proj);
|
||||
}
|
||||
|
||||
Map *Atlas::createTBA(const QString &path, bool *isDir)
|
||||
Map *Atlas::createTBA(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
||||
return new Atlas(path, false);
|
||||
return new Atlas(path, false, proj);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Atlas::Bounds &bounds)
|
||||
{
|
||||
dbg.nospace() << "Bounds(" << bounds.xy << ", " << bounds.pp << ")";
|
||||
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Atlas::Zoom &zoom)
|
||||
{
|
||||
dbg.nospace() << "Zoom(" << zoom.first << ", " << zoom.last << ")";
|
||||
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -12,12 +12,13 @@ class Atlas : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Atlas(const QString &fileName, bool TAR, QObject *parent = 0);
|
||||
Atlas(const QString &fileName, bool TAR, const Projection &proj,
|
||||
QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &proj);
|
||||
RectC llBounds();
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -37,8 +38,10 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *createTAR(const QString &path, bool *isDir);
|
||||
static Map *createTBA(const QString &path, bool *isDir);
|
||||
static Map *createTAR(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
static Map *createTBA(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
|
||||
private:
|
||||
struct Zoom {
|
||||
@ -61,6 +64,9 @@ private:
|
||||
void computeZooms();
|
||||
void computeBounds();
|
||||
|
||||
friend QDebug operator<<(QDebug dbg, const Bounds &bounds);
|
||||
friend QDebug operator<<(QDebug dbg, const Zoom &zoom);
|
||||
|
||||
QString _name;
|
||||
|
||||
QList<OziMap*> _maps;
|
||||
@ -73,4 +79,9 @@ private:
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Atlas::Zoom &zoom);
|
||||
QDebug operator<<(QDebug dbg, const Atlas::Bounds &bounds);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // ATLAS_H
|
||||
|
@ -462,8 +462,10 @@ void BSBMap::unload()
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
Map *BSBMap::create(const QString &path, bool *isMap)
|
||||
Map *BSBMap::create(const QString &path, const Projection &proj, bool *isMap)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isMap);
|
||||
|
||||
private:
|
||||
bool parseBSB(const QByteArray &line);
|
||||
|
@ -378,8 +378,10 @@ void ENCAtlas::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *ENCAtlas::create(const QString &path, bool *isDir)
|
||||
Map *ENCAtlas::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _llBounds;}
|
||||
RectC llBounds() {return _llBounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -44,7 +44,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private slots:
|
||||
void jobFinished(ENCJob *job);
|
||||
|
@ -345,8 +345,10 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *ENCMap::create(const QString &path, bool *isMap)
|
||||
Map *ENCMap::create(const QString &path, const Projection &proj, bool *isMap)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _llBounds;}
|
||||
RectC llBounds() {return _llBounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -45,7 +45,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isMap);
|
||||
|
||||
private slots:
|
||||
void jobFinished(ENCJob *job);
|
||||
|
@ -301,8 +301,10 @@ void GEMFMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
}
|
||||
|
||||
Map *GEMFMap::create(const QString &path, bool *isDir)
|
||||
Map *GEMFMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
GEMFMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
|
||||
int zoom() const {return _zi;}
|
||||
void setZoom(int zoom) {_zi = zoom;}
|
||||
@ -35,7 +35,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Region {
|
||||
|
@ -73,8 +73,10 @@ void GeoTIFFMap::unload()
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
Map *GeoTIFFMap::create(const QString &path, bool *isDir)
|
||||
Map *GeoTIFFMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
Projection _projection;
|
||||
|
74
src/map/gmifile.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include <QIODevice>
|
||||
#include "gmifile.h"
|
||||
|
||||
static CalibrationPoint calibrationPoint(const QByteArray line)
|
||||
{
|
||||
bool xOk, yOk, lonOk, latOk;
|
||||
QList<QByteArray> list = line.split(';');
|
||||
if (list.size() != 4)
|
||||
return CalibrationPoint();
|
||||
|
||||
int x = list.at(0).toInt(&xOk);
|
||||
int y = list.at(1).toInt(&yOk);
|
||||
double lon = list.at(2).toDouble(&lonOk);
|
||||
double lat = list.at(3).toDouble(&latOk);
|
||||
|
||||
return (xOk && yOk && latOk && lonOk)
|
||||
? CalibrationPoint(PointD(x, y), Coordinates(lon, lat))
|
||||
: CalibrationPoint();
|
||||
}
|
||||
|
||||
bool GmiFile::parse(QIODevice &device)
|
||||
{
|
||||
int ln = 1;
|
||||
int width, height;
|
||||
bool ok;
|
||||
|
||||
if (!device.open(QIODevice::ReadOnly)) {
|
||||
_errorString = device.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!device.atEnd()) {
|
||||
QByteArray line = device.readLine(4096);
|
||||
|
||||
if (ln == 1) {
|
||||
if (!line.startsWith("Map Calibration data file")) {
|
||||
_errorString = "Not a GMI file";
|
||||
return false;
|
||||
}
|
||||
} else if (ln == 2)
|
||||
_image = line.trimmed();
|
||||
else if (ln == 3) {
|
||||
width = line.toInt(&ok);
|
||||
if (!ok || ok <= 0) {
|
||||
_errorString = "Invalid image width";
|
||||
return false;
|
||||
}
|
||||
} else if (ln == 4) {
|
||||
height = line.toInt(&ok);
|
||||
if (!ok || ok <= 0) {
|
||||
_errorString = "Invalid image height";
|
||||
return false;
|
||||
}
|
||||
_size = QSize(width, height);
|
||||
} else {
|
||||
CalibrationPoint cp(calibrationPoint(line));
|
||||
if (cp.isValid())
|
||||
_points.append(cp);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ln++;
|
||||
}
|
||||
|
||||
device.close();
|
||||
|
||||
return (_points.size() >= 2);
|
||||
}
|
||||
|
||||
GmiFile::GmiFile(QIODevice &file)
|
||||
{
|
||||
_valid = parse(file);
|
||||
}
|
31
src/map/gmifile.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef GMIFILE_H
|
||||
#define GMIFILE_H
|
||||
|
||||
#include "calibrationpoint.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
class GmiFile
|
||||
{
|
||||
public:
|
||||
GmiFile(QIODevice &file);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
const QString &image() const {return _image;}
|
||||
const QSize &size() const {return _size;}
|
||||
const QList<CalibrationPoint> &calibrationPoints() const {return _points;}
|
||||
|
||||
private:
|
||||
bool parse(QIODevice &device);
|
||||
|
||||
QString _image;
|
||||
QSize _size;
|
||||
QList<CalibrationPoint> _points;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // GMIFILE_H
|
@ -264,16 +264,20 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map* IMGMap::createIMG(const QString &path, bool *isDir)
|
||||
Map* IMGMap::createIMG(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new IMGMap(path, false);
|
||||
}
|
||||
|
||||
Map* IMGMap::createGMAP(const QString &path, bool *isDir)
|
||||
Map* IMGMap::createGMAP(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
QString name() const {return _data.first()->name();}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _data.first()->bounds();}
|
||||
RectC llBounds() {return _data.first()->bounds();}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -77,8 +77,10 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map* createIMG(const QString &path, bool *isDir);
|
||||
static Map* createGMAP(const QString &path, bool *isDir);
|
||||
static Map* createIMG(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
static Map* createGMAP(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
|
||||
private slots:
|
||||
void jobFinished(IMGMapJob *job);
|
||||
|
@ -274,8 +274,10 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
tree.Search(min, max, cb, &ctx);
|
||||
}
|
||||
|
||||
Map *JNXMap::create(const QString &path, bool *isDir)
|
||||
Map *JNXMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -19,7 +19,7 @@ public:
|
||||
~JNXMap();
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom) {_zoom = zoom;}
|
||||
@ -39,7 +39,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Tile {
|
||||
|
@ -484,8 +484,10 @@ void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex)
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
Map *KMZMap::create(const QString &path, bool *isDir)
|
||||
Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
KMZMap(const QString &fileName, QObject *parent = 0);
|
||||
~KMZMap();
|
||||
|
||||
RectC llBounds(const Projection &) {return _llbounds;}
|
||||
RectC llBounds() {return _llbounds;}
|
||||
QRectF bounds();
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -39,7 +39,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
class Overlay {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
|
||||
#define SAMPLES 100
|
||||
#define DELTA 1e-6
|
||||
|
||||
static void growLeft(const Coordinates &c, RectC &rect)
|
||||
{
|
||||
@ -29,12 +30,8 @@ static void growBottom(const Coordinates &c, RectC &rect)
|
||||
rect.setBottom(c.lat());
|
||||
}
|
||||
|
||||
RectC Map::llBounds(const Projection &proj)
|
||||
RectC Map::llBounds()
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
/* We use bounds() and xy2ll() here as this fallback implementation is
|
||||
used ONLY for maps providing those functions since map creation. */
|
||||
QRectF b(bounds());
|
||||
double dx = b.width() / SAMPLES;
|
||||
double dy = b.height() / SAMPLES;
|
||||
@ -55,14 +52,27 @@ RectC Map::llBounds(const Projection &proj)
|
||||
growRight(xy2ll(QPointF(b.right(), y)), rect);
|
||||
}
|
||||
|
||||
if (rect.right() <= -180.0 + DELTA)
|
||||
rect.setRight(180.0);
|
||||
if (rect.left() >= 180.0 - DELTA)
|
||||
rect.setLeft(-180.0);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
qreal Map::resolution(const QRectF &rect)
|
||||
{
|
||||
qreal cy = rect.center().y();
|
||||
QPointF cl(rect.left(), cy);
|
||||
QPointF cr(rect.right(), cy);
|
||||
/* The haversine formula used in Coordinates::distanceTo() only gives
|
||||
"half world" distances and shorter so we have to use only the center
|
||||
"half rectangle" in case e.g. world map bounds are on the input */
|
||||
QRectF halfRect(QPointF(rect.left() + (rect.width() / 4.0),
|
||||
rect.top() + (rect.height() / 4.0)),
|
||||
QPointF(rect.right() - (rect.width() / 4.0),
|
||||
rect.bottom() - (rect.height() / 4.0)));
|
||||
|
||||
qreal cy = halfRect.center().y();
|
||||
QPointF cl(halfRect.left(), cy);
|
||||
QPointF cr(halfRect.right(), cy);
|
||||
|
||||
qreal ds = xy2ll(cl).distanceTo(xy2ll(cr));
|
||||
qreal ps = QLineF(cl, cr).length();
|
||||
|
@ -28,19 +28,19 @@ public:
|
||||
: QObject(parent), _path(path) {}
|
||||
virtual ~Map() {}
|
||||
|
||||
/* Functions available since map creation */
|
||||
const QString &path() const {return _path;}
|
||||
virtual QString name() const {return Util::file2name(path());}
|
||||
virtual RectC llBounds(const Projection &proj);
|
||||
|
||||
virtual bool isValid() const {return true;}
|
||||
virtual bool isReady() const {return true;}
|
||||
virtual QString errorString() const {return QString();}
|
||||
|
||||
/* Functions that shall be called after load() */
|
||||
virtual void load(const Projection &, const Projection &, qreal, bool) {}
|
||||
virtual void unload() {}
|
||||
|
||||
/* llBounds() is mandatory for maps that do not provide bounds() until
|
||||
load() is called! */
|
||||
virtual RectC llBounds();
|
||||
virtual QRectF bounds() = 0;
|
||||
virtual qreal resolution(const QRectF &rect);
|
||||
|
||||
|
@ -43,6 +43,7 @@ MapList::ParserMap MapList::parsers()
|
||||
map.insert("rtmap", &RMap::create);
|
||||
map.insert("map", &MapsforgeMap::create);
|
||||
map.insert("map", &OziMap::createMAP);
|
||||
map.insert("gmi", &OziMap::createMAP);
|
||||
map.insert("kap", &BSBMap::create);
|
||||
map.insert("kmz", &KMZMap::create);
|
||||
map.insert("aqm", &AQMMap::create);
|
||||
@ -64,7 +65,7 @@ MapList::ParserMap MapList::parsers()
|
||||
|
||||
MapList::ParserMap MapList::_parsers = parsers();
|
||||
|
||||
Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
ParserMap::iterator it;
|
||||
QFileInfo fi(Util::displayName(path));
|
||||
@ -75,7 +76,7 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
if ((it = _parsers.find(suffix)) != _parsers.end()) {
|
||||
while (it != _parsers.end() && it.key() == suffix) {
|
||||
delete map;
|
||||
map = it.value()(path, isDir);
|
||||
map = it.value()(path, proj, isDir);
|
||||
if (map->isValid())
|
||||
return map;
|
||||
else
|
||||
@ -84,7 +85,7 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
}
|
||||
} else {
|
||||
for (it = _parsers.begin(); it != _parsers.end(); it++) {
|
||||
map = it.value()(path, isDir);
|
||||
map = it.value()(path, proj, isDir);
|
||||
if (map->isValid())
|
||||
return map;
|
||||
else {
|
||||
@ -102,7 +103,8 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
return map ? map : new InvalidMap(path, "Unknown file format");
|
||||
}
|
||||
|
||||
TreeNode<Map*> MapList::loadDir(const QString &path, TreeNode<Map*> *parent)
|
||||
TreeNode<Map*> MapList::loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map*> *parent)
|
||||
{
|
||||
QDir md(path);
|
||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -119,12 +121,12 @@ TreeNode<Map*> MapList::loadDir(const QString &path, TreeNode<Map*> *parent)
|
||||
QString suffix = fi.suffix().toLower();
|
||||
|
||||
if (fi.isDir()) {
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), &tree));
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), proj, &tree));
|
||||
if (!child.isEmpty())
|
||||
tree.addChild(child);
|
||||
} else if (filter().contains("*." + suffix)) {
|
||||
bool isDir = false;
|
||||
Map *map = loadFile(fi.absoluteFilePath(), &isDir);
|
||||
Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir);
|
||||
if (isDir) {
|
||||
if (parent)
|
||||
parent->addItem(map);
|
||||
@ -139,13 +141,13 @@ TreeNode<Map*> MapList::loadDir(const QString &path, TreeNode<Map*> *parent)
|
||||
return tree;
|
||||
}
|
||||
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path)
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path, const Projection &proj)
|
||||
{
|
||||
if (QFileInfo(path).isDir())
|
||||
return loadDir(path);
|
||||
return loadDir(path, proj);
|
||||
else {
|
||||
TreeNode<Map*> tree;
|
||||
tree.addItem(loadFile(path));
|
||||
tree.addItem(loadFile(path, proj));
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
@ -173,7 +175,8 @@ QString MapList::formats()
|
||||
+ qApp->translate("MapList", "Osmdroid SQLite maps") + " (*.sqlite);;"
|
||||
+ qApp->translate("MapList", "Locus/OsmAnd/RMaps SQLite maps")
|
||||
+ " (*.sqlitedb);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases")
|
||||
+ " (*.tar *.tba *.gmi *.map);;"
|
||||
+ qApp->translate("MapList", "GeoTIFF images") + " (*.tif *.tiff);;"
|
||||
+ qApp->translate("MapList", "World-file georeferenced images")
|
||||
+ " (*.wld *.jgw *.gfw *.pgw *.tfw);;"
|
||||
|
@ -10,16 +10,18 @@ class Projection;
|
||||
class MapList
|
||||
{
|
||||
public:
|
||||
static TreeNode<Map*> loadMaps(const QString &path);
|
||||
static TreeNode<Map*> loadMaps(const QString &path, const Projection &proj);
|
||||
static QString formats();
|
||||
static QStringList filter();
|
||||
|
||||
private:
|
||||
typedef Map*(*ParserCb)(const QString &, bool *isDir);
|
||||
typedef Map*(*ParserCb)(const QString &, const Projection &, bool *);
|
||||
typedef QMultiMap<QString, ParserCb> ParserMap;
|
||||
|
||||
static Map *loadFile(const QString &path, bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path, TreeNode<Map*> *parent = 0);
|
||||
static Map *loadFile(const QString &path, const Projection &proj,
|
||||
bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map*> *parent = 0);
|
||||
|
||||
static ParserMap parsers();
|
||||
static ParserMap _parsers;
|
||||
|
@ -209,8 +209,11 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *MapsforgeMap::create(const QString &path, bool *isMap)
|
||||
Map *MapsforgeMap::create(const QString &path, const Projection &proj,
|
||||
bool *isMap)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
MapsforgeMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _data.bounds();}
|
||||
RectC llBounds() {return _data.bounds();}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -74,7 +74,7 @@ public:
|
||||
bool isValid() const {return _data.isValid();}
|
||||
QString errorString() const {return _data.errorString();}
|
||||
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isMap);
|
||||
|
||||
private slots:
|
||||
void jobFinished(MapsforgeMapJob *job);
|
||||
|
@ -214,8 +214,9 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
||||
}
|
||||
}
|
||||
|
||||
Map *MapSource::create(const QString &path, bool *isDir)
|
||||
Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
Config config;
|
||||
QFile file(path);
|
||||
|
||||
|
@ -15,7 +15,7 @@ class Projection;
|
||||
class MapSource
|
||||
{
|
||||
public:
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
|
@ -338,8 +338,10 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p)
|
||||
* coordinatesRatio());
|
||||
}
|
||||
|
||||
Map *MBTilesMap::create(const QString &path, bool *isDir)
|
||||
Map *MBTilesMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -13,7 +13,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zi;}
|
||||
@ -34,7 +34,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
qreal tileSize() const;
|
||||
|
@ -590,8 +590,10 @@ Coordinates OruxMap::xy2ll(const QPointF &p)
|
||||
return z.projection.xy2ll(z.transform.img2proj(p * _mapRatio));
|
||||
}
|
||||
|
||||
Map *OruxMap::create(const QString &path, bool *isDir)
|
||||
Map *OruxMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Zoom {
|
||||
|
@ -309,8 +309,11 @@ Coordinates OsmdroidMap::xy2ll(const QPointF &p)
|
||||
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
|
||||
}
|
||||
|
||||
Map *OsmdroidMap::create(const QString &path, bool *isDir)
|
||||
Map *OsmdroidMap::create(const QString &path, const Projection &proj,
|
||||
bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
OsmdroidMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -32,7 +32,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
int limitZoom(int zoom) const;
|
||||
|
@ -12,58 +12,135 @@
|
||||
#include "ozf.h"
|
||||
#include "image.h"
|
||||
#include "mapfile.h"
|
||||
#include "gmifile.h"
|
||||
#include "rectd.h"
|
||||
#include "ozimap.h"
|
||||
|
||||
|
||||
OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
static QString tarFile(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
QFileInfoList files = dir.entryInfoList(QDir::Files);
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const QFileInfo &fi = files.at(i);
|
||||
|
||||
if (fi.suffix().toLower() == "tar")
|
||||
return fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString OziMap::calibrationFile(const QStringList &files, const QString path,
|
||||
CalibrationType &type)
|
||||
{
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
QFileInfo fi(files.at(i));
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (path.endsWith(fi.path())) {
|
||||
if (suffix == "map") {
|
||||
type = MAP;
|
||||
return files.at(i);
|
||||
} else if (suffix == "gmi") {
|
||||
type = GMI;
|
||||
return files.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type = Unknown;
|
||||
return QString();
|
||||
}
|
||||
|
||||
OziMap::OziMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (suffix == "tar") {
|
||||
CalibrationType type;
|
||||
|
||||
if (TAR) {
|
||||
_tar = new Tar(fileName);
|
||||
if (!_tar->open()) {
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
QStringList files(_tar->files());
|
||||
QString cf(calibrationFile(files, ".", type));
|
||||
|
||||
QString mapFileName = fi.completeBaseName() + ".map";
|
||||
QByteArray ba = _tar->file(mapFileName);
|
||||
if (ba.isNull()) {
|
||||
_errorString = "Map file not found";
|
||||
return;
|
||||
}
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
return;
|
||||
if (type == GMI) {
|
||||
QByteArray ba(_tar->file(cf));
|
||||
QBuffer buffer(&ba);
|
||||
GmiFile gmi(buffer);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = Util::file2name(fileName);
|
||||
_map.size = gmi.size();
|
||||
_map.path = gmi.image();
|
||||
_calibrationPoints = gmi.calibrationPoints();
|
||||
_projection = proj;
|
||||
computeTransform();
|
||||
}
|
||||
} else if (type == MAP) {
|
||||
QByteArray ba(_tar->file(cf));
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setTileInfo(_tar->files()))
|
||||
if (!setTileInfo(files))
|
||||
return;
|
||||
|
||||
_tar->close();
|
||||
} else {
|
||||
QFile file(fileName);
|
||||
MapFile mf(file);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
return;
|
||||
|
||||
if (suffix == "map") {
|
||||
MapFile mf(file);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
} else if (suffix == "gmi") {
|
||||
GmiFile gmi(file);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = Util::file2name(fileName);
|
||||
_map.size = gmi.size();
|
||||
_map.path = gmi.image();
|
||||
_calibrationPoints = gmi.calibrationPoints();
|
||||
_projection = proj;
|
||||
computeTransform();
|
||||
}
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
_errorString = "Unknown file type";
|
||||
return;
|
||||
}
|
||||
|
||||
QDir set(fi.absolutePath() + "/" + "set");
|
||||
@ -79,34 +156,51 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
OziMap::OziMap(const QString &dirName, Tar &tar, const Projection &proj,
|
||||
QObject *parent) : Map(dirName, parent), _img(0), _tar(0), _ozf(0), _zoom(0),
|
||||
_mapRatio(1.0), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QFileInfo map(fi.absolutePath());
|
||||
QFileInfo layer(map.absolutePath());
|
||||
QString mapFile = layer.fileName() + "/" + map.fileName() + "/"
|
||||
+ fi.fileName();
|
||||
CalibrationType type;
|
||||
QString cf(calibrationFile(tar.files(), dirName, type));
|
||||
|
||||
QByteArray ba = tar.file(mapFile);
|
||||
if (ba.isNull()) {
|
||||
_errorString = "Map file not found";
|
||||
return;
|
||||
}
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
if (type == MAP) {
|
||||
QByteArray ba = tar.file(cf);
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
} else if (type == GMI) {
|
||||
QByteArray ba = tar.file(cf);
|
||||
QBuffer buffer(&ba);
|
||||
GmiFile gmi(buffer);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
_name = Util::file2name(cf);
|
||||
_map.size = gmi.size();
|
||||
_calibrationPoints = gmi.calibrationPoints();
|
||||
_projection = proj;
|
||||
computeTransform();
|
||||
} else {
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
|
||||
_name = mf.name();
|
||||
_map.size = mf.size();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
|
||||
|
||||
QString tf(tarFile(dirName));
|
||||
if (tf.isNull()) {
|
||||
_errorString = "No map tar file found";
|
||||
return;
|
||||
}
|
||||
_tar = new Tar(tf);
|
||||
if (!_tar->open()) {
|
||||
_errorString = _tar->fileName() + ": error reading tar file";
|
||||
return;
|
||||
@ -208,10 +302,13 @@ bool OziMap::setTileInfo(const QStringList &tiles, const QString &path)
|
||||
void OziMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
if (!_calibrationPoints.isEmpty()) {
|
||||
_projection = in;
|
||||
computeTransform();
|
||||
}
|
||||
|
||||
if (_tar) {
|
||||
Q_ASSERT(!_tar->isOpen());
|
||||
@ -395,18 +492,28 @@ void OziMap::rescale(int zoom)
|
||||
_scale = _ozf->scale(zoom);
|
||||
}
|
||||
|
||||
Map *OziMap::createTAR(const QString &path, bool *isDir)
|
||||
void OziMap::computeTransform()
|
||||
{
|
||||
QList<ReferencePoint> rp;
|
||||
|
||||
for (int i = 0; i < _calibrationPoints.size(); i++)
|
||||
rp.append(_calibrationPoints.at(i).rp(_projection));
|
||||
|
||||
_transform = Transform(rp);
|
||||
}
|
||||
|
||||
Map *OziMap::createTAR(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new OziMap(path, true);
|
||||
return new OziMap(path, proj);
|
||||
}
|
||||
|
||||
Map *OziMap::createMAP(const QString &path, bool *isDir)
|
||||
Map *OziMap::createMAP(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new OziMap(path, false);
|
||||
return new OziMap(path, proj);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "transform.h"
|
||||
#include "projection.h"
|
||||
#include "calibrationpoint.h"
|
||||
#include "map.h"
|
||||
|
||||
class Tar;
|
||||
@ -14,8 +15,10 @@ class OziMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OziMap(const QString &fileName, bool TAR, QObject *parent = 0);
|
||||
OziMap(const QString &fileName, Tar &tar, QObject *parent = 0);
|
||||
OziMap(const QString &fileName, const Projection &proj,
|
||||
QObject *parent = 0);
|
||||
OziMap(const QString &dirName, Tar &tar, const Projection &proj,
|
||||
QObject *parent = 0);
|
||||
~OziMap();
|
||||
|
||||
QString name() const {return _name;}
|
||||
@ -47,10 +50,16 @@ public:
|
||||
QPointF pp2xy(const PointD &p) const
|
||||
{return _transform.proj2img(p) / _mapRatio;}
|
||||
|
||||
static Map *createTAR(const QString &path, bool *isDir);
|
||||
static Map *createMAP(const QString &path, bool *isDir);
|
||||
static Map *createTAR(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
static Map *createMAP(const QString &path, const Projection &proj,
|
||||
bool *isDir);
|
||||
|
||||
private:
|
||||
enum CalibrationType {
|
||||
Unknown, MAP, GMI
|
||||
};
|
||||
|
||||
struct ImageInfo {
|
||||
QSize size;
|
||||
QString path;
|
||||
@ -66,6 +75,10 @@ private:
|
||||
void drawImage(QPainter *painter, const QRectF &rect, Flags flags) const;
|
||||
|
||||
void rescale(int zoom);
|
||||
void computeTransform();
|
||||
|
||||
static QString calibrationFile(const QStringList &files, const QString path,
|
||||
CalibrationType &type);
|
||||
|
||||
QString _name;
|
||||
Projection _projection;
|
||||
@ -77,6 +90,7 @@ private:
|
||||
int _zoom;
|
||||
QPointF _scale;
|
||||
qreal _mapRatio;
|
||||
QList<CalibrationPoint> _calibrationPoints;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
@ -491,8 +491,10 @@ void QCTMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *QCTMap::create(const QString &path, bool *isDir)
|
||||
Map *QCTMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
bool readName(QDataStream &stream);
|
||||
|
@ -460,8 +460,10 @@ void RMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *RMap::create(const QString &path, bool *isDir)
|
||||
Map *RMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Header {
|
||||
|
@ -256,8 +256,10 @@ Coordinates SqliteMap::xy2ll(const QPointF &p)
|
||||
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
|
||||
}
|
||||
|
||||
Map *SqliteMap::create(const QString &path, bool *isDir)
|
||||
Map *SqliteMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
SqliteMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -32,7 +32,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
int limitZoom(int zoom) const;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QtConcurrent>
|
||||
#include "tileloader.h"
|
||||
|
||||
#define SUBSTITUTE_CHAR '$'
|
||||
|
||||
class TileImage
|
||||
{
|
||||
@ -34,6 +35,27 @@ private:
|
||||
int _scaledSize;
|
||||
};
|
||||
|
||||
static QString fsSafeStr(const QString &str)
|
||||
{
|
||||
QString ret(str);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
ret.replace('<', SUBSTITUTE_CHAR);
|
||||
ret.replace('>', SUBSTITUTE_CHAR);
|
||||
ret.replace(':', SUBSTITUTE_CHAR);
|
||||
ret.replace('"', SUBSTITUTE_CHAR);
|
||||
ret.replace('/', SUBSTITUTE_CHAR);
|
||||
ret.replace('\\', SUBSTITUTE_CHAR);
|
||||
ret.replace('|', SUBSTITUTE_CHAR);
|
||||
ret.replace('?', SUBSTITUTE_CHAR);
|
||||
ret.replace('*', SUBSTITUTE_CHAR);
|
||||
#else // Q_OS_WIN32
|
||||
ret.replace('/', SUBSTITUTE_CHAR);
|
||||
#endif // Q_OS_WIN32
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QString quadKey(const QPoint &xy, int zoom)
|
||||
{
|
||||
QString qk;
|
||||
@ -198,7 +220,10 @@ QUrl TileLoader::tileUrl(const FetchTile &tile) const
|
||||
|
||||
QString TileLoader::tileFile(const FetchTile &tile) const
|
||||
{
|
||||
return _dir + QLatin1Char('/') + tile.zoom().toString() + QLatin1Char('-')
|
||||
QString zoom(((QMetaType::Type)(tile.zoom().type()) == QMetaType::Int)
|
||||
? tile.zoom().toString() : fsSafeStr(tile.zoom().toString()));
|
||||
|
||||
return _dir + QLatin1Char('/') + zoom + QLatin1Char('-')
|
||||
+ QString::number(tile.xy().x()) + QLatin1Char('-')
|
||||
+ QString::number(tile.xy().y());
|
||||
}
|
||||
|
@ -9,8 +9,9 @@
|
||||
#include "worldfilemap.h"
|
||||
|
||||
|
||||
WorldFileMap::WorldFileMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _mapRatio(1.0), _hasPRJ(false), _valid(false)
|
||||
WorldFileMap::WorldFileMap(const QString &fileName, const Projection &proj,
|
||||
QObject *parent) : Map(fileName, parent), _img(0), _mapRatio(1.0),
|
||||
_hasPRJ(false), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QDir dir(fi.absoluteDir());
|
||||
@ -37,7 +38,8 @@ WorldFileMap::WorldFileMap(const QString &fileName, QObject *parent)
|
||||
_errorString = prjFile + ": " + prj.errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
_projection = proj;
|
||||
|
||||
// Find the corresponding image file
|
||||
QList<QByteArray> formats(QImageReader::supportedImageFormats());
|
||||
@ -81,14 +83,6 @@ Coordinates WorldFileMap::xy2ll(const QPointF &p)
|
||||
return _projection.xy2ll(_transform.img2proj(p * _mapRatio));
|
||||
}
|
||||
|
||||
RectC WorldFileMap::llBounds(const Projection &proj)
|
||||
{
|
||||
if (_projection.isNull())
|
||||
_projection = proj;
|
||||
|
||||
return Map::llBounds(proj);
|
||||
}
|
||||
|
||||
QRectF WorldFileMap::bounds()
|
||||
{
|
||||
return QRectF(QPointF(0, 0), _size / _mapRatio);
|
||||
@ -122,10 +116,11 @@ void WorldFileMap::unload()
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
Map *WorldFileMap::create(const QString &path, bool *isDir)
|
||||
Map *WorldFileMap::create(const QString &path, const Projection &proj,
|
||||
bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new WorldFileMap(path);
|
||||
return new WorldFileMap(path, proj);
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ class WorldFileMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WorldFileMap(const QString &fileName, QObject *parent = 0);
|
||||
WorldFileMap(const QString &fileName, const Projection &proj,
|
||||
QObject *parent = 0);
|
||||
~WorldFileMap();
|
||||
|
||||
RectC llBounds(const Projection &proj);
|
||||
QRectF bounds();
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
@ -29,7 +29,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
|
||||
private:
|
||||
Projection _projection;
|
||||
|