1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-04-20 04:09:11 +02:00

Compare commits

..

No commits in common. "master" and "13.36" have entirely different histories.

75 changed files with 5439 additions and 6703 deletions

View File

@ -1,4 +1,4 @@
version: 13.39.{build}
version: 13.36.{build}
configuration:
- Release
@ -8,7 +8,6 @@ image:
environment:
NSISDIR: C:\Program Files (x86)\NSIS
JOMDIR: C:\Qt\Tools\QtCreator\bin\jom
matrix:
- QTDIR: C:\Qt\5.15\msvc2019_64
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
@ -18,14 +17,14 @@ environment:
install:
- cmd: |-
set PATH=%QTDIR%\bin;%NSISDIR%;%JOMDIR%;%PATH%
set PATH=%QTDIR%\bin;%NSISDIR%;%PATH%
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
build_script:
- cmd: |-
lrelease gpxsee.pro
qmake gpxsee.pro
jom release
nmake release
md installer
copy release\GPXSee.exe installer

View File

@ -43,7 +43,7 @@ jobs:
- name: Configure build
run: qmake gpxsee.pro OPENSSL_PATH=android_openssl
- name: Build project
run: make -j4 apk
run: make -j2 apk
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:

View File

@ -24,4 +24,4 @@ jobs:
- name: Configure build
run: qmake CONFIG+=${{ matrix.config }} gpxsee.pro
- name: Build project
run: make -j4
run: make -j2

View File

@ -5,8 +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, Velocitek VTK, Vakaros VKX, 70mai GPS logs
and geotagged JPEG files.
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG files.
* Opens geo URIs (RFC 5870).
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS,
QuadTiles).

View File

@ -214,11 +214,10 @@
</rule>
<!-- Buildings -->
<rule e="way" k="building" v="-|civic|office|cathedral|church|basilica">
<rule e="way" k="building" v="*">
<area fill="#dbd0b6" stroke="#cdccc4" stroke-width="0.1"/>
</rule>
<rule e="way" k="building" v="civic|office">
<rule e="way" k="building" v="civic">
<area fill="#cfc4b3" stroke="#cdccc4" stroke-width="0.1"/>
<rule e="way" k="*" v="*" zoom-min="16">
<caption fill="#000000" font-size="10" font-style="italic" k="name" stroke="#FFFFFF" stroke-width="2" priority="-10"/>
@ -404,7 +403,7 @@
<rule e="way" k="*" v="*" zoom-min="14">
<pathText fill="#000000" font-size="10" k="name" priority="-5" stroke="#FFFFFF" stroke-width="2"/>
<rule e="way" k="oneway" v="yes|true|1" zoom-min="16">
<lineSymbol priority="-50" src=":/symbols/oneway.svg" symbol-width="16" symbol-height="8"/>
<lineSymbol priority="-50" src=":/symbols/arrow.svg" symbol-width="16" symbol-height="8"/>
</rule>
</rule>
</rule>
@ -429,12 +428,6 @@
<line stroke="#f7d9a6" stroke-width="1" stroke-linecap="butt"/>
</rule>
</rule>
<rule e="way" k="*" v="*" zoom-min="14">
<pathText fill="#000000" font-size="10" k="name" priority="-3" stroke="#FFFFFF" stroke-width="2"/>
<rule e="way" k="oneway" v="yes|true|1" zoom-min="16">
<lineSymbol priority="-50" src=":/symbols/oneway.svg" symbol-width="16" symbol-height="8"/>
</rule>
</rule>
</rule>
<rule e="way" k="highway" v="motorway|motorway_link">
<rule e="way" k="tunnel" v="~|false|no">

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else {
TARGET = GPXSee
}
VERSION = 13.39
VERSION = 13.36
QT += core \
gui \
@ -117,10 +117,6 @@ HEADERS += src/common/config.h \
src/data/gpsdumpparser.h \
src/data/style.h \
src/data/twonavparser.h \
src/data/txtparser.h \
src/data/vkxparser.h \
src/data/vtkparser.h \
src/map/ENC/data.h \
src/map/IMG/light.h \
src/map/downloader.h \
src/map/demloader.h \
@ -347,9 +343,6 @@ SOURCES += src/main.cpp \
src/GUI/pngexportdialog.cpp \
src/GUI/projectioncombobox.cpp \
src/GUI/passwordedit.cpp \
src/data/txtparser.cpp \
src/data/vkxparser.cpp \
src/data/vtkparser.cpp \
src/map/downloader.cpp \
src/map/demloader.cpp \
src/map/ENC/atlasdata.cpp \
@ -565,9 +558,7 @@ win32 {
icons/formats/trk.ico \
icons/formats/gemf.ico \
icons/formats/000.ico \
icons/formats/031.ico \
icons/formats/vtk.ico \
icons/formats/vkx.ico
icons/formats/031.ico
DEFINES += _USE_MATH_DEFINES \
NOGDI
}

View File

@ -216,7 +216,6 @@
<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) -->

View File

@ -32,5 +32,3 @@ trk:#cccccc
gemf:#147085
000:#000000
031:#000000
vtk:#632433
vkx:#00ccff

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

Before

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, Velocitek VTK,
Vakaros VKX, 70mai GPS logs and geotagged JPEG files.</li>
TwoNav (TRK, RTE, WPT), GPSDump WPT 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,9 +113,6 @@
<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>application/vnd.velocitek.vtk</mimetype>
<mimetype>application/vnd.vakaros.vkx</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;application/vnd.70mai.txt;application/vnd.velocitek.vtk;application/vnd.vakaros.vkx
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

View File

@ -188,33 +188,6 @@
<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>
<mime-type type="application/vnd.velocitek.vtk">
<comment>Velocitek VTK File</comment>
<sub-class-of type="application/octet-stream"/>
<generic-icon name="application/octet-stream"/>
<glob pattern="*.vtk"/>
</mime-type>
<mime-type type="application/vnd.vakaros.vkx">
<comment>Vakaros VKX File</comment>
<sub-class-of type="application/octet-stream"/>
<generic-icon name="application/octet-stream"/>
<magic>
<match type="byte" offset="0" value="0xFF"/>
</magic>
<glob pattern="*.vkx"/>
</mime-type>
<!-- Maps -->
<mime-type type="application/vnd.garmin.img">

View File

@ -736,52 +736,6 @@
<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>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vtk</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.velocitek.vtk</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/vtk.icns</string>
<key>CFBundleTypeName</key>
<string>Velocitek VTK File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vkx</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.vakaros.vkx</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/vkx.icns</string>
<key>CFBundleTypeName</key>
<string>Vakaros VKX File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleURLTypes</key>
@ -1729,8 +1683,6 @@
<string>https://iho.int/uploads/user/pubs/standards/s-57/31Main.pdf</string>
<key>UTTypeDescription</key>
<string>IHO S-57 Electronic Navigation Chart</string>
<key>UTTypeIconFile</key>
<string>icons/000.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
@ -1752,8 +1704,6 @@
<string>https://iho.int/uploads/user/pubs/standards/s-57/20ApB1.pdf</string>
<key>UTTypeDescription</key>
<string>IHO S-57 Electronic Navigation Catalogue</string>
<key>UTTypeIconFile</key>
<string>icons/031.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
@ -1768,73 +1718,6 @@
<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>
<dict>
<key>UTTypeIdentifier</key>
<string>com.velocitek.vtk</string>
<key>UTTypeReferenceURL</key>
<string>https://github.com/velocitek/vtk_protocol</string>
<key>UTTypeDescription</key>
<string>Velocitek VTK File</string>
<key>UTTypeIconFile</key>
<string>icons/vtk.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>vtk</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.velocitek.vtk</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.vakaros.vkx</string>
<key>UTTypeReferenceURL</key>
<string>https://github.com/vakaros/vkx</string>
<key>UTTypeDescription</key>
<string>Vakaros VKX File</string>
<key>UTTypeIconFile</key>
<string>icons/vkx.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>vkx</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.vakaros.vkx</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.39"
!define VERSION "13.36"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -204,15 +204,13 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "gemf" "GEMF Map File" 26
!insertmacro FILE_ASSOCIATION_ADD "000" "IHO S-57 Electronic Navigation Chart" 27
!insertmacro FILE_ASSOCIATION_ADD "031" "IHO S-57 Electronic Navigation Catalogue" 28
!insertmacro FILE_ASSOCIATION_ADD "vtk" "Velocitek VTK File" 29
!insertmacro FILE_ASSOCIATION_ADD "vkx" "Vakaros VKX File" 30
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 31
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 31
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 32
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 33
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 34
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 35
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 36
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 29
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 29
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 30
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 31
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 32
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 33
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 34
!insertmacro URI_ASSOCIATION_ADD "geo"
@ -267,9 +265,6 @@ 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" ""
WriteRegStr HKCR ".vtk\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".vkx\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -444,8 +439,6 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "gemf"
!insertmacro FILE_ASSOCIATION_REMOVE "000"
!insertmacro FILE_ASSOCIATION_REMOVE "031"
!insertmacro FILE_ASSOCIATION_REMOVE "vtk"
!insertmacro FILE_ASSOCIATION_REMOVE "vkx"
!insertmacro URI_ASSOCIATION_REMOVE "geo"
@ -499,9 +492,6 @@ 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"
DeleteRegValue HKCR ".vtk\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".vkx\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,12 +1193,10 @@ 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;
}
if (_dateRange.first.isNull() || _dateRange.first > date)
_dateRange.first = date;
if (_dateRange.second.isNull() || _dateRange.second < date)
_dateRange.second = date;
}
_trackCount += data.tracks().count();

