1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-03-13 10:37:45 +01:00

Merge branch 'master' into android-latest

This commit is contained in:
Martin Tůma 2025-03-08 15:32:39 +01:00
commit 977fea9330
53 changed files with 5629 additions and 5140 deletions

View File

@ -1,4 +1,4 @@
version: 13.36.{build}
version: 13.37.{build}
configuration:
- Release

View File

@ -5,7 +5,7 @@ GPS log file formats.
## Features
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON,
OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV, TomTom OV2&ITN, ONmove OMD/GHP,
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG files.
TwoNav (TRK, RTE, WPT), GPSDump WPT, 70mai GPS logs and geotagged JPEG files.
* Opens geo URIs (RFC 5870).
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS,
QuadTiles).

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else {
TARGET = GPXSee
}
VERSION = 13.36
VERSION = 13.37
QT += core \
gui \
@ -117,6 +117,8 @@ HEADERS += src/common/config.h \
src/data/gpsdumpparser.h \
src/data/style.h \
src/data/twonavparser.h \
src/data/txtparser.h \
src/map/ENC/data.h \
src/map/IMG/light.h \
src/map/downloader.h \
src/map/demloader.h \
@ -343,6 +345,7 @@ SOURCES += src/main.cpp \
src/GUI/pngexportdialog.cpp \
src/GUI/projectioncombobox.cpp \
src/GUI/passwordedit.cpp \
src/data/txtparser.cpp \
src/map/downloader.cpp \
src/map/demloader.cpp \
src/map/ENC/atlasdata.cpp \

View File

@ -216,6 +216,7 @@
<file alias="tanker-anchorage.png">icons/map/marine/tanker-anchorage.png</file>
<file alias="nature-reserve-line.png">icons/map/marine/nature-reserve-line.png</file>
<file alias="sanctuary-line.png">icons/map/marine/sanctuary-line.png</file>
<file alias="fishing-farm.png">icons/map/marine/fishing-farm.png</file>
</qresource>
<!-- Patterns (Mapsforge) -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SIGMA SLF, Suunto SML, LOC,
OziExplorer (PLT, WPT, RTE), GeoJSON, SeeYou CUP,
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN, ONmove OMD/GHP,
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG
files.</li>
TwoNav (TRK, RTE, WPT), GPSDump WPT, 70mai GPS logs and
geotagged JPEG files.</li>
<li>Opens geo URIs (RFC 5870).</li>
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
WMS, TMS, QuadTiles).</li>
@ -113,6 +113,7 @@
<mimetype>application/vnd.iho.s57-catalogue</mimetype>
<mimetype>application/vnd.gpsdump.wpt</mimetype>
<mimetype>application/vnd.gpstuner.gmi</mimetype>
<mimetype>application/vnd.70mai.txt</mimetype>
<mimetype>x-scheme-handler/geo</mimetype>
</mimetypes>
</component>

View File

@ -16,4 +16,4 @@ Icon=gpxsee
Terminal=false
Type=Application
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt
MimeType=x-scheme-handler/geo;application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.cgtk.gemf;application/vnd.rmaps.sqlite;application/vnd.osmdroid.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn;application/vnd.esri.wld;application/vnd.onmove.omd;application/vnd.onmove.ghp;application/vnd.memory-map.qct;application/vnd.twonav.trk;application/vnd.twonav.rte;application/vnd.twonav.wpt;application/vnd.orux.map+xml;application/vnd.iho.s57-data;application/vnd.iho.s57-catalogue;application/vnd.gpsdump.wpt;application/vnd.gpstuner.gmi
MimeType=x-scheme-handler/geo;application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.cgtk.gemf;application/vnd.rmaps.sqlite;application/vnd.osmdroid.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn;application/vnd.esri.wld;application/vnd.onmove.omd;application/vnd.onmove.ghp;application/vnd.memory-map.qct;application/vnd.twonav.trk;application/vnd.twonav.rte;application/vnd.twonav.wpt;application/vnd.orux.map+xml;application/vnd.iho.s57-data;application/vnd.iho.s57-catalogue;application/vnd.gpsdump.wpt;application/vnd.gpstuner.gmi;application/vnd.70mai.txt

View File

@ -188,6 +188,16 @@
<glob pattern="*.wpt"/>
</mime-type>
<mime-type type="application/vnd.70mai.txt">
<comment>70mai GPS Log File</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text/plain"/>
<magic>
<match type="string" offset="0" value="$V02"/>
</magic>
<glob pattern="*.txt"/>
</mime-type>
<!-- Maps -->
<mime-type type="application/vnd.garmin.img">

View File

