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:
commit
977fea9330
@ -1,4 +1,4 @@
|
||||
version: 13.36.{build}
|
||||
version: 13.37.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
@ -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).
|
||||
|
@ -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 \
|
||||
|
@ -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) -->
|
||||
|
BIN
icons/map/marine/fishing-farm.png
Normal file
BIN
icons/map/marine/fishing-farm.png
Normal file
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
@ -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 & CSV, TomTom OV2 & 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>
|
||||
|
@ -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
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
@ -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)'
|
||||
|
@ -1193,10 +1193,12 @@ void GUI::loadData(const Data &data)
|
||||
_time += track.time();
|
||||
_movingTime += track.movingTime();
|
||||
const QDateTime date = track.date().toTimeZone(_options.timeZone.zone());
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
_dateRange.second = date;
|
||||
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();
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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;}
|
||||
|
||||
|
@ -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());}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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") + " (*)";
|
||||
|
@ -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
80
src/data/txtparser.cpp
Normal 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
18
src/data/txtparser.h
Normal 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
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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
79
src/map/ENC/data.h
Normal 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
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -28,14 +28,14 @@ static double angle(uint type, const QVariant ¶m)
|
||||
? 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> §orLights)
|
||||
void RasterTile::processPoints(const QList<Data::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
|
||||
QMultiMap<Coordinates, SectorLight> §orLights, 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);
|
||||
|
@ -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> §orLights);
|
||||
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> §orLights, 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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -338,7 +338,7 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
||||
painter->drawPixmap(ttl, pm);
|
||||
else
|
||||
tiles.append(RasterTile(_projection, _transform, _style, _data,
|
||||
tiles.append(RasterTile(_projection, _transform, _style, _data,
|
||||
_zoom, _zooms, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)),
|
||||
_tileRatio));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user