View File

@ -64,7 +64,6 @@ GraphItem *SpeedGraph::loadGraph(const Graph &graph, const Track &track,
if (primary) {
_avg.append(QPointF(track.distance(), gi->avg()));
_mavg.append(QPointF(track.distance(), gi->mavg()));
_max.append(QPointF(track.distance(), gi->max()));
}
return gi;
@ -118,16 +117,6 @@ qreal SpeedGraph::avg() const
return (sum / w);
}
qreal SpeedGraph::max() const
{
qreal mv = 0;
for (int i = 0; i < _max.size(); i++)
mv = qMax(mv, _max.at(i).y());
return mv;
}
void SpeedGraph::clear()
{
qDeleteAll(_tracks);
@ -135,7 +124,6 @@ void SpeedGraph::clear()
_avg.clear();
_mavg.clear();
_max.clear();
GraphTab::clear();
}

View File

@ -26,13 +26,12 @@ private:
GraphItem *loadGraph(const Graph &graph, const Track &track,
const QColor &color, bool primary);
qreal avg() const;
qreal max() const;
qreal max() const {return bounds().bottom();}
void setYUnits();
void setInfo();
QVector<QPointF> _avg;
QVector<QPointF> _mavg;
QVector<QPointF> _max;
Units _units;
TimeType _timeType;

View File

@ -7,18 +7,15 @@ RFC 4180 parser with the following enchancements:
- allows LF line ends in addition to CRLF line ends
*/
bool CSV::readEntry(QByteArrayList &list, int limit)
bool CSV::readEntry(QByteArrayList &list)
{
int state = 0, len = 0;
int state = 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, int limit = 4096);
bool readEntry(QByteArrayList &list);
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() const;
int Count();
/// 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) const;
void CountRec(Node* a_node, int& a_count);
/// 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() const
int RTREE_QUAL::Count()
{
int count = 0;
CountRec(m_root, count);
@ -483,7 +483,7 @@ int RTREE_QUAL::Count() const
RTREE_TEMPLATE
void RTREE_QUAL::CountRec(Node* a_node, int& a_count) const
void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
{
if (a_node->IsInternalNode()) { // not a leaf node
for (int index = 0; index < a_node->m_count; ++index)

View File

@ -23,9 +23,6 @@
#include "onmoveparsers.h"
#include "twonavparser.h"
#include "gpsdumpparser.h"
#include "txtparser.h"
#include "vtkparser.h"
#include "vkxparser.h"
#include "data.h"
@ -52,9 +49,6 @@ static OMDParser omd;
static GHPParser ghp;
static TwoNavParser twonav;
static GPSDumpParser gpsdump;
static TXTParser txt;
static VTKParser vtk;
static VKXParser vkx;
static QMultiMap<QString, Parser*> parsers()
{
@ -88,9 +82,6 @@ static QMultiMap<QString, Parser*> parsers()
map.insert("rte", &twonav);
map.insert("wpt", &twonav);
map.insert("wpt", &gpsdump);
map.insert("txt", &txt);
map.insert("vtk", &vtk);
map.insert("vkx", &vkx);
return map;
}
@ -250,9 +241,6 @@ 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", "VKX files") + " (*.vkx);;"
+ qApp->translate("Data", "VTK files") + " (*.vtk);;"
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
+ qApp->translate("Data", "GPSDump files") + " (*.wpt);;"
+ qApp->translate("Data", "All files") + " (*)";

View File

@ -467,7 +467,8 @@ bool FITParser::parseHeader(CTX &ctx)
}
bool FITParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);

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 const QRegularExpression re("\\$\\[[^\\]]+\\]");
static QRegularExpression re("\\$\\[[^\\]]+\\]");
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("name"))

View File

@ -4,6 +4,7 @@
#include <QXmlStreamReader>
#include "parser.h"
class TCXParser : public Parser
{
public:

View File

@ -1,80 +0,0 @@
#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;
}

View File

@ -1,18 +0,0 @@
#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

@ -1,151 +0,0 @@
#include "vkxparser.h"
static bool readTrackPoint(QDataStream &stream, SegmentData &segment)
{
quint64 time;
qint32 lat, lon;
quint32 unused;
float speed, alt;
stream >> time >> lat >> lon;
if (stream.status() != QDataStream::Ok)
return false;
if (stream.readRawData((char*)&speed, 4) != 4)
return false;
stream >> unused;
if (stream.readRawData((char*)&alt, 4) != 4)
return false;
stream >> unused >> unused >> unused >> unused;
if (stream.status() != QDataStream::Ok)
return false;
Trackpoint t(Coordinates(lon / 1e7, lat / 1e7));
if (!t.coordinates().isValid())
return false;
t.setTimestamp(QDateTime::fromMSecsSinceEpoch(time));
t.setSpeed(speed);
t.setElevation(alt);
segment.append(t);
return true;
}
bool VKXParser::skip(QDataStream &stream, quint8 key, int len)
{
if (stream.skipRawData(len) != len) {
_errorString = "Invalid 0x" + QString::number(key, 16) + " row";
return false;
}
return true;
}
bool VKXParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);
Q_UNUSED(waypoints);
quint8 key;
quint64 hdr;
SegmentData segment;
QDataStream stream(file);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> hdr;
if ((hdr & 0xFF) != 0xFF) {
_errorString = "Not a Vakaros VKX file";
return false;
}
while (stream.status() == QDataStream::Ok) {
stream >> key;
if (stream.status() != QDataStream::Ok)
break;
switch (key) {
case 0x01:
if (!skip(stream, key, 32))
return false;
break;
case 0x02:
if (!readTrackPoint(stream, segment)) {
_errorString = "Invalid 0x2 row";
return false;
}
break;
case 0x03:
if (!skip(stream, key, 20))
return false;
break;
case 0x04:
if (!skip(stream, key, 13))
return false;
break;
case 0x05:
if (!skip(stream, key, 17))
return false;
break;
case 0x06:
if (!skip(stream, key, 18))
return false;
break;
case 0x07:
if (!skip(stream, key, 12))
return false;
break;
case 0x08:
if (!skip(stream, key, 13))
return false;
break;
case 0x0A:
case 0x0B:
if (!skip(stream, key, 16))
return false;
break;
case 0x0C:
if (!skip(stream, key, 12))
return false;
break;
case 0x0E:
case 0x0F:
if (!skip(stream, key, 16))
return false;
break;
case 0x10:
if (!skip(stream, key, 12))
return false;
break;
case 0x20:
if (!skip(stream, key, 13))
return false;
break;
case 0x21:
if (!skip(stream, key, 52))
return false;
break;
case 0xFE:
if (!skip(stream, key, 2))
return false;
break;
case 0xFF:
if (!skip(stream, key, 7))
return false;
break;
default:
_errorString = "Unknown row key: 0x" + QString::number(key, 16);
return false;
}
}
if (stream.status() != QDataStream::ReadPastEnd) {
_errorString = "Unexpected EOF";
return false;
}
tracks.append(segment);
return true;
}

View File

@ -1,27 +0,0 @@
#ifndef VKXPARSER_H
#define VKXPARSER_H
#include "parser.h"
class QDataStream;
class VKXParser : public Parser
{
public:
VKXParser()
{
static_assert(sizeof(float) == 4, "Invalid float size");
}
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 0;}
private:
bool skip(QDataStream &stream, quint8 key, int len);
QString _errorString;
};
#endif // VKXPARSER_H

View File