@ -736,6 +736,20 @@
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>txt</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.70mai.txt</string>
</array>
<key>CFBundleTypeName</key>
<string>70mai GPS Log File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleURLTypes</key>
@ -1718,6 +1732,27 @@
<string>application/vnd.iho.s57-catalogue</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.70mai.txt</string>
<key>UTTypeReferenceURL</key>
<string>https://forum.mapillary.com/t/using-the-70mai-a810-dashcam-for-mapillary/9130/7?u=boris</string>
<key>UTTypeDescription</key>
<string>70mai GPS Log File</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>txt</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.70mai.txt</string>
</dict>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>

View File

@ -49,7 +49,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "13.36"
!define VERSION "13.37"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -265,6 +265,7 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".gemf\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".000\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".031\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".txt\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -492,6 +493,7 @@ Section "Uninstall"
DeleteRegValue HKCR ".gemf\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".000\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".031\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".txt\OpenWithList" "GPXSee.exe"
DeleteRegKey HKCR "Applications\GPXSee.exe"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'

View File

@ -1193,11 +1193,13 @@ void GUI::loadData(const Data &data)
_time += track.time();
_movingTime += track.movingTime();
const QDateTime date = track.date().toTimeZone(_options.timeZone.zone());
if (date.isValid()) {
if (_dateRange.first.isNull() || _dateRange.first > date)
_dateRange.first = date;
if (_dateRange.second.isNull() || _dateRange.second < date)
_dateRange.second = date;
}
}
_trackCount += data.tracks().count();
for (int i = 0; i < data.routes().count(); i++)

View File

@ -7,15 +7,18 @@ RFC 4180 parser with the following enchancements:
- allows LF line ends in addition to CRLF line ends
*/
bool CSV::readEntry(QByteArrayList &list)
bool CSV::readEntry(QByteArrayList &list, int limit)
{
int state = 0;
int state = 0, len = 0;
char c;
QByteArray field;
list.clear();
while (_device->getChar(&c)) {
if (limit && ++len > limit)
return false;
switch (state) {
case 0:
if (c == '\r')

View File

@ -9,7 +9,7 @@ public:
CSV(QIODevice *device, char delimiter = ',')
: _device(device), _delimiter(delimiter), _line(1) {}
bool readEntry(QByteArrayList &list);
bool readEntry(QByteArrayList &list, int limit = 4096);
bool atEnd() const {return _device->atEnd();}
int line() const {return _line;}

View File

@ -53,7 +53,7 @@ public:
bool intersects(const RectC &r) const
{return (right() >= r.left() && bottom() <= r.top() && left() <= r.right()
&& top() >= r.bottom());}
bool contains(const Coordinates&c) const
bool contains(const Coordinates &c) const
{return (c.lon() >= left() && c.lon() <= right() && c.lat() <= top()
&& c.lat() >= bottom());}

View File

@ -115,7 +115,7 @@ public:
/// Count the data elements in this container. This is slow as no internal
/// counter is maintained.
int Count();
int Count() const;
/// Iterator is not remove safe.
@ -363,7 +363,7 @@ protected:
void* a_context) const;
void RemoveAllRec(Node* a_node);
void Reset();
void CountRec(Node* a_node, int& a_count);
void CountRec(Node* a_node, int& a_count) const;
/// Root of tree
Node* m_root;
@ -473,7 +473,7 @@ int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDI
RTREE_TEMPLATE
int RTREE_QUAL::Count()
int RTREE_QUAL::Count() const
{
int count = 0;
CountRec(m_root, count);
@ -483,7 +483,7 @@ int RTREE_QUAL::Count()
RTREE_TEMPLATE
void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
void RTREE_QUAL::CountRec(Node* a_node, int& a_count) const
{
if (a_node->IsInternalNode()) { // not a leaf node
for (int index = 0; index < a_node->m_count; ++index)

View File

@ -23,6 +23,7 @@
#include "onmoveparsers.h"
#include "twonavparser.h"
#include "gpsdumpparser.h"
#include "txtparser.h"
#include "data.h"
@ -49,6 +50,7 @@ static OMDParser omd;
static GHPParser ghp;
static TwoNavParser twonav;
static GPSDumpParser gpsdump;
static TXTParser txt;
static QMultiMap<QString, Parser*> parsers()
{
@ -82,6 +84,7 @@ static QMultiMap<QString, Parser*> parsers()
map.insert("rte", &twonav);
map.insert("wpt", &twonav);
map.insert("wpt", &gpsdump);
map.insert("txt", &txt);
return map;
}
@ -241,6 +244,7 @@ QString Data::formats()
+ qApp->translate("Data", "SLF files") + " (*.slf);;"
+ qApp->translate("Data", "SML files") + " (*.sml);;"
+ qApp->translate("Data", "TCX files") + " (*.tcx);;"
+ qApp->translate("Data", "70mai GPS log files") + " (*.txt);;"
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
+ qApp->translate("Data", "GPSDump files") + " (*.wpt);;"
+ qApp->translate("Data", "All files") + " (*)";

View File

@ -541,7 +541,7 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
Waypoint w;
QMap<QString, PolygonStyle> unused;
QMap<QString, LineStyle> unused2;
static QRegularExpression re("\\$\\[[^\\]]+\\]");
static const QRegularExpression re("\\$\\[[^\\]]+\\]");
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("name"))

80
src/data/txtparser.cpp Normal file
View File

@ -0,0 +1,80 @@
#include <QTimeZone>
#include "common/csv.h"
#include "txtparser.h"
static Coordinates coordinates(const QByteArrayList &entry)
{
bool lonOk, latOk;
double lon = entry.at(3).toDouble(&lonOk);
double lat = entry.at(2).toDouble(&latOk);
return (lonOk && latOk) ? Coordinates(lon, lat) : Coordinates();
}
bool TXTParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);
Q_UNUSED(waypoints);
CSV csv(file);
QByteArrayList entry;
SegmentData *sg = 0;
_errorLine = 1;
_errorString.clear();
while (!csv.atEnd()) {
if (!csv.readEntry(entry)) {
_errorString = "CSV parse error";
_errorLine = csv.line() - 1;
return false;
}
if (entry.size() == 1) {
if (entry.at(0) == "$V02") {
tracks.append(TrackData(SegmentData()));
sg = &tracks.last().last();
} else {
_errorString = "Invalid track start marker";
_errorLine = csv.line() - 1;
return false;
}
} else {
if (!sg) {
_errorString = "Missing start marker";
_errorLine = csv.line() - 1;
return false;
}
if (entry.size() == 13 && entry.at(1) == "A") {
Coordinates c(coordinates(entry));
if (!c.isValid()) {
_errorString = "Invalid coordinates";
_errorLine = csv.line() - 1;
return false;
}
Trackpoint tp(c);
bool ok;
qulonglong ts = entry.at(0).toULongLong(&ok);
if (!ok) {
_errorString = "Invalid timestamp";
_errorLine = csv.line() - 1;
return false;
}
tp.setTimestamp(QDateTime::fromSecsSinceEpoch(ts,
QTimeZone::utc()));
uint speed = entry.at(5).toULong(&ok);
if (ok)
tp.setSpeed(speed * 0.01);
if (c != Coordinates(0, 0))
sg->append(tp);
}
}
}
return true;
}

18
src/data/txtparser.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef TXTPARSER_H
#define TXTPARSER_H
#include "parser.h"
class TXTParser : public Parser
{
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}
private:
QString _errorString;
int _errorLine;
};
#endif // TXTPARSER_H

View File

@ -39,15 +39,12 @@ bool AtlasData::polyCb(MapEntry *map, void *context)
ctx->cacheLock.unlock();
MapData *data = new MapData(map->path);
data->polygons(ctx->rect, ctx->polygons);
data->lines(ctx->rect, ctx->lines);
data->polys(ctx->rect, ctx->polygons, ctx->lines);
ctx->cacheLock.lock();
ctx->cache.insert(map->path, data);
} else {
cached->polygons(ctx->rect, ctx->polygons);
cached->lines(ctx->rect, ctx->lines);
}
} else
cached->polys(ctx->rect, ctx->polygons, ctx->lines);
ctx->cacheLock.unlock();
map->lock.unlock();