@ -1,217 +0,0 @@
#include <QtEndian>
#include <QTimeZone>
#include "vtkparser.h"
#define TYPE(tag) (tag & 0x07)
#define FIELD(tag) (tag >> 3)
#define VARINT 0
#define I64 1
#define LEN 2
#define I32 5
struct CTX
{
CTX(const QByteArray &ba)
: bp(ba.constData()), be(bp + ba.size()), tag(0) {}
const char *bp;
const char *be;
quint32 tag;
};
static inline qint32 zigzag32decode(quint32 value)
{
return static_cast<qint32>((value >> 1u) ^ static_cast<quint32>(
-static_cast<qint32>(value & 1u)));
}
template<typename T>
static bool varint(CTX &ctx, T &val)
{
unsigned int shift = 0;
val = 0;
while (ctx.bp < ctx.be) {
val |= ((quint8)*ctx.bp & 0x7F) << shift;
shift += 7;
if (!((quint8)*ctx.bp++ & 0x80))
return true;
}
return false;
}
static bool length(CTX &ctx, qint32 &val)
{
if (TYPE(ctx.tag) != LEN)
return false;
if (!varint(ctx, val))
return false;
return (val >= 0);
}
static bool skip(CTX &ctx)
{
qint32 len = 0;
switch (TYPE(ctx.tag)) {
case VARINT:
return varint(ctx, len);
case I64:
len = 8;
break;
case LEN:
if (!varint(ctx, len) || len < 0)
return false;
break;
case I32:
len = 4;
break;
default:
return false;
}
if (ctx.bp + len > ctx.be)
return false;
ctx.bp += len;
return true;
}
static bool trackpoint(CTX &ctx, Trackpoint &t)
{
qint32 len, lon = 0xFFFFFFF, lat = 0xFFFFFFF;
quint32 val, seconds = 0, centiSeconds = 0, speed = 0;
if (!length(ctx, len))
return false;
const char *ee = ctx.bp + len;
if (ee > ctx.be)
return false;
while (ctx.bp < ee) {
if (!varint(ctx, ctx.tag))
return false;
switch (FIELD(ctx.tag)) {
case 1:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, seconds))
return false;
break;
case 2:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, centiSeconds))
return false;
break;
case 3:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, val))
return false;
lat = zigzag32decode(val);
break;
case 4:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, val))
return false;
lon = zigzag32decode(val);
break;
case 5:
if (TYPE(ctx.tag) != VARINT)
return false;
if (!varint(ctx, speed))
return false;
break;
default:
if (!skip(ctx))
return false;
}
}
t.setCoordinates(Coordinates(lon / 1e7, lat / 1e7));
t.setTimestamp(QDateTime::fromMSecsSinceEpoch(
((qint64)seconds * 1000) + ((qint64)centiSeconds * 10),
QTimeZone::utc()));
t.setSpeed(speed * 0.051444);
return (ctx.bp == ee);
}
static bool record(CTX &ctx, Trackpoint &t)
{
while (ctx.bp < ctx.be) {
if (!varint(ctx, ctx.tag))
return false;
switch (FIELD(ctx.tag)) {
case 1:
if (!trackpoint(ctx, t))
return false;
break;
default:
if (!skip(ctx))
return false;
}
}
return (ctx.bp == ctx.be);
}
bool VTKParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(polygons);
Q_UNUSED(waypoints);
qint64 len;
quint16 recordLen;
QByteArray ba;
SegmentData segment;
Trackpoint t;
_errorString = "";
while (true) {
if ((len = file->read((char*)&recordLen, sizeof(recordLen)))
!= sizeof(recordLen)) {
if (!len)
break;
else {
_errorString = "Error reading VTK record size";
return false;
}
}
recordLen = qFromLittleEndian(recordLen);
ba.resize(recordLen);
if (file->read(ba.data(), ba.size()) != ba.size()) {
_errorString = "Error reading VTK record";
return false;
}
CTX ctx(ba);
t.setCoordinates(Coordinates());
if (!record(ctx, t)) {
_errorString = "Invalid VTK record";
return false;
} else {
if (t.coordinates().isValid())
segment.append(t);
else if (!t.coordinates().isNull()) {
_errorString = "Invalid VTK record coordinates";
return false;
}
}
}
tracks.append(segment);
return true;
}

View File

@ -1,18 +0,0 @@
#ifndef VTKPARSER_H
#define VTKPARSER_H
#include "parser.h"
class VTKParser : public Parser
{
public:
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 0;}
private:
QString _errorString;
};
#endif // VTKPARSER_H

View File

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

View File

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

View File

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

View File

@ -1,79 +0,0 @@
#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

@ -1,4 +1,3 @@
#include <QtEndian>
#include <QFile>
#include <QRegularExpression>
#include "common/util.h"
@ -6,6 +5,13 @@
using namespace ENC;
#define UINT16(x) \
(((quint16)*(const uchar*)(x)) \
| ((quint16)(*((const uchar*)(x) + 1)) << 8))
#define INT32(x) ((qint32)UINT32(x))
#define INT16(x) ((qint16)UINT16(x))
struct DR {
char RecordLength[5];
char InterchangeLevel;
@ -23,18 +29,18 @@ struct DR {
};
const QVariant *ISO8211::Field::data(quint32 name, int idx) const
const QVariant *ISO8211::Field::data(const QByteArray &name, int idx) const
{
const QVector<QVariant> &v = _data.at(idx);
for (int i = 0; i < _subFields->size(); i++)
if (_subFields->at(i) == name)
for (int i = 0; i < _subFields.size(); i++)
if (_subFields.at(i) == name)
return &v.at(i);
return 0;
}
bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const
bool ISO8211::Field::subfield(const char *name, int *val, int idx) const
{
bool ok;
@ -46,7 +52,7 @@ bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const
return ok;
}
bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const
bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const
{
bool ok;
@ -58,7 +64,7 @@ bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const
return ok;
}
bool ISO8211::Field::subfield(quint32 name, QByteArray *val, int idx) const
bool ISO8211::Field::subfield(const char *name, QByteArray *val, int idx) const
{
const QVariant *v = data(name, idx);
if (!v)
@ -95,7 +101,6 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
DR ddr;
QByteArray fieldLen, fieldPos;
int len, lenSize, posSize, tagSize, offset;
char tag[4];
static_assert(sizeof(ddr) == 24, "Invalid DR alignment");
if (_file.read((char*)&ddr, sizeof(ddr)) != sizeof(ddr))
@ -110,19 +115,20 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
if (len < 0 || offset < 0 || lenSize < 0 || posSize < 0 || tagSize < 0)
return -1;
fields.resize((offset - 1 - sizeof(ddr)) / (lenSize + posSize + tagSize));
fields.resize((offset - 1 - sizeof(DR)) / (lenSize + posSize + tagSize));
fieldLen.resize(lenSize);
fieldPos.resize(posSize);
for (int i = 0; i < fields.size(); i++) {
FieldDefinition &r = fields[i];
if (_file.read(tag, sizeof(tag)) != tagSize
r.tag.resize(tagSize);
if (_file.read(r.tag.data(), tagSize) != tagSize
|| _file.read(fieldLen.data(), lenSize) != lenSize
|| _file.read(fieldPos.data(), posSize) != posSize)
return -1;
r.tag = qFromLittleEndian<quint32>(tag);
r.pos = offset + Util::str2int(fieldPos.constData(), posSize);
r.size = Util::str2int(fieldLen.constData(), lenSize);
@ -135,13 +141,13 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
{
static const QRegularExpression re(
"([0-9]*)(A|I|R|B|b11|b12|b14|b21|b22|b24)\\(*([0-9]*)\\)*");
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
static QRegularExpression re("(\\d*)(\\w+)\\(*(\\d*)\\)*");
QByteArray ba;
bool repeat = false;
QVector<SubFieldDefinition> defs;
QVector<quint32> defTags;
QVector<QByteArray> defTags;
ba.resize(def.size);
if (!(_file.seek(def.pos) && _file.read(ba.data(), ba.size()) == ba.size()))
return false;
@ -150,9 +156,9 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
repeat = true;
list[1].remove(0, 1);
}
QList<QByteArray> tags(list.at(1).split('!'));
if (list.size() > 2) {
QList<QByteArray> tags(list.at(1).split('!'));
QRegularExpressionMatchIterator it = re.globalMatch(list.at(2));
int tag = 0;
@ -182,17 +188,11 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
SubFieldDefinition sfd(fieldType(typeStr, size));
if (sfd.type() == Unknown)
return false;
if (tag >= tags.size())
return false;
defs[tag] = sfd;
defTags[tag] = (tags.at(tag).length() == 4)
? qFromLittleEndian<quint32>(tags.at(tag).constData()) : 0;
defTags[tag] = tags.at(tag);
tag++;
}
}
if (tag != tags.size())
return false;
}
fields = SubFields(defTags, defs, repeat);
@ -218,10 +218,8 @@ bool ISO8211::readDDR()
for (int i = 0; i < fields.size(); i++) {
SubFields def;
if (!readDDA(fields.at(i), def)) {
QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized);
qToLittleEndian<quint32>(fields.at(i).tag, tag.data());
_errorString = QString("Error reading %1 DDA field")
.arg(QString(tag));
.arg(QString(fields.at(i).tag));
return false;
}
_map.insert(fields.at(i).tag, def);
@ -238,8 +236,9 @@ bool ISO8211::readDDR()
bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
const QVector<SubFieldDefinition> &fields, bool repeat, Data &data)
{
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
QByteArray ba;
ba.resize(def.size);
if (!(_file.seek(pos + def.pos)
&& _file.read(ba.data(), ba.size()) == ba.size()))
return false;
@ -249,7 +248,8 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
const char *ep = ba.constData() + ba.size() - 1;
do {
QVector<QVariant> row(fields.size());
QVector<QVariant> row;
row.resize(fields.size());
for (int i = 0; i < fields.size(); i++) {
const SubFieldDefinition &f = fields.at(i);
@ -273,11 +273,11 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
dp++;
break;
case S16:
row[i] = QVariant(qFromLittleEndian<qint16>(dp));
row[i] = QVariant(INT16(dp));
dp += 2;
break;
case S32:
row[i] = QVariant(qFromLittleEndian<qint32>(dp));
row[i] = QVariant(INT32(dp));
dp += 4;
break;
case U8:
@ -285,11 +285,11 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
dp++;
break;
case U16:
row[i] = QVariant(qFromLittleEndian<quint16>(dp));
row[i] = QVariant(UINT16(dp));
dp += 2;
break;
case U32:
row[i] = QVariant(qFromLittleEndian<quint32>(dp));
row[i] = QVariant(UINT32(dp));
dp += 4;
break;
default:
@ -325,16 +325,13 @@ bool ISO8211::readRecord(Record &record)
FieldsMap::const_iterator it(_map.find(def.tag));
if (it == _map.constEnd()) {
QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized);
qToLittleEndian<quint32>(def.tag, tag.data());
_errorString = QString("%1: unknown record").arg(QString(tag));
_errorString = QString("%1: unknown record").arg(QString(def.tag));
return false;
}
if (!readUDA(pos, def, it->defs(), it->repeat(), data)) {
QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized);
qToLittleEndian<quint32>(def.tag, tag.data());
_errorString = QString("Error reading %1 record").arg(QString(tag));
_errorString = QString("Error reading %1 record")
.arg(QString(def.tag));
return false;
}
@ -344,7 +341,8 @@ bool ISO8211::readRecord(Record &record)
return true;
}
const ISO8211::Field *ISO8211::field(const Record &record, quint32 name)
const ISO8211::Field *ISO8211::field(const Record &record, const QByteArray &name)
{
for (int i = 0; i < record.size(); i++)
if (record.at(i).tag() == name)

View File

@ -4,6 +4,13 @@
#include <QFile>
#include <QByteArray>
#include <QVariant>
#include <QDebug>
#define UINT32(x) \
(((quint32)*(const uchar*)(x)) \
| ((quint32)(*((const uchar*)(x) + 1)) << 8) \
| ((quint32)(*((const uchar*)(x) + 2)) << 16) \
| ((quint32)(*((const uchar*)(x) + 3)) << 24))
namespace ENC {
@ -15,22 +22,23 @@ public:
class Field
{
public:
Field() : _subFields(0) {}
Field(quint32 tag, const QVector<quint32> &subFields, const Data &data)
: _tag(tag), _subFields(&subFields), _data(data) {}
Field() {}
Field(const QByteArray &tag, const QVector<QByteArray> &subFields,
const Data &data) : _tag(tag), _subFields(subFields), _data(data) {}
quint32 tag() const {return _tag;}
const QByteArray &tag() const {return _tag;}
const QVector<QByteArray> &subFields() const {return _subFields;}
const Data &data() const {return _data;}
bool subfield(quint32 name, int *val, int idx = 0) const;
bool subfield(quint32 name, uint *val, int idx = 0) const;
bool subfield(quint32 name, QByteArray *val, int idx = 0) const;
bool subfield(const char *name, int *val, int idx = 0) const;
bool subfield(const char *name, uint *val, int idx = 0) const;
bool subfield(const char *name, QByteArray *val, int idx = 0) const;
private:
const QVariant *data(quint32 name, int idx = 0) const;
const QVariant *data(const QByteArray &name, int idx = 0) const;
quint32 _tag;
const QVector<quint32> *_subFields;
QByteArray _tag;
QVector<QByteArray> _subFields;
Data _data;
};
@ -42,21 +50,14 @@ public:
const QString &errorString() const {return _errorString;}
static const Field *field(const Record &record, quint32 name);
static constexpr quint32 NAME(const char str[4])
{
return static_cast<quint32>(str[0])
+ (static_cast<quint32>(str[1]) << 8)
+ (static_cast<quint32>(str[2]) << 16)
+ (static_cast<quint32>(str[3]) << 24);
}
static const Field *field(const Record &record, const QByteArray &name);
private:
enum FieldType {Unknown, String, Array, S8, S16, S32, U8, U16, U32};
struct FieldDefinition
{
quint32 tag;
QByteArray tag;
int pos;
int size;
};
@ -80,22 +81,22 @@ private:
{
public:
SubFields() : _repeat(false) {}
SubFields(const QVector<quint32> &tags,
SubFields(const QVector<QByteArray> &tags,
const QVector<SubFieldDefinition> &defs, bool repeat)
: _tags(tags), _defs(defs), _repeat(repeat) {}
const QVector<quint32> &tags() const {return _tags;}
const QVector<QByteArray> &tags() const {return _tags;}
const QVector<SubFieldDefinition> &defs() const {return _defs;}
bool repeat() const {return _repeat;}
private:
QVector<quint32> _tags;
QVector<QByteArray> _tags;
QVector<SubFieldDefinition> _defs;
bool _repeat;
};
typedef QMap<quint32, SubFields> FieldsMap;
typedef QMap<QByteArray, SubFields> FieldsMap;
static SubFieldDefinition fieldType(const QString &str, int cnt);
@ -109,6 +110,14 @@ private:
QString _errorString;
};
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const ISO8211::Field &field)
{
dbg.nospace() << "Field(" << field.tag() << ", " << field.subFields() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG
}
#endif // ENC_ISO8211_H

View File

@ -1,4 +1,3 @@
#include <QtEndian>
#include "GUI/units.h"
#include "objects.h"
#include "attributes.h"
@ -15,19 +14,6 @@ using namespace ENC;
#define PRIM_L 2
#define PRIM_A 3
constexpr quint32 RCID = ISO8211::NAME("RCID");
constexpr quint32 SG2D = ISO8211::NAME("SG2D");
constexpr quint32 SG3D = ISO8211::NAME("SG3D");
constexpr quint32 FSPT = ISO8211::NAME("FSPT");
constexpr quint32 VRPT = ISO8211::NAME("VRPT");
constexpr quint32 ATTF = ISO8211::NAME("ATTF");
constexpr quint32 VRID = ISO8211::NAME("VRID");
constexpr quint32 FRID = ISO8211::NAME("FRID");
constexpr quint32 DSPM = ISO8211::NAME("DSPM");
constexpr quint32 COMF = ISO8211::NAME("COMF");
constexpr quint32 SOMF = ISO8211::NAME("SOMF");
constexpr quint32 HUNI = ISO8211::NAME("HUNI");
static QMap<uint,uint> orderMapInit()
{
QMap<uint,uint> map;
@ -104,20 +90,20 @@ static uint order(uint type)
return (it == orderMap.constEnd()) ? (type>>16) + 512 : it.value();
}
static void warning(const ISO8211::Field &frid, uint prim)
static void warning(const ISO8211::Field &FRID, uint PRIM)
{
uint rcid = 0xFFFFFFFF;
frid.subfield(RCID, &rcid);
uint RCID = 0xFFFFFFFF;
FRID.subfield("RCID", &RCID);
switch (prim) {
switch (PRIM) {
case PRIM_P:
qWarning("%u: invalid point feature", rcid);
qWarning("%u: invalid point feature", RCID);
break;
case PRIM_L:
qWarning("%u: invalid line feature", rcid);
qWarning("%u: invalid line feature", RCID);
break;
case PRIM_A:
qWarning("%u: invalid area feature", rcid);
qWarning("%u: invalid area feature", RCID);
break;
}
}
@ -146,7 +132,7 @@ static bool parseNAME(const ISO8211::Field *f, quint8 *type, quint32 *id,
return false;
*type = (quint8)(*ba.constData());
*id = qFromLittleEndian<quint32>(ba.constData() + 1);
*id = UINT32(ba.constData() + 1);
return true;
}
@ -155,9 +141,9 @@ static const ISO8211::Field *SGXD(const ISO8211::Record &r)
{
const ISO8211::Field *f;
if ((f = ISO8211::field(r, SG2D)))
if ((f = ISO8211::field(r, "SG2D")))
return f;
else if ((f = ISO8211::field(r, SG3D)))
else if ((f = ISO8211::field(r, "SG3D")))
return f;
else
return 0;
@ -226,12 +212,12 @@ static bool linePointCb(const MapData::Line *line, void *context)
return true;
}
static Coordinates coordinates(int x, int y, uint comf)
static Coordinates coordinates(int x, int y, uint COMF)
{
return Coordinates(x / (double)comf, y / (double)comf);
return Coordinates(x / (double)COMF, y / (double)COMF);
}
static Coordinates point(const ISO8211::Record &r, uint comf)
static Coordinates point(const ISO8211::Record &r, uint COMF)
{
const ISO8211::Field *f = SGXD(r);
if (!f)
@ -240,7 +226,7 @@ static Coordinates point(const ISO8211::Record &r, uint comf)
int y = f->data().at(0).at(0).toInt();
int x = f->data().at(0).at(1).toInt();
return coordinates(x, y, comf);
return coordinates(x, y, COMF);
}
static uint depthLevel(double minDepth)
@ -376,8 +362,6 @@ 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());
@ -439,8 +423,6 @@ 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:
@ -491,10 +473,10 @@ RectC MapData::Line::bounds() const
}
QVector<MapData::Sounding> MapData::soundings(const ISO8211::Record &r,
uint comf, uint somf)
uint COMF, uint SOMF)
{
QVector<Sounding> s;
const ISO8211::Field *f = ISO8211::field(r, SG3D);
const ISO8211::Field *f = ISO8211::field(r, "SG3D");
if (!f)
return QVector<Sounding>();
@ -503,24 +485,24 @@ QVector<MapData::Sounding> MapData::soundings(const ISO8211::Record &r,
int y = f->data().at(i).at(0).toInt();
int x = f->data().at(i).at(1).toInt();
int z = f->data().at(i).at(2).toInt();
s.append(Sounding(coordinates(x, y, comf), z / (double)somf));
s.append(Sounding(coordinates(x, y, COMF), z / (double)SOMF));
}
return s;
}
QVector<MapData::Sounding> MapData::soundingGeometry(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint comf, uint somf)
const RecordMap &vi, const RecordMap &vc, uint COMF, uint SOMF)
{
quint8 type;
quint32 id;
RecordMapIterator it;
const ISO8211::Field *fspt = ISO8211::field(r, FSPT);
if (!fspt || fspt->data().at(0).size() != 4)
const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT");
if (!FSPT || FSPT->data().at(0).size() != 4)
return QVector<Sounding>();
if (!parseNAME(fspt, &type, &id))
if (!parseNAME(FSPT, &type, &id))
return QVector<Sounding>();
if (type == RCNM_VI) {
@ -534,21 +516,21 @@ QVector<MapData::Sounding> MapData::soundingGeometry(const ISO8211::Record &r,
} else
return QVector<Sounding>();
return soundings(it.value(), comf, somf);
return soundings(it.value(), COMF, SOMF);
}
Coordinates MapData::pointGeometry(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint comf)
const RecordMap &vi, const RecordMap &vc, uint COMF)
{
quint8 type;
quint32 id;
RecordMapIterator it;
const ISO8211::Field *fspt = ISO8211::field(r, FSPT);
if (!fspt || fspt->data().at(0).size() != 4)
const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT");
if (!FSPT || FSPT->data().at(0).size() != 4)
return Coordinates();
if (!parseNAME(fspt, &type, &id))
if (!parseNAME(FSPT, &type, &id))
return Coordinates();
if (type == RCNM_VI) {
@ -562,55 +544,55 @@ Coordinates MapData::pointGeometry(const ISO8211::Record &r,
} else
return Coordinates();
return point(it.value(), comf);
return point(it.value(), COMF);
}
QVector<Coordinates> MapData::lineGeometry(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint comf)
const RecordMap &vc, const RecordMap &ve, uint COMF)
{
QVector<Coordinates> path;
Coordinates c[2];
uint ornt;
uint ORNT;
quint8 type;
quint32 id;
const ISO8211::Field *fspt = ISO8211::field(r, FSPT);
if (!fspt || fspt->data().at(0).size() != 4)
const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT");
if (!FSPT || FSPT->data().at(0).size() != 4)
return QVector<Coordinates>();
for (int i = 0; i < fspt->data().size(); i++) {
if (!parseNAME(fspt, &type, &id, i) || type != RCNM_VE)
for (int i = 0; i < FSPT->data().size(); i++) {
if (!parseNAME(FSPT, &type, &id, i) || type != RCNM_VE)
return QVector<Coordinates>();
ornt = fspt->data().at(i).at(1).toUInt();
ORNT = FSPT->data().at(i).at(1).toUInt();
RecordMapIterator it = ve.find(id);
if (it == ve.constEnd())
return QVector<Coordinates>();
const ISO8211::Record &frid = it.value();
const ISO8211::Field *vrpt = ISO8211::field(frid, VRPT);
if (!vrpt || vrpt->data().size() != 2)
const ISO8211::Record &FRID = it.value();
const ISO8211::Field *VRPT = ISO8211::field(FRID, "VRPT");
if (!VRPT || VRPT->data().size() != 2)
return QVector<Coordinates>();
for (int j = 0; j < 2; j++) {
if (!parseNAME(vrpt, &type, &id, j) || type != RCNM_VC)
if (!parseNAME(VRPT, &type, &id, j) || type != RCNM_VC)
return QVector<Coordinates>();
RecordMapIterator jt = vc.find(id);
if (jt == vc.constEnd())
return QVector<Coordinates>();
c[j] = point(jt.value(), comf);
c[j] = point(jt.value(), COMF);
if (c[j].isNull())
return QVector<Coordinates>();
}
const ISO8211::Field *vertexes = SGXD(frid);
if (ornt == 2) {
const ISO8211::Field *vertexes = SGXD(FRID);
if (ORNT == 2) {
path.append(c[1]);
if (vertexes) {
for (int j = vertexes->data().size() - 1; j >= 0; j--) {
const QVector<QVariant> &cv = vertexes->data().at(j);
path.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(),
comf));
COMF));
}
}
path.append(c[0]);
@ -620,7 +602,7 @@ QVector<Coordinates> MapData::lineGeometry(const ISO8211::Record &r,
for (int j = 0; j < vertexes->data().size(); j++) {
const QVector<QVariant> &cv = vertexes->data().at(j);
path.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(),
comf));
COMF));
}
}
path.append(c[1]);
@ -631,26 +613,26 @@ QVector<Coordinates> MapData::lineGeometry(const ISO8211::Record &r,
}
Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint comf)
const RecordMap &ve, uint COMF)
{
Polygon path;
QVector<Coordinates> v;
Coordinates c[2];
uint ornt, usag;
uint ORNT, USAG;
quint8 type;
quint32 id;
const ISO8211::Field *fspt = ISO8211::field(r, FSPT);
if (!fspt || fspt->data().at(0).size() != 4)
const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT");
if (!FSPT || FSPT->data().at(0).size() != 4)
return Polygon();
for (int i = 0; i < fspt->data().size(); i++) {
if (!parseNAME(fspt, &type, &id, i) || type != RCNM_VE)
for (int i = 0; i < FSPT->data().size(); i++) {
if (!parseNAME(FSPT, &type, &id, i) || type != RCNM_VE)
return Polygon();
ornt = fspt->data().at(i).at(1).toUInt();
usag = fspt->data().at(i).at(2).toUInt();
ORNT = FSPT->data().at(i).at(1).toUInt();
USAG = FSPT->data().at(i).at(2).toUInt();
if (usag == 2 && path.isEmpty()) {
if (USAG == 2 && path.isEmpty()) {
path.append(v);
v.clear();
}
@ -658,55 +640,55 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
RecordMapIterator it = ve.find(id);
if (it == ve.constEnd())
return Polygon();
const ISO8211::Record &frid = it.value();
const ISO8211::Field *vrpt = ISO8211::field(frid, VRPT);
if (!vrpt || vrpt->data().size() != 2)
const ISO8211::Record &FRID = it.value();
const ISO8211::Field *VRPT = ISO8211::field(FRID, "VRPT");
if (!VRPT || VRPT->data().size() != 2)
return Polygon();
for (int j = 0; j < 2; j++) {
if (!parseNAME(vrpt, &type, &id, j) || type != RCNM_VC)
if (!parseNAME(VRPT, &type, &id, j) || type != RCNM_VC)
return Polygon();
RecordMapIterator jt = vc.find(id);
if (jt == vc.constEnd())
return Polygon();
c[j] = point(jt.value(), comf);
c[j] = point(jt.value(), COMF);
if (c[j].isNull())
return Polygon();
}
const ISO8211::Field *vertexes = SGXD(frid);
if (ornt == 2) {
const ISO8211::Field *vertexes = SGXD(FRID);
if (ORNT == 2) {
v.append(c[1]);
if (usag == 3)
if (USAG == 3)
v.append(Coordinates());
if (vertexes) {
for (int j = vertexes->data().size() - 1; j >= 0; j--) {
const QVector<QVariant> &cv = vertexes->data().at(j);
v.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(),
comf));
COMF));
}
}
if (usag == 3)
if (USAG == 3)
v.append(Coordinates());
v.append(c[0]);
} else {
v.append(c[0]);
if (usag == 3)
if (USAG == 3)
v.append(Coordinates());
if (vertexes) {
for (int j = 0; j < vertexes->data().size(); j++) {
const QVector<QVariant> &cv = vertexes->data().at(j);
v.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(),
comf));
COMF));
}
}
if (usag == 3)
if (USAG == 3)
v.append(Coordinates());
v.append(c[1]);
}
if (usag == 2 && v.first() == v.last()) {
if (USAG == 2 && v.first() == v.last()) {
path.append(v);
v.clear();
}
@ -722,12 +704,12 @@ MapData::Attributes MapData::attributes(const ISO8211::Record &r)
{
Attributes attr;
const ISO8211::Field *attf = ISO8211::field(r, ATTF);
if (!(attf && attf->data().at(0).size() == 2))
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2))
return attr;
for (int i = 0; i < attf->data().size(); i++) {
const QVector<QVariant> &av = attf->data().at(i);
for (int i = 0; i < ATTF->data().size(); i++) {
const QVector<QVariant> &av = ATTF->data().at(i);
attr.insert(av.at(0).toUInt(), av.at(1).toByteArray());
}
@ -740,64 +722,64 @@ MapData::Point *MapData::pointObject(const Sounding &s)
}
MapData::Point *MapData::pointObject(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint comf, uint objl, uint huni)
const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL, uint HUNI)
{
Coordinates c(pointGeometry(r, vi, vc, comf));
return (c.isNull() ? 0 : new Point(objl, c, attributes(r), huni));
Coordinates c(pointGeometry(r, vi, vc, COMF));
return (c.isNull() ? 0 : new Point(OBJL, c, attributes(r), HUNI));
}
MapData::Line *MapData::lineObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint comf, uint objl)
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL)
{
QVector<Coordinates> path(lineGeometry(r, vc, ve, comf));
return (path.isEmpty() ? 0 : new Line(objl, path, attributes(r)));
QVector<Coordinates> path(lineGeometry(r, vc, ve, COMF));
return (path.isEmpty() ? 0 : new Line(OBJL, path, attributes(r)));
}
MapData::Poly *MapData::polyObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint comf, uint objl, uint huni)
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI)
{
Polygon path(polyGeometry(r, vc, ve, comf));
return (path.isEmpty() ? 0 : new Poly(objl, path, attributes(r), huni));
Polygon path(polyGeometry(r, vc, ve, COMF));
return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI));
}
bool MapData::processRecord(const ISO8211::Record &record,
QVector<ISO8211::Record> &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve,
RecordMap &vf, uint &comf, uint &somf, uint &huni)
RecordMap &vf, uint &COMF, uint &SOMF, uint &HUNI)
{
if (record.size() < 2)
return false;
const ISO8211::Field &f = record.at(1);
quint32 tag = f.tag();
const QByteArray &ba = f.tag();
if (tag == VRID) {
if (ba == "VRID") {
if (f.data().at(0).size() < 2)
return false;
int rcnm = f.data().at(0).at(0).toInt();
uint rcid = f.data().at(0).at(1).toUInt();
int RCNM = f.data().at(0).at(0).toInt();
uint RCID = f.data().at(0).at(1).toUInt();
switch (rcnm) {
switch (RCNM) {
case RCNM_VI:
vi.insert(rcid, record);
vi.insert(RCID, record);
break;
case RCNM_VC:
vc.insert(rcid, record);
vc.insert(RCID, record);
break;
case RCNM_VE:
ve.insert(rcid, record);
ve.insert(RCID, record);
break;
case RCNM_VF:
vf.insert(rcid, record);
vf.insert(RCID, record);
break;
default:
return false;
}
} else if (tag == FRID) {
} else if (ba == "FRID") {
fe.append(record);
} else if (tag == DSPM) {
if (!(f.subfield(COMF, &comf) && f.subfield(SOMF, &somf)))
} else if (ba == "DSPM") {
if (!(f.subfield("COMF", &COMF) && f.subfield("SOMF", &SOMF)))
return false;
if (!f.subfield(HUNI, &huni))
if (!f.subfield("HUNI", &HUNI))
return false;
}
@ -810,7 +792,7 @@ MapData::MapData(const QString &path)
QVector<ISO8211::Record> fe;
ISO8211 ddf(path);
ISO8211::Record record;
uint prim, objl, comf = 1, somf = 1, huni = 1;
uint PRIM, OBJL, COMF = 1, SOMF = 1, HUNI = 1;
Poly *poly;
Line *line;
Point *point;
@ -820,7 +802,7 @@ MapData::MapData(const QString &path)
if (!ddf.readDDR())
return;
while (ddf.readRecord(record))
if (!processRecord(record, fe, vi, vc, ve, vf, comf, somf, huni))
if (!processRecord(record, fe, vi, vc, ve, vf, COMF, SOMF, HUNI))
qWarning("Invalid S-57 record");
for (int i = 0; i < fe.size(); i++) {
@ -829,39 +811,39 @@ MapData::MapData(const QString &path)
if (f.data().at(0).size() < 5)
continue;
prim = f.data().at(0).at(2).toUInt();
objl = f.data().at(0).at(4).toUInt();
PRIM = f.data().at(0).at(2).toUInt();
OBJL = f.data().at(0).at(4).toUInt();
switch (prim) {
switch (PRIM) {
case PRIM_P:
if (objl == SOUNDG) {
QVector<Sounding> s(soundingGeometry(r, vi, vc, comf, somf));
if (OBJL == SOUNDG) {
QVector<Sounding> s(soundingGeometry(r, vi, vc, COMF, SOMF));
for (int i = 0; i < s.size(); i++) {
point = pointObject(s.at(i));
pointBounds(point->pos(), min, max);
_points.Insert(min, max, point);
}
} else {
if ((point = pointObject(r, vi, vc, comf, objl, huni))) {
if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) {
pointBounds(point->pos(), min, max);
_points.Insert(min, max, point);
} else
warning(f, prim);
warning(f, PRIM);
}
break;
case PRIM_L:
if ((line = lineObject(r, vc, ve, comf, objl))) {
if ((line = lineObject(r, vc, ve, COMF, OBJL))) {
rectcBounds(line->bounds(), min, max);
_lines.Insert(min, max, line);
} else
warning(f, prim);
warning(f, PRIM);
break;
case PRIM_A:
if ((poly = polyObject(r, vc, ve, comf, objl, huni))) {
if ((poly = polyObject(r, vc, ve, COMF, OBJL, HUNI))) {
rectcBounds(poly->bounds(), min, max);
_areas.Insert(min, max, poly);
} else
warning(f, prim);
warning(f, PRIM);
break;
}
}
@ -882,7 +864,7 @@ MapData::~MapData()
delete _points.GetAt(pit);
}
void MapData::points(const RectC &rect, QList<Point> *points)
void MapData::points(const RectC &rect, QList<Point> *points) const
{
double min[2], max[2];
@ -892,12 +874,18 @@ void MapData::points(const RectC &rect, QList<Point> *points)
_lines.Search(min, max, linePointCb, points);
}
void MapData::polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines)
void MapData::lines(const RectC &rect, QList<Line> *lines) const
{
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,21 +1,82 @@
#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 : public Data
class MapData
{
public:
MapData(const QString &path);
virtual ~MapData();
typedef QMap<uint, QByteArray> Attributes;
virtual void polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines);
virtual void points(const RectC &rect, QList<Point> *points);
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();
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;
private:
struct Sounding {
@ -32,28 +93,28 @@ private:
typedef RTree<const Line*, double, 2> LineTree;
typedef RTree<const Point*, double, 2> PointTree;
static QVector<Sounding> soundings(const ISO8211::Record &r, uint comf,
uint somf);
static QVector<Sounding> soundings(const ISO8211::Record &r, uint COMF,
uint SOMF);
static QVector<Sounding> soundingGeometry(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint comf, uint somf);
const RecordMap &vi, const RecordMap &vc, uint COMF, uint SOMF);
static Coordinates pointGeometry(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint comf);
const RecordMap &vi, const RecordMap &vc, uint COMF);
static QVector<Coordinates> lineGeometry(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint comf);
const RecordMap &vc, const RecordMap &ve, uint COMF);
static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint comf);
const RecordMap &ve, uint COMF);
static Attributes attributes(const ISO8211::Record &r);
static Point *pointObject(const Sounding &s);
static Point *pointObject(const ISO8211::Record &r, const RecordMap &vi,
const RecordMap &vc, uint comf, uint objl, uint huni);
const RecordMap &vc, uint COMF, uint OBJL, uint HUNI);
static Line *lineObject(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint comf, uint objl);
const RecordMap &ve, uint COMF, uint OBJL);
static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint comf, uint objl, uint huni);
const RecordMap &ve, uint COMF, uint OBJL, uint HUNI);
static bool processRecord(const ISO8211::Record &record,
QVector<ISO8211::Record> &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve,
RecordMap &vf, uint &comf, uint &somf, uint &huni);
RecordMap &vf, uint &COMF, uint &SOMF, uint &HUNI);
PolygonTree _areas;
LineTree _lines;