View File

@ -10,18 +10,18 @@ namespace ENC {
typedef QCache<QString, MapData> MapCache;
class AtlasData
class AtlasData : public Data
{
public:
AtlasData(MapCache &cache, QMutex &cacheLock)
: _cache(cache), _cacheLock(cacheLock) {}
~AtlasData();
virtual ~AtlasData();
void addMap(const RectC &bounds, const QString &path);
void polys(const RectC &rect, QList<MapData::Poly> *polygons,
virtual void polys(const RectC &rect, QList<MapData::Poly> *polygons,
QList<MapData::Line> *lines);
void points(const RectC &rect, QList<MapData::Point> *points);
virtual void points(const RectC &rect, QList<MapData::Point> *points);
private:
struct MapEntry {

View File

@ -3,6 +3,7 @@
#define CATACH 8
#define CATBUA 10
#define CATCOV 18
#define CATDIS 21
#define CATHAF 30
#define CATLMK 35

79
src/map/ENC/data.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef ENC_DATA_H
#define ENC_DATA_H
#include "common/rectc.h"
#include "common/polygon.h"
namespace ENC {
class Data
{
public:
typedef QMap<uint, QByteArray> Attributes;
class Poly {
public:
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
const Attributes &attributes() const {return _attr;}
uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
Attributes _attr;
uint _HUNI;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
private:
uint _type;
QVector<Coordinates> _path;
QString _label;
Attributes _attr;
};
class Point {
public:
Point(uint type, const Coordinates &c, const Attributes &attr,
uint HUNI, bool polygon = false);
Point(uint type, const Coordinates &s, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
bool polygon() const {return _polygon;}
bool operator<(const Point &other) const
{return _id < other._id;}
private:
uint _type;
Coordinates _pos;
QString _label;
quint64 _id;
Attributes _attr;
bool _polygon;
};
virtual void polys(const RectC &rect, QList<Data::Poly> *polygons,
QList<Data::Line> *lines) = 0;
virtual void points(const RectC &rect, QList<Data::Point> *points) = 0;
};
}
#endif // ENC_DATA_H

View File

@ -141,13 +141,12 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
{
static QRegularExpression re("(\\d*)(\\w+)\\(*(\\d*)\\)*");
QByteArray ba;
static const QRegularExpression re("(\\d*)(\\w+)\\(*(\\d*)\\)*");
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
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()))
return false;
@ -236,9 +235,8 @@ bool ISO8211::readDDR()
bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
const QVector<SubFieldDefinition> &fields, bool repeat, Data &data)
{
QByteArray ba;
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
ba.resize(def.size);
if (!(_file.seek(pos + def.pos)
&& _file.read(ba.data(), ba.size()) == ba.size()))
return false;
@ -248,8 +246,7 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
const char *ep = ba.constData() + ba.size() - 1;
do {
QVector<QVariant> row;
row.resize(fields.size());
QVector<QVariant> row(fields.size());
for (int i = 0; i < fields.size(); i++) {
const SubFieldDefinition &f = fields.at(i);

View File

@ -362,6 +362,8 @@ MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr,
subtype = CATACH;
else if (type == I_ACHARE)
subtype = I_CATACH;
else if (type == MARKUL)
subtype = CATMFA;
QList<QByteArray> list(_attr.value(subtype).split(','));
std::sort(list.begin(), list.end());
@ -423,6 +425,8 @@ MapData::Poly::Poly(uint type, const Polygon &path, const Attributes &attr,
subtype = CATMFA;
else if (type == I_BERTHS)
subtype = I_CATBRT;
else if (type == M_COVR)
subtype = CATCOV;
switch (type) {
case DEPARE:
@ -864,7 +868,7 @@ MapData::~MapData()
delete _points.GetAt(pit);
}
void MapData::points(const RectC &rect, QList<Point> *points) const
void MapData::points(const RectC &rect, QList<Point> *points)
{
double min[2], max[2];
@ -874,18 +878,12 @@ void MapData::points(const RectC &rect, QList<Point> *points) const
_lines.Search(min, max, linePointCb, points);
}
void MapData::lines(const RectC &rect, QList<Line> *lines) const
void MapData::polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines)
{
double min[2], max[2];
rectcBounds(rect, min, max);
_lines.Search(min, max, lineCb, lines);
}
void MapData::polygons(const RectC &rect, QList<Poly> *polygons) const
{
double min[2], max[2];
rectcBounds(rect, min, max);
_areas.Search(min, max, polygonCb, polygons);
}

View File

@ -1,82 +1,21 @@
#ifndef ENC_MAPDATA_H
#define ENC_MAPDATA_H
#include "common/rectc.h"
#include "common/rtree.h"
#include "common/polygon.h"
#include "iso8211.h"
#include "data.h"
namespace ENC {
class MapData
class MapData : public Data
{
public:
typedef QMap<uint, QByteArray> Attributes;
class Poly {
public:
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
const Attributes &attributes() const {return _attr;}
uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
Attributes _attr;
uint _HUNI;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
private:
uint _type;
QVector<Coordinates> _path;
QString _label;
Attributes _attr;
};
class Point {
public:
Point(uint type, const Coordinates &c, const Attributes &attr,
uint HUNI, bool polygon = false);
Point(uint type, const Coordinates &s, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
bool polygon() const {return _polygon;}
bool operator<(const Point &other) const
{return _id < other._id;}
private:
uint _type;
Coordinates _pos;
QString _label;
quint64 _id;
Attributes _attr;
bool _polygon;
};
MapData(const QString &path);
~MapData();
virtual ~MapData();
void polygons(const RectC &rect, QList<Poly> *polygons) const;
void lines(const RectC &rect, QList<Line> *lines) const;
void points(const RectC &rect, QList<Point> *points) const;
virtual void polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines);
virtual void points(const RectC &rect, QList<Point> *points);
private:
struct Sounding {

View File

@ -28,14 +28,14 @@ static double angle(uint type, const QVariant &param)
? 90 + param.toDouble() : NAN;
}
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
bool RasterTile::showLabel(const QImage *img, int type) const
{
if (type>>16 == I_DISMAR)
return true;
int limit = (!range.size())
? range.min() : range.min() + (range.size() + 1) / 2;
if ((img || (type>>16 == SOUNDG)) && (zoom < limit))
int limit = (!_zoomRange.size())
? _zoomRange.min() : _zoomRange.min() + (_zoomRange.size() + 1) / 2;
if ((img || (type>>16 == SOUNDG)) && (_zoom < limit))
return false;
return true;
@ -139,10 +139,10 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type)
}
void RasterTile::drawArrows(QPainter *painter,
const QList<MapData::Point> &points) const
const QList<Data::Point> &points) const
{
for (int i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
@ -153,11 +153,11 @@ void RasterTile::drawArrows(QPainter *painter,
}
void RasterTile::drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons) const
const QList<Data::Poly> &polygons) const
{
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
const MapData::Poly &poly = polygons.at(i);
const Data::Poly &poly = polygons.at(i);
if (poly.type() != _style->drawOrder().at(n))
continue;
const Style::Polygon &style = _style->polygon(poly.type());
@ -169,8 +169,13 @@ void RasterTile::drawPolygons(QPainter *painter,
} else {
if (style.brush() != Qt::NoBrush) {
painter->setPen(Qt::NoPen);
QPainterPath path(painterPath(poly.path()));
if (poly.type() == TYPE(DRGARE)) {
painter->setBrush(Qt::white);
painter->drawPath(path);
}
painter->setBrush(style.brush());
painter->drawPath(painterPath(poly.path()));
painter->drawPath(path);
}
if (style.pen() != Qt::NoPen) {
painter->setPen(style.pen());
@ -185,12 +190,12 @@ void RasterTile::drawPolygons(QPainter *painter,
}
}
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines) const
void RasterTile::drawLines(QPainter *painter, const QList<Data::Line> &lines) const
{
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Data::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (!style.img().isNull()) {
@ -221,11 +226,11 @@ static QRectF lightRect(const QPointF &pos, double range)
}
void RasterTile::drawSectorLights(QPainter *painter,
const QList<SectorLight> &lights) const
const QMultiMap<Coordinates, SectorLight> &lights) const
{
for (int i = 0; i < lights.size(); i++) {
const SectorLight &l = lights.at(i);
QPointF pos(ll2xy(l.pos));
for (auto it = lights.cbegin(); it != lights.cend(); ++it) {
const SectorLight &l = it.value();
QPointF pos(ll2xy(it.key()));
QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range));
double a1 = -(l.end + 90);
double a2 = -(l.start + 90);
@ -257,49 +262,45 @@ void RasterTile::drawSectorLights(QPainter *painter,
}
}
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<SectorLight> &sectorLights)
void RasterTile::processPoints(const QList<Data::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
QMultiMap<Coordinates, SectorLight> &sectorLights, bool overZoom) const
{
LightMap lightsMap;
SignalSet signalsSet;
QSet<Coordinates> slMap;
QMap<Coordinates, Style::Color> lights;
QSet<Coordinates> sigs;
int i;
std::sort(points.begin(), points.end());
/* Lights & Signals */
for (i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
if (point.type()>>16 == LIGHTS) {
const MapData::Attributes &attr = point.attributes();
const Data::Attributes &attr = point.attributes();
Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
double range = attr.value(VALNMR).toDouble();
if (attr.contains(SECTR1)
|| (range >= MAJOR_RANGE && !(point.type() & 0xFFFF))) {
sectorLights.append(SectorLight(point.pos(), color,
sectorLights.insert(point.pos(), SectorLight(color,
attr.value(LITVIS).toUInt(), range,
attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble()));
slMap.insert(point.pos());
} else
lightsMap.insert(point.pos(), color);
lights.insert(point.pos(), color);
} else if (point.type()>>16 == FOGSIG)
signalsSet.insert(point.pos());
sigs.insert(point.pos());
else
break;
}
/* Everything else */
for ( ; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
QPoint pos(ll2xy(point.pos()).toPoint());
const Style::Point &style = _style->point(point.type());
const QString *label = point.label().isEmpty() ? 0 : &(point.label());
const QImage *img = style.img().isNull() ? 0 : &style.img();
const QFont *fnt = showLabel(img, _zoomRange, _zoom, point.type())
const QFont *fnt = (overZoom || showLabel(img, point.type()))
? _style->font(style.textFontSize()) : 0;
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
@ -313,25 +314,25 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
color, hColor, 0, 2, rotate);
if (item->isValid() && (slMap.contains(point.pos())
if (item->isValid() && (sectorLights.contains(point.pos())
|| (point.polygon() && img) || !item->collides(textItems))) {
textItems.append(item);
if (lightsMap.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->lightOffset(),
0, 0, _style->light(lightsMap.value(point.pos())), 0, 0, 0, 0));
if (signalsSet.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->signalOffset(),
if (lights.contains(point.pos()))
lightItems.append(new TextPointItem(pos + _style->lightOffset(),
0, 0, _style->light(lights.value(point.pos())), 0, 0, 0, 0));
if (sigs.contains(point.pos()))
lightItems.append(new TextPointItem(pos + _style->signalOffset(),
0, 0, _style->signal(), 0, 0, 0, 0));
} else
delete item;
}
}
void RasterTile::processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems)
void RasterTile::processLines(const QList<Data::Line> &lines,
QList<TextItem*> &textItems) const
{
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Data::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (style.img().isNull() && style.pen() == Qt::NoPen)
@ -351,11 +352,46 @@ void RasterTile::processLines(const QList<MapData::Line> &lines,
}
}
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
QList<MapData::Line> &lines, QList<MapData::Point> &points)
void RasterTile::drawLevels(QPainter *painter, const QList<Level> &levels)
{
QPoint ttl(_rect.topLeft());
for (int i = levels.size() - 1; i >= 0; i--) {
QList<TextItem*> textItems, lightItems;
QMultiMap<Coordinates, SectorLight> sectorLights;
const Level &l = levels.at(i);
processPoints(l.points, textItems, lightItems, sectorLights, l.overZoom);
processLines(l.lines, textItems);
drawPolygons(painter, l.polygons);
drawLines(painter, l.lines);
drawArrows(painter, l.points);
drawTextItems(painter, lightItems);
drawSectorLights(painter, sectorLights);
drawTextItems(painter, textItems);
qDeleteAll(textItems);
qDeleteAll(lightItems);
}
}
QPainterPath RasterTile::shape(const QList<Data::Poly> &polygons) const
{
QPainterPath shp;
for (int i = 0; i < polygons.size(); i++) {
const Data::Poly &p = polygons.at(i);
if (p.type() == SUBTYPE(M_COVR, 1))
shp.addPath(painterPath(p.path()));
}
return shp;
}
QList<RasterTile::Level> RasterTile::fetchLevels()
{
QList<RasterTile::Level> list;
QPoint ttl(_rect.topLeft());
QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y()
+ _rect.height()));
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
@ -368,50 +404,41 @@ void RasterTile::fetchData(QList<MapData::Poly> &polygons,
_transform.img2proj(pointRect.bottomRight()));
RectC pointRectC(pointRectD.toRectC(_proj, 20));
if (_map) {
_map->lines(polyRectC, &lines);
_map->polygons(polyRectC, &polygons);
_map->points(pointRectC, &points);
} else {
_atlas->polys(polyRectC, &polygons, &lines);
_atlas->points(pointRectC, &points);
for (int i = 0; i < _data.size(); i++) {
Level level;
_data.at(i)->polys(polyRectC, &level.polygons, &level.lines);
_data.at(i)->points(pointRectC, &level.points);
level.overZoom = i > 0;
std::sort(level.points.begin(), level.points.end());
if (!level.isNull())
list.append(level);
if (_data.size() > 1 && shape(level.polygons).contains(_rect))
break;
}
return list;
}
void RasterTile::render()
{
QList<Level> levels(fetchLevels());
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
QImage::Format_ARGB32_Premultiplied);
QList<MapData::Line> lines;
QList<MapData::Poly> polygons;
QList<MapData::Point> points;
QList<TextItem*> textItems, lights;
QList<SectorLight> sectorLights;
img.setDevicePixelRatio(_ratio);
img.fill(Qt::transparent);
fetchData(polygons, lines, points);
processPoints(points, textItems, lights, sectorLights);
processLines(lines, textItems);
QPainter painter(&img);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(-_rect.x(), -_rect.y());
drawPolygons(&painter, polygons);
drawLines(&painter, lines);
drawArrows(&painter, points);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
qDeleteAll(lights);
drawLevels(&painter, levels);
//painter.setPen(Qt::red);
//painter.setBrush(Qt::NoBrush);

View File

@ -5,7 +5,7 @@
#include "common/range.h"
#include "map/projection.h"
#include "map/transform.h"
#include "mapdata.h"
#include "data.h"
#include "style.h"
#include "atlasdata.h"
@ -17,14 +17,17 @@ class RasterTile
{
public:
RasterTile(const Projection &proj, const Transform &transform,
const Style *style, const MapData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _map(data), _atlas(0),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
const Style *style, Data *data, int zoom,
const Range &zoomRange, const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio)
{
_data.append(data);
}
RasterTile(const Projection &proj, const Transform &transform,
const Style *style, AtlasData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _map(0), _atlas(data),
const Style *style, const QList<Data*> &data, int zoom,
const Range &zoomRange, const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _data(data),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
int zoom() const {return _zoom;}
@ -36,11 +39,10 @@ public:
private:
struct SectorLight
{
SectorLight(const Coordinates &pos, Style::Color color, uint visibility,
double range, double start, double end) : pos(pos), color(color),
visibility(visibility), range(range), start(start), end(end) {}
SectorLight(Style::Color color, uint visibility, double range,
double start, double end) : color(color), visibility(visibility),
range(range), start(start), end(end) {}
Coordinates pos;
Style::Color color;
uint visibility;
double range;
@ -48,11 +50,16 @@ private:
double end;
};
typedef QMap<Coordinates, Style::Color> LightMap;
typedef QSet<Coordinates> SignalSet;
struct Level {
QList<Data::Line> lines;
QList<Data::Poly> polygons;
QList<Data::Point> points;
bool overZoom;
bool isNull() const
{return lines.isEmpty() && polygons.isEmpty() && points.isEmpty();}
};
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines,
QList<MapData::Point> &points);
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
QPainterPath painterPath(const Polygon &polygon) const;
@ -60,25 +67,26 @@ private:
QVector<QPolygonF> polylineM(const QVector<Coordinates> &path) const;
QPolygonF tsslptArrow(const QPointF &p, qreal angle) const;
QPointF centroid(const QVector<Coordinates> &polygon) const;
void processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem *> &lights,
QList<SectorLight> &sectorLights);
void processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems);
void drawArrows(QPainter *painter, const QList<MapData::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<MapData::Line> &lines) const;
void processPoints(const QList<Data::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
QMultiMap<Coordinates, SectorLight> &sectorLights, bool overZoom) const;
void processLines(const QList<Data::Line> &lines,
QList<TextItem*> &textItems) const;
void drawArrows(QPainter *painter, const QList<Data::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<Data::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<Data::Line> &lines) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights) const;
static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context);
void drawSectorLights(QPainter *painter,
const QMultiMap<Coordinates, SectorLight> &lights) const;
bool showLabel(const QImage *img, int type) const;
void drawLevels(QPainter *painter, const QList<Level> &levels);
QList<Level> fetchLevels();
QPainterPath shape(const QList<Data::Poly> &polygons) const;
Projection _proj;
Transform _transform;
const Style *_style;
const MapData *_map;
AtlasData *_atlas;
QList<Data *> _data;
int _zoom;
Range _zoomRange;
QRect _rect;

View File

@ -27,7 +27,6 @@ static QFont pixelSizeFont(int pixelSize)
void Style::polygonStyle()
{
_polygons[TYPE(M_COVR)] = Polygon(QBrush(QColor(0xff, 0xff, 0xff)));
_polygons[TYPE(LNDARE)] = Polygon(QBrush(QColor(0xe8, 0xe0, 0x64)));
_polygons[TYPE(BUAARE)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)));
_polygons[TYPE(BUISGL)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)),
@ -141,6 +140,7 @@ void Style::polygonStyle()
1.5, Qt::DashLine));
_polygons[TYPE(CBLARE)] = Polygon(QImage(":/marine/cable-area-line.png"));
_polygons[TYPE(PIPARE)] = Polygon(QImage(":/marine/pipeline-area-line.png"));
_polygons[SUBTYPE(MARKUL, 0)] = Polygon(QImage(":/marine/fishing-farm-line.png"));
_polygons[SUBTYPE(MARKUL, 3)] = Polygon(QImage(":/marine/fishing-farm-line.png"));
_polygons[TYPE(BERTHS)] = Polygon(Qt::NoBrush, QPen(QColor(0xeb, 0x49, 0xeb),
1, Qt::DashLine));
@ -152,19 +152,19 @@ void Style::polygonStyle()
1, Qt::DashDotLine));
_drawOrder
<< TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0)
<< SUBTYPE(DEPARE, 1) << SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3)
<< TYPE(UNSARE) << SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5)
<< SUBTYPE(DEPARE, 6) << TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON)
<< TYPE(RIVERS) << TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN)
<< TYPE(I_LOKBSN) << TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK)
<< TYPE(AIRARE) << TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL)
<< TYPE(I_TERMNL) << TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON)
<< TYPE(I_PONTON) << TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC)
<< TYPE(I_FLODOC) << TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS)
<< TYPE(MORFAC) << TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS)
<< TYPE(I_BERTHS) << SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE)
<< TYPE(OBSTRN) << TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
<< TYPE(LNDARE) << SUBTYPE(DEPARE, 0) << SUBTYPE(DEPARE, 1)
<< SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3) << TYPE(UNSARE)
<< SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5) << SUBTYPE(DEPARE, 6)
<< TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON) << TYPE(RIVERS)
<< TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN) << TYPE(I_LOKBSN)
<< TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK) << TYPE(AIRARE)
<< TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL) << TYPE(I_TERMNL)
<< TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON) << TYPE(I_PONTON)
<< TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC) << TYPE(I_FLODOC)
<< TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS) << TYPE(MORFAC)
<< TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS) << TYPE(I_BERTHS)
<< SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN)
<< TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
<< SUBTYPE(ACHARE, 2) << SUBTYPE(ACHARE, 3) << SUBTYPE(ACHARE, 4)
<< SUBTYPE(ACHARE, 5) << SUBTYPE(ACHARE, 6) << SUBTYPE(ACHARE, 7)
<< SUBTYPE(ACHARE, 8) << SUBTYPE(ACHARE, 9) << SUBTYPE(I_ACHARE, 1)
@ -180,7 +180,8 @@ void Style::polygonStyle()
<< SUBTYPE(RESARE, 17) << SUBTYPE(I_RESARE, 17) << SUBTYPE(RESARE, 22)
<< SUBTYPE(I_RESARE, 22) << SUBTYPE(RESARE, 23) << SUBTYPE(I_RESARE, 23)
<< SUBTYPE(RESARE, 1) << TYPE(CBLARE) << TYPE(PIPARE) << TYPE(PRCARE)
<< TYPE(I_TRNBSN) << SUBTYPE(MARKUL, 3) << TYPE(CONZNE);
<< TYPE(I_TRNBSN) << SUBTYPE(MARKUL, 0) << SUBTYPE(MARKUL, 3)
<< TYPE(CONZNE);
}
void Style::lineStyle(qreal ratio)
@ -393,6 +394,8 @@ void Style::pointStyle(qreal ratio)
_points[TYPE(LNDARE)].setHaloColor(QColor());
_points[TYPE(LNDRGN)].setHaloColor(QColor());
_points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png"));
_points[SUBTYPE(MARKUL, 0)] = Point(QImage(":/marine/fishing-farm.png"));
_points[SUBTYPE(MARKUL, 3)] = Point(QImage(":/marine/fishing-farm.png"));
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"),
Small);
@ -482,6 +485,7 @@ Style::Style(qreal ratio)
_lightRed = QImage(":/marine/light-red.png");
_lightGreen = QImage(":/marine/light-green.png");
_lightYellow = QImage(":/marine/light-yellow.png");
_lightWhite = QImage(":/marine/light-white.png");
_lightOffset = QPoint(11, 11);
_signal = QImage(":/marine/fog-signal.png");
_signalOffset = QPoint(-9, 9);
@ -541,6 +545,7 @@ const QImage *Style::light(Color color) const
case Green:
return &_lightGreen;
case White:
return &_lightWhite;
case Yellow:
case Amber:
case Orange:
@ -558,6 +563,7 @@ QColor Style::color(Style::Color c)
case Green:
return Qt::green;
case White:
return Qt::white;
case Yellow:
case Amber:
case Orange:

View File

@ -121,7 +121,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */
QFont _small, _normal, _large;
QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
QImage _light, _lightRed, _lightGreen, _lightYellow, _lightWhite, _signal;
QPoint _lightOffset, _signalOffset;
};

View File

@ -151,8 +151,7 @@ bool Downloader::doDownload(const Download &dl, const QList<HTTPHeader> &headers
for (int i = 0; i < headers.size(); i++) {
const HTTPHeader &hdr = headers.at(i);
request.setRawHeader(hdr.key(), hdr.value());
// QByteArray::compare() not available in Qt < 5.12
if (!QString(hdr.key()).compare("User-Agent", Qt::CaseInsensitive))
if (!hdr.key().compare("User-Agent", Qt::CaseInsensitive))
userAgent = true;
}
if (!userAgent)

View File

@ -154,7 +154,7 @@ ENCAtlas::ENCAtlas(const QString &fileName, QObject *parent)
_zoom = zooms(_usage).min();
updateTransform();
_cache.setMaxCost(10);
_cache.setMaxCost(16);
_valid = true;
}
@ -345,9 +345,21 @@ QString ENCAtlas::key(int zoom, const QPoint &xy) const
+ QString::number(xy.x()) + "_" + QString::number(xy.y());
}
QList<Data*> ENCAtlas::levels() const
{
QList<Data*> list;
QMap<IntendedUsage, ENC::AtlasData*>::const_iterator it = _data.find(_usage);
do {
list.append(it.value());
} while (it-- != _data.cbegin());
return list;
}
void ENCAtlas::draw(QPainter *painter, const QRectF &rect, Flags flags)
{
AtlasData *data = _data.value(_usage);
QList<Data*> data(levels());
Range zr(zooms(_usage));
QPointF tl(floor(rect.left() / TILE_SIZE) * TILE_SIZE,
floor(rect.top() / TILE_SIZE) * TILE_SIZE);

View File

@ -74,6 +74,7 @@ private:
void cancelJobs(bool wait);
QString key(int zoom, const QPoint &xy) const;
void addMap(const QDir &dir, const QByteArray &file, const RectC &bounds);
QList<ENC::Data*> levels() const;
static bool processRecord(const ENC::ISO8211::Record &record,
QByteArray &file, RectC &bounds);