View File

@ -28,14 +28,14 @@ static double angle(uint type, const QVariant &param)
? 90 + param.toDouble() : NAN;
}
bool RasterTile::showLabel(const QImage *img, int type) const
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
{
if (type>>16 == I_DISMAR)
return true;
int limit = (!_zoomRange.size())
? _zoomRange.min() : _zoomRange.min() + (_zoomRange.size() + 1) / 2;
if ((img || (type>>16 == SOUNDG)) && (_zoom < limit))
int limit = (!range.size())
? range.min() : range.min() + (range.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<Data::Point> &points) const
const QList<MapData::Point> &points) const
{
for (int i = 0; i < points.size(); i++) {
const Data::Point &point = points.at(i);
const MapData::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<Data::Poly> &polygons) const
const QList<MapData::Poly> &polygons) const
{
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
const Data::Poly &poly = polygons.at(i);
const MapData::Poly &poly = polygons.at(i);
if (poly.type() != _style->drawOrder().at(n))
continue;
const Style::Polygon &style = _style->polygon(poly.type());
@ -169,13 +169,8 @@ 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(path);
painter->drawPath(painterPath(poly.path()));
}
if (style.pen() != Qt::NoPen) {
painter->setPen(style.pen());
@ -190,12 +185,12 @@ void RasterTile::drawPolygons(QPainter *painter,
}
}
void RasterTile::drawLines(QPainter *painter, const QList<Data::Line> &lines) const
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines) const
{
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < lines.size(); i++) {
const Data::Line &line = lines.at(i);
const MapData::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (!style.img().isNull()) {
@ -226,11 +221,11 @@ static QRectF lightRect(const QPointF &pos, double range)
}
void RasterTile::drawSectorLights(QPainter *painter,
const QMultiMap<Coordinates, SectorLight> &lights) const
const QList<SectorLight> &lights) const
{
for (auto it = lights.cbegin(); it != lights.cend(); ++it) {
const SectorLight &l = it.value();
QPointF pos(ll2xy(it.key()));
for (int i = 0; i < lights.size(); i++) {
const SectorLight &l = lights.at(i);
QPointF pos(ll2xy(l.pos));
QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range));
double a1 = -(l.end + 90);
double a2 = -(l.start + 90);
@ -262,45 +257,49 @@ void RasterTile::drawSectorLights(QPainter *painter,
}
}
void RasterTile::processPoints(const QList<Data::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
QMultiMap<Coordinates, SectorLight> &sectorLights, bool overZoom) const
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<SectorLight> &sectorLights)
{
QMap<Coordinates, Style::Color> lights;
QSet<Coordinates> sigs;
LightMap lightsMap;
SignalSet signalsSet;
QSet<Coordinates> slMap;
int i;
std::sort(points.begin(), points.end());
/* Lights & Signals */
for (i = 0; i < points.size(); i++) {
const Data::Point &point = points.at(i);
const MapData::Point &point = points.at(i);
if (point.type()>>16 == LIGHTS) {
const Data::Attributes &attr = point.attributes();
const MapData::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.insert(point.pos(), SectorLight(color,
sectorLights.append(SectorLight(point.pos(), color,
attr.value(LITVIS).toUInt(), range,
attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble()));
slMap.insert(point.pos());
} else
lights.insert(point.pos(), color);
lightsMap.insert(point.pos(), color);
} else if (point.type()>>16 == FOGSIG)
sigs.insert(point.pos());
signalsSet.insert(point.pos());
else
break;
}
/* Everything else */
for ( ; i < points.size(); i++) {
const Data::Point &point = points.at(i);
const MapData::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 = (overZoom || showLabel(img, point.type()))
const QFont *fnt = showLabel(img, _zoomRange, _zoom, point.type())
? _style->font(style.textFontSize()) : 0;
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
@ -314,25 +313,25 @@ void RasterTile::processPoints(const QList<Data::Point> &points,
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
color, hColor, 0, 2, rotate);
if (item->isValid() && (sectorLights.contains(point.pos())
if (item->isValid() && (slMap.contains(point.pos())
|| (point.polygon() && img) || !item->collides(textItems))) {
textItems.append(item);
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(),
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(),
0, 0, _style->signal(), 0, 0, 0, 0));
} else
delete item;
}
}
void RasterTile::processLines(const QList<Data::Line> &lines,
QList<TextItem*> &textItems) const
void RasterTile::processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems)
{
for (int i = 0; i < lines.size(); i++) {
const Data::Line &line = lines.at(i);
const MapData::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (style.img().isNull() && style.pen() == Qt::NoPen)
@ -352,46 +351,11 @@ void RasterTile::processLines(const QList<Data::Line> &lines,
}
}
void RasterTile::drawLevels(QPainter *painter, const QList<Level> &levels)
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
QList<MapData::Line> &lines, QList<MapData::Point> &points)
{
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()),
@ -404,41 +368,50 @@ QList<RasterTile::Level> RasterTile::fetchLevels()
_transform.img2proj(pointRect.bottomRight()));
RectC pointRectC(pointRectD.toRectC(_proj, 20));
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;
if (_map) {
_map->lines(polyRectC, &lines);
_map->polygons(polyRectC, &polygons);
_map->points(pointRectC, &points);
} else {
_atlas->polys(polyRectC, &polygons, &lines);
_atlas->points(pointRectC, &points);
}
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());
drawLevels(&painter, levels);
drawPolygons(&painter, polygons);
drawLines(&painter, lines);
drawArrows(&painter, points);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
qDeleteAll(lights);
//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 "data.h"
#include "mapdata.h"
#include "style.h"
#include "atlasdata.h"
@ -17,17 +17,14 @@ class RasterTile
{
public:
RasterTile(const Projection &proj, const Transform &transform,
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);
}
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) {}
RasterTile(const Projection &proj, const Transform &transform,
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),
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),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
int zoom() const {return _zoom;}
@ -39,10 +36,11 @@ public:
private:
struct SectorLight
{
SectorLight(Style::Color color, uint visibility, double range,
double start, double end) : color(color), visibility(visibility),
range(range), start(start), end(end) {}
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) {}
Coordinates pos;
Style::Color color;
uint visibility;
double range;
@ -50,16 +48,11 @@ private:
double end;
};
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();}
};
typedef QMap<Coordinates, Style::Color> LightMap;
typedef QSet<Coordinates> SignalSet;
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;
@ -67,26 +60,25 @@ 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(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 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 drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
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;
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights) const;
static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context);
Projection _proj;
Transform _transform;
const Style *_style;
QList<Data *> _data;
const MapData *_map;
AtlasData *_atlas;
int _zoom;
Range _zoomRange;
QRect _rect;

View File

@ -27,6 +27,7 @@ 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)),
@ -140,7 +141,6 @@ 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(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(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)
<< 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,8 +180,7 @@ 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, 0) << SUBTYPE(MARKUL, 3)
<< TYPE(CONZNE);
<< TYPE(I_TRNBSN) << SUBTYPE(MARKUL, 3) << TYPE(CONZNE);
}
void Style::lineStyle(qreal ratio)
@ -394,8 +393,6 @@ 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);
@ -485,7 +482,6 @@ 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);
@ -545,7 +541,6 @@ const QImage *Style::light(Color color) const
case Green:
return &_lightGreen;
case White:
return &_lightWhite;
case Yellow:
case Amber:
case Orange:
@ -563,7 +558,6 @@ 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, _lightWhite, _signal;
QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
QPoint _lightOffset, _signalOffset;
};

View File

@ -133,7 +133,9 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, quint32 size,
bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const
{
quint32 flags1, flags2, unused;
quint16 flags1;
quint8 flags2;
quint32 unused;
if (!(size >= 3 && readUInt16(hdl, flags1) && readUInt8(hdl, flags2)))
return false;

View File

@ -151,7 +151,8 @@ 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());
if (!hdr.key().compare("User-Agent", Qt::CaseInsensitive))
// QByteArray::compare() not available in Qt < 5.12
if (!QString(hdr.key()).compare("User-Agent", Qt::CaseInsensitive))
userAgent = true;
}
if (!userAgent)

View File

@ -12,14 +12,6 @@ using namespace ENC;
#define EPSILON 1e-6
#define TILE_SIZE 512
constexpr quint32 CATD = ISO8211::NAME("CATD");
constexpr quint32 IMPL = ISO8211::NAME("IMPL");
constexpr quint32 F1LE = ISO8211::NAME("FILE");
constexpr quint32 SLAT = ISO8211::NAME("SLAT");
constexpr quint32 WLON = ISO8211::NAME("WLON");
constexpr quint32 NLAT = ISO8211::NAME("NLAT");
constexpr quint32 ELON = ISO8211::NAME("ELON");
Range ENCAtlas::zooms(IntendedUsage usage)
{
switch (usage) {
@ -68,34 +60,35 @@ bool ENCAtlas::processRecord(const ISO8211::Record &record, QByteArray &file,
return false;
const ENC::ISO8211::Field &f = record.at(1);
const QByteArray &ba = f.tag();
if (f.tag() == CATD) {
QByteArray impl;
if (ba == "CATD") {
QByteArray FILE, IMPL;
if (!f.subfield(IMPL, &impl))
if (!f.subfield("IMPL", &IMPL))
return false;
if (!f.subfield(F1LE, &file))
if (!f.subfield("FILE", &FILE))
return false;
if (impl == "BIN" && file.endsWith("000")) {
QByteArray slat, wlon, nlat, elon;
if (IMPL == "BIN" && FILE.endsWith("000")) {
QByteArray SLAT, WLON, NLAT, ELON;
if (!f.subfield(SLAT, &slat))
if (!f.subfield("SLAT", &SLAT))
return false;
if (!f.subfield(WLON, &wlon))
if (!f.subfield("WLON", &WLON))
return false;
if (!f.subfield(NLAT, &nlat))
if (!f.subfield("NLAT", &NLAT))
return false;
if (!f.subfield(ELON, &elon))
if (!f.subfield("ELON", &ELON))
return false;
bool ok1, ok2, ok3, ok4;
bounds = RectC(Coordinates(wlon.toDouble(&ok1), nlat.toDouble(&ok2)),
Coordinates(elon.toDouble(&ok3), slat.toDouble(&ok4)));
bounds = RectC(Coordinates(WLON.toDouble(&ok1), NLAT.toDouble(&ok2)),
Coordinates(ELON.toDouble(&ok3), SLAT.toDouble(&ok4)));
if (!(ok1 && ok2 && ok3 && ok4))
return false;
file.replace('\\', '/');
file = FILE.replace('\\', '/');
return true;
}
@ -161,7 +154,7 @@ ENCAtlas::ENCAtlas(const QString &fileName, QObject *parent)
_zoom = zooms(_usage).min();
updateTransform();
_cache.setMaxCost(16);
_cache.setMaxCost(10);
_valid = true;
}
@ -352,21 +345,9 @@ 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)
{
QList<Data*> data(levels());
AtlasData *data = _data.value(_usage);
Range zr(zooms(_usage));
QPointF tl(floor(rect.left() / TILE_SIZE) * TILE_SIZE,
floor(rect.top() / TILE_SIZE) * TILE_SIZE);

View File

@ -74,7 +74,6 @@ 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);

View File

@ -15,14 +15,6 @@ using namespace ENC;
#define EPSILON 1e-6
#define TILE_SIZE 512
constexpr quint32 SG2D = ISO8211::NAME("SG2D");
constexpr quint32 SG3D = ISO8211::NAME("SG3D");
constexpr quint32 VRID = ISO8211::NAME("VRID");
constexpr quint32 DSID = ISO8211::NAME("DSID");
constexpr quint32 DSNM = ISO8211::NAME("DSNM");
constexpr quint32 DSPM = ISO8211::NAME("DSPM");
constexpr quint32 COMF = ISO8211::NAME("COMF");
static Range zooms(const RectC &bounds)
{
double size = qMin(bounds.width(), bounds.height());
@ -65,9 +57,9 @@ static const ISO8211::Field *SGXD(const ISO8211::Record &r)
{
const ISO8211::Field *f;
if ((f = ISO8211::field(r, SG2D)))
if ((f = ISO8211::field(r, "SG2D")))
return f;
else if ((f = ISO8211::field(r, SG3D)))
else if ((f = ISO8211::field(r, "SG3D")))
return f;
else
return 0;
@ -105,21 +97,23 @@ bool ENCMap::bounds(const QVector<ISO8211::Record> &gv, Rect &b)
}
bool ENCMap::processRecord(const ISO8211::Record &record,
QVector<ISO8211::Record> &rv, uint &comf, QByteArray &dsnm)
QVector<ISO8211::Record> &rv, uint &COMF, QString &name)
{
if (record.size() < 2)
return false;
const ISO8211::Field &f = record.at(1);
quint32 tag = f.tag();
const QByteArray &ba = f.tag();
if (tag == VRID) {
if (ba == "VRID") {
rv.append(record);
} else if (tag == DSID) {
if (!f.subfield(DSNM, &dsnm))
} else if (ba == "DSID") {
QByteArray DSNM;
if (!f.subfield("DSNM", &DSNM))
return false;
} else if (tag == DSPM) {
if (!f.subfield(COMF, &comf))
name = DSNM;
} else if (ba == "DSPM") {
if (!f.subfield("COMF", &COMF))
return false;
}
@ -133,15 +127,14 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent)
QVector<ISO8211::Record> gv;
ISO8211 ddf(fileName);
ISO8211::Record record;
uint comf = 1;
QByteArray dsnm;
uint COMF = 1;
if (!ddf.readDDR()) {
_errorString = ddf.errorString();
return;
}
while (ddf.readRecord(record)) {
if (!processRecord(record, gv, comf, dsnm)) {
if (!processRecord(record, gv, COMF, _name)) {
_errorString = "Invalid S-57 record";
return;
}
@ -151,15 +144,13 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent)
return;
}
_name = dsnm;
Rect b;
if (!bounds(gv, b)) {
_errorString = "Error fetching geometries bounds";
return;
}
Coordinates tl(b.minX() / (double)comf, b.maxY() / (double)comf);
Coordinates br(b.maxX() / (double)comf, b.minY() / (double)comf);
Coordinates tl(b.minX() / (double)COMF, b.maxY() / (double)COMF);
Coordinates br(b.maxX() / (double)COMF, b.minY() / (double)COMF);
_llBounds = RectC(tl, br);
if (!_llBounds.isValid()) {
_errorString = "Invalid geometries bounds";
@ -347,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));
}

View File

@ -97,7 +97,7 @@ private:
static bool bounds(const ENC::ISO8211::Record &record, Rect &rect);
static bool bounds(const QVector<ENC::ISO8211::Record> &gv, Rect &b);
static bool processRecord(const ENC::ISO8211::Record &record,
QVector<ENC::ISO8211::Record> &rv, uint &comf, QByteArray &dsnm);
QVector<ENC::ISO8211::Record> &rv, uint &COMF, QString &name);
QString _name;
ENC::MapData *_data;

View File

@ -188,7 +188,7 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
if (l.ti) {
limit = (l.ti->key() == ID_ELE || l.ti->key() == ID_REF
|| (!l.si && l.ti->shield()));
if (limit && l.lbl && set.contains(*l.lbl))
if (limit && set.contains(*l.lbl))
continue;
}
@ -214,7 +214,7 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
color, hColor, rotate);
if (item->isValid() && !item->collides(textItems)) {
textItems.append(item);
if (limit && l.lbl)
if (limit)
set.insert(*l.lbl);
} else {
delete item;

View File

@ -116,15 +116,13 @@ QSet<QString> Style::Menu::cats() const
}
Style::Rule::Filter::Filter(const MapData &data, const QList<QByteArray> &keys,
const QList<QByteArray> &vals) : _neg(false), _excl(false)
const QList<QByteArray> &vals) : _neg(false)
{
_keys = keyList(data, keys);
QList<QByteArray> vc(vals);
if (vc.removeAll("~"))
_neg = true;
if (vc.removeAll("-"))
_excl = true;
_vals = valList(vc);
}

View File

@ -38,7 +38,7 @@ public:
class Filter {
public:
Filter() : _neg(false), _excl(false) {}
Filter() : _neg(false) {}
Filter(const MapData &data, const QList<QByteArray> &keys,
const QList<QByteArray> &vals);
@ -47,15 +47,14 @@ public:
if (_neg) {
if (!keyMatches(tags))
return true;
return valueMatches(tags) ^ _excl;
return valueMatches(tags);
} else
return (keyMatches(tags) && (valueMatches(tags) ^ _excl));
return (keyMatches(tags) && valueMatches(tags));
}
bool isTautology() const
{
return (!_neg && !_excl && _keys.contains(0u)
&& _vals.contains(QByteArray()));
return (!_neg && _keys.contains(0u) && _vals.contains(QByteArray()));
}
private:
@ -87,7 +86,7 @@ public:
QList<unsigned> _keys;
QList<QByteArray> _vals;
bool _neg, _excl;
bool _neg;
};
void setType(Type type)