Compare commits
126 Commits
Author | SHA1 | Date | |
---|---|---|---|
372f2966bb | |||
1aa0fa4be4 | |||
f4e19d0917 | |||
91376fd609 | |||
92b2fbaf04 | |||
a21096a0a9 | |||
920cf03d1b | |||
72155beb6b | |||
|
88acc78e1c | ||
|
1583794329 | ||
|
beb2f6d70c | ||
|
afd3a09f50 | ||
|
2a247a2a38 | ||
44af6eea4d | |||
40c396a8c8 | |||
5018aecb42 | |||
a2d56236b6 | |||
b20a6cd479 | |||
7bbf6fba97 | |||
d2ac9f2ee6 | |||
|
fa344e94e4 | ||
|
dd53293229 | ||
355f451e5c | |||
0b61fb0470 | |||
af18c98a03 | |||
e9a8112196 | |||
|
bca335d4b2 | ||
|
f3b1fa8eb7 | ||
|
fac377e746 | ||
7184c691d3 | |||
381ab1516d | |||
cf84680bc6 | |||
|
74e322860f | ||
38abffda17 | |||
|
304d4f770e | ||
|
739564955e | ||
|
4e45cf6d40 | ||
|
644e14947d | ||
c171e8088c | |||
|
431357b08d | ||
af03a85fdb | |||
|
003bdd8814 | ||
91c0e2a83d | |||
496a474bd2 | |||
f1b7d57027 | |||
2e4e702640 | |||
9d3cdbbd42 | |||
0e329f4b22 | |||
2041cc7ff5 | |||
8169015f70 | |||
28f55b7e0d | |||
912a00c80e | |||
8de6bbe4fb | |||
f34d6b0540 | |||
|
2eb527f2f3 | ||
94785ee2ec | |||
a2f1ef7572 | |||
7731cfaa4f | |||
a9572d05fe | |||
fdd5d46c03 | |||
39ed798a48 | |||
64b29f8aac | |||
8ea84c5c86 | |||
db6e891c30 | |||
d91acb66f2 | |||
|
3804e8ca7c | ||
2595926b7f | |||
|
0d38603332 | ||
66693cd5c9 | |||
4eec328dbf | |||
|
4121c99e56 | ||
a3f1d25d63 | |||
6c80d89c89 | |||
7cf957a48d | |||
792ede2a96 | |||
|
cee53eab90 | ||
|
1f81d867d5 | ||
|
39edcd4a1e | ||
2808768f13 | |||
451782ce20 | |||
5d1ba90f09 | |||
60fd7fb7c3 | |||
7249c85a02 | |||
099ce0ad6c | |||
b1aa32d23b | |||
1f31a5d6c5 | |||
044770bc84 | |||
c5f51e935e | |||
17ad10ba23 | |||
f5f27c0212 | |||
7e1bbbbd6a | |||
71a757983f | |||
cc7209ad70 | |||
ba49497608 | |||
48404ea43b | |||
b9fb9eece3 | |||
0cac0369aa | |||
cdf198ec1d | |||
0896b54831 | |||
9f1808274f | |||
5d2465cffc | |||
2ab7bff3f8 | |||
060cfb574d | |||
5c178b4088 | |||
2f4a7f8053 | |||
5f1838ea30 | |||
bdf75169c5 | |||
|
9295f8f4a9 | ||
3fc8e69ebb | |||
4438bc8d52 | |||
|
f9e99fcc73 | ||
|
f494543e54 | ||
|
70936cafe3 | ||
|
74781d6462 | ||
|
466e8f2909 | ||
|
1c9dd610d5 | ||
|
538ec4f71b | ||
|
9bb56032b0 | ||
|
c3e76e1d3d | ||
|
766000458d | ||
|
0d029636be | ||
|
89b4bc56e4 | ||
|
08d09d038e | ||
|
02c236a49e | ||
|
f67c262292 | ||
|
7cfd62ca97 |
@ -1,4 +1,4 @@
|
||||
version: 13.35.{build}
|
||||
version: 13.39.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
@ -8,6 +8,7 @@ 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
|
||||
@ -17,14 +18,14 @@ environment:
|
||||
|
||||
install:
|
||||
- cmd: |-
|
||||
set PATH=%QTDIR%\bin;%NSISDIR%;%PATH%
|
||||
set PATH=%QTDIR%\bin;%NSISDIR%;%JOMDIR%;%PATH%
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
|
||||
build_script:
|
||||
- cmd: |-
|
||||
lrelease gpxsee.pro
|
||||
qmake gpxsee.pro
|
||||
nmake release
|
||||
jom release
|
||||
|
||||
md installer
|
||||
copy release\GPXSee.exe installer
|
||||
|
2
.github/workflows/android.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
- name: Configure build
|
||||
run: qmake gpxsee.pro OPENSSL_PATH=android_openssl
|
||||
- name: Build project
|
||||
run: make -j2 apk
|
||||
run: make -j4 apk
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
9
.github/workflows/linux.yml
vendored
@ -8,7 +8,10 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
name: GPXSee
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
config: ['release', 'debug']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@ -19,6 +22,6 @@ jobs:
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
- name: Configure build
|
||||
run: qmake gpxsee.pro
|
||||
run: qmake CONFIG+=${{ matrix.config }} gpxsee.pro
|
||||
- name: Build project
|
||||
run: make -j2
|
||||
run: make -j4
|
||||
|
2
.github/workflows/osx.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: '6.8.1'
|
||||
version: '6.8.2'
|
||||
modules: qtpositioning qtserialport qtimageformats
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
|
@ -5,7 +5,8 @@ GPS log file formats.
|
||||
## Features
|
||||
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON,
|
||||
OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV, TomTom OV2&ITN, ONmove OMD/GHP,
|
||||
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG files.
|
||||
TwoNav (TRK, RTE, WPT), GPSDump WPT, Velocitek VTK, Vakaros VKX, 70mai GPS logs
|
||||
and geotagged JPEG files.
|
||||
* Opens geo URIs (RFC 5870).
|
||||
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS,
|
||||
QuadTiles).
|
||||
@ -29,8 +30,8 @@ GPS log file formats.
|
||||
|
||||
## Build
|
||||
Build requirements:
|
||||
* Qt5 >= 5.11 or Qt6 >= 6.2 (Android builds require Qt6)
|
||||
* C++11 or newer compiler (tested: msvc2019, gcc 7.5.0, clang/Apple LLVM version
|
||||
* Qt5 >= 5.15 or Qt6 >= 6.2 (Android builds require Qt6)
|
||||
* C++11 or newer compiler (tested: msvc2022, gcc 11, clang/Apple LLVM version
|
||||
10.0.0)
|
||||
|
||||
Build steps:
|
||||
|
@ -214,10 +214,11 @@
|
||||
</rule>
|
||||
|
||||
<!-- Buildings -->
|
||||
<rule e="way" k="building" v="*">
|
||||
<rule e="way" k="building" v="-|civic|office|cathedral|church|basilica">
|
||||
<area fill="#dbd0b6" stroke="#cdccc4" stroke-width="0.1"/>
|
||||
</rule>
|
||||
<rule e="way" k="building" v="civic">
|
||||
|
||||
<rule e="way" k="building" v="civic|office">
|
||||
<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"/>
|
||||
@ -403,7 +404,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/arrow.svg" symbol-width="16" symbol-height="8"/>
|
||||
<lineSymbol priority="-50" src=":/symbols/oneway.svg" symbol-width="16" symbol-height="8"/>
|
||||
</rule>
|
||||
</rule>
|
||||
</rule>
|
||||
@ -428,6 +429,12 @@
|
||||
<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">
|
||||
|
16
gpxsee.pro
@ -3,8 +3,7 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 13.35
|
||||
|
||||
VERSION = 13.39
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -118,7 +117,11 @@ HEADERS += src/common/config.h \
|
||||
src/data/gpsdumpparser.h \
|
||||
src/data/style.h \
|
||||
src/data/twonavparser.h \
|
||||
src/map/IMG/lights.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 \
|
||||
src/map/ENC/attributes.h \
|
||||
@ -344,6 +347,9 @@ 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 \
|
||||
@ -559,7 +565,9 @@ win32 {
|
||||
icons/formats/trk.ico \
|
||||
icons/formats/gemf.ico \
|
||||
icons/formats/000.ico \
|
||||
icons/formats/031.ico
|
||||
icons/formats/031.ico \
|
||||
icons/formats/vtk.ico \
|
||||
icons/formats/vkx.ico
|
||||
DEFINES += _USE_MATH_DEFINES \
|
||||
NOGDI
|
||||
}
|
||||
|
@ -216,6 +216,7 @@
|
||||
<file alias="tanker-anchorage.png">icons/map/marine/tanker-anchorage.png</file>
|
||||
<file alias="nature-reserve-line.png">icons/map/marine/nature-reserve-line.png</file>
|
||||
<file alias="sanctuary-line.png">icons/map/marine/sanctuary-line.png</file>
|
||||
<file alias="fishing-farm.png">icons/map/marine/fishing-farm.png</file>
|
||||
</qresource>
|
||||
|
||||
<!-- Patterns (Mapsforge) -->
|
||||
|
@ -32,3 +32,5 @@ trk:#cccccc
|
||||
gemf:#147085
|
||||
000:#000000
|
||||
031:#000000
|
||||
vtk:#632433
|
||||
vkx:#00ccff
|
||||
|
BIN
icons/formats/vkx.icns
Normal file
BIN
icons/formats/vkx.ico
Normal file
After Width: | Height: | Size: 331 KiB |
BIN
icons/formats/vtk.icns
Normal file
BIN
icons/formats/vtk.ico
Normal file
After Width: | Height: | Size: 331 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 202 B |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 215 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 189 B |
BIN
icons/map/marine/fishing-farm.png
Normal file
After Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 238 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 220 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 330 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 401 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 261 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 217 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 243 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 275 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 266 B |
@ -15,8 +15,8 @@
|
||||
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SIGMA SLF, Suunto SML, LOC,
|
||||
OziExplorer (PLT, WPT, RTE), GeoJSON, SeeYou CUP,
|
||||
Garmin GPI & CSV, TomTom OV2 & ITN, ONmove OMD/GHP,
|
||||
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG
|
||||
files.</li>
|
||||
TwoNav (TRK, RTE, WPT), GPSDump WPT, Velocitek VTK,
|
||||
Vakaros VKX, 70mai GPS logs and geotagged JPEG files.</li>
|
||||
<li>Opens geo URIs (RFC 5870).</li>
|
||||
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
|
||||
WMS, TMS, QuadTiles).</li>
|
||||
@ -113,6 +113,9 @@
|
||||
<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>
|
||||
|
@ -16,4 +16,4 @@ Icon=gpxsee
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt
|
||||
MimeType=x-scheme-handler/geo;application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.cgtk.gemf;application/vnd.rmaps.sqlite;application/vnd.osmdroid.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn;application/vnd.esri.wld;application/vnd.onmove.omd;application/vnd.onmove.ghp;application/vnd.memory-map.qct;application/vnd.twonav.trk;application/vnd.twonav.rte;application/vnd.twonav.wpt;application/vnd.orux.map+xml;application/vnd.iho.s57-data;application/vnd.iho.s57-catalogue;application/vnd.gpsdump.wpt;application/vnd.gpstuner.gmi
|
||||
MimeType=x-scheme-handler/geo;application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.cgtk.gemf;application/vnd.rmaps.sqlite;application/vnd.osmdroid.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn;application/vnd.esri.wld;application/vnd.onmove.omd;application/vnd.onmove.ghp;application/vnd.memory-map.qct;application/vnd.twonav.trk;application/vnd.twonav.rte;application/vnd.twonav.wpt;application/vnd.orux.map+xml;application/vnd.iho.s57-data;application/vnd.iho.s57-catalogue;application/vnd.gpsdump.wpt;application/vnd.gpstuner.gmi;application/vnd.70mai.txt;application/vnd.velocitek.vtk;application/vnd.vakaros.vkx
|
||||
|
@ -188,6 +188,33 @@
|
||||
<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">
|
||||
|
@ -736,6 +736,52 @@
|
||||
<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>
|
||||
@ -1683,6 +1729,8 @@
|
||||
<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>
|
||||
@ -1704,6 +1752,8 @@
|
||||
<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>
|
||||
@ -1718,6 +1768,73 @@
|
||||
<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>
|
||||
|
@ -49,7 +49,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "13.35"
|
||||
!define VERSION "13.39"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -204,13 +204,15 @@ 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 "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 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 URI_ASSOCIATION_ADD "geo"
|
||||
|
||||
@ -265,6 +267,9 @@ 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)'
|
||||
|
||||
@ -439,6 +444,8 @@ 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"
|
||||
|
||||
@ -492,6 +499,9 @@ 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)'
|
||||
|
@ -73,9 +73,7 @@ App::App(int &argc, char **argv) : QApplication(argc, argv)
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_MAC)
|
||||
QIcon::setThemeName(APP_NAME);
|
||||
#endif // Q_OS_WIN32 || Q_OS_MAC
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
|
||||
QIcon::setFallbackThemeName(APP_NAME);
|
||||
#endif // QT 5.12
|
||||
|
||||
_gui = new GUI();
|
||||
|
||||
|
@ -25,15 +25,6 @@
|
||||
#define IW(item) ((item)->boundingRect().width())
|
||||
#define IH(item) ((item)->boundingRect().height())
|
||||
|
||||
static inline QPoint POS(QWheelEvent *e)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
return e->pos();
|
||||
#else // QT 5.15
|
||||
return e->position().toPoint();
|
||||
#endif // QT 5.15
|
||||
}
|
||||
|
||||
static inline QPoint POS(QMouseEvent *e)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
@ -393,7 +384,7 @@ void GraphView::wheelEvent(QWheelEvent *e)
|
||||
return;
|
||||
_angleDelta = _angleDelta % (15 * 8);
|
||||
|
||||
QPointF pos = mapToScene(POS(e));
|
||||
QPointF pos = mapToScene(e->position().toPoint());
|
||||
QRectF gr(_grid->boundingRect());
|
||||
QPointF r(pos.x() / gr.width(), pos.y() / gr.height());
|
||||
|
||||
@ -404,7 +395,8 @@ void GraphView::wheelEvent(QWheelEvent *e)
|
||||
QPointF npos(mapFromScene(QPointF(r.x() * ngr.width(),
|
||||
r.y() * ngr.height())));
|
||||
QScrollBar *sb = horizontalScrollBar();
|
||||
sb->setSliderPosition(sb->sliderPosition() + npos.x() - POS(e).x());
|
||||
sb->setSliderPosition(sb->sliderPosition() + npos.x()
|
||||
- e->position().toPoint().x());
|
||||
|
||||
QGraphicsView::wheelEvent(e);
|
||||
}
|
||||
|
@ -1193,10 +1193,12 @@ void GUI::loadData(const Data &data)
|
||||
_time += track.time();
|
||||
_movingTime += track.movingTime();
|
||||
const QDateTime date = track.date().toTimeZone(_options.timeZone.zone());
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
_dateRange.second = date;
|
||||
if (date.isValid()) {
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
_dateRange.second = date;
|
||||
}
|
||||
}
|
||||
_trackCount += data.tracks().count();
|
||||
|
||||
@ -2498,12 +2500,8 @@ QGeoPositionInfoSource *GUI::positionSource(const Options &options)
|
||||
{
|
||||
QGeoPositionInfoSource *source;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
source = QGeoPositionInfoSource::createSource(options.plugin, this);
|
||||
#else // QT 5.14
|
||||
source = QGeoPositionInfoSource::createSource(options.plugin,
|
||||
options.pluginParams.value(options.plugin), this);
|
||||
#endif // QT 5.14
|
||||
if (source)
|
||||
source->setPreferredPositioningMethods(
|
||||
QGeoPositionInfoSource::SatellitePositioningMethods);
|
||||
|
@ -638,11 +638,7 @@ void MapView::wheelEvent(QWheelEvent *event)
|
||||
return;
|
||||
_wheelDelta = _wheelDelta % (15 * 8);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
zoom((delta > 0) ? 1 : -1, event->pos(), shift);
|
||||
#else // QT 5.15
|
||||
zoom((delta > 0) ? 1 : -1, event->position().toPoint(), shift);
|
||||
#endif // QT 5.15
|
||||
|
||||
/* Do not call QGraphicsView::wheelEvent() here as this would shift the
|
||||
view ! */
|
||||
@ -1258,7 +1254,7 @@ void MapView::drawHillShading(bool draw)
|
||||
setMap(_map);
|
||||
}
|
||||
|
||||
void MapView::selectLayers(Layers layers)
|
||||
void MapView::selectLayers(MapView::Layers layers)
|
||||
{
|
||||
_layers = layers;
|
||||
|
||||
|
@ -136,7 +136,7 @@ public slots:
|
||||
void showMotionInfo(bool show);
|
||||
void useStyles(bool use);
|
||||
void drawHillShading(bool draw);
|
||||
void selectLayers(Layers layers);
|
||||
void selectLayers(MapView::Layers layers);
|
||||
|
||||
private slots:
|
||||
void updatePOI();
|
||||
|
@ -676,21 +676,17 @@ QWidget *OptionsDialog::createPositionPage()
|
||||
_positionPlugin = new QComboBox();
|
||||
_positionPlugin->addItems(plugins);
|
||||
_positionPlugin->setCurrentIndex(_positionPlugin->findText(_options.plugin));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
_pluginParameters = new PluginParameters(_positionPlugin->currentText(),
|
||||
_options.pluginParams);
|
||||
connect(_positionPlugin, &QComboBox::currentTextChanged, _pluginParameters,
|
||||
&PluginParameters::setPlugin);
|
||||
#endif // QT 5.14
|
||||
|
||||
QFormLayout *pluginLayout = new QFormLayout();
|
||||
pluginLayout->addRow(tr("Plugin:"), _positionPlugin);
|
||||
|
||||
QVBoxLayout *sourceLayout = new QVBoxLayout();
|
||||
sourceLayout->addLayout(pluginLayout);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
sourceLayout->addWidget(_pluginParameters);
|
||||
#endif // QT 5.14
|
||||
sourceLayout->addStretch();
|
||||
|
||||
QWidget *sourceTab = new QWidget();
|
||||
@ -1009,9 +1005,7 @@ void OptionsDialog::accept()
|
||||
_options.hillshadingZFactor = _hillshadingZFactor->value();
|
||||
|
||||
_options.plugin = _positionPlugin->currentText();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
_options.pluginParams = _pluginParameters->parameters();
|
||||
#endif // QT 5.14
|
||||
|
||||
_options.useOpenGL = _useOpenGL->isChecked();
|
||||
_options.enableHTTP2 = _enableHTTP2->isChecked();
|
||||
|
@ -193,9 +193,7 @@ private:
|
||||
QDoubleSpinBox *_hillshadingZFactor;
|
||||
// Position
|
||||
QComboBox *_positionPlugin;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
PluginParameters *_pluginParameters;
|
||||
#endif // QT 5.14
|
||||
// System
|
||||
QSpinBox *_pixmapCache;
|
||||
QSpinBox *_demCache;
|
||||
|
@ -10,13 +10,6 @@
|
||||
#include "markeritem.h"
|
||||
#include "pathitem.h"
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
#define INTERSECTS intersect
|
||||
#else // QT 5.15
|
||||
#define INTERSECTS intersects
|
||||
#endif // QT 5.15
|
||||
|
||||
#define GEOGRAPHICAL_MILE 1855.3248
|
||||
|
||||
Units PathItem::_units = Metric;
|
||||
@ -79,14 +72,14 @@ bool PathItem::addSegment(const Coordinates &c1, const Coordinates &c2)
|
||||
QLineF l(QPointF(c1.lon(), c1.lat()), QPointF(c2.lon() + 360,
|
||||
c2.lat()));
|
||||
QLineF dl(QPointF(180, -90), QPointF(180, 90));
|
||||
l.INTERSECTS(dl, &p);
|
||||
l.intersects(dl, &p);
|
||||
_painterPath.lineTo(_map->ll2xy(Coordinates(180, p.y())));
|
||||
_painterPath.moveTo(_map->ll2xy(Coordinates(-180, p.y())));
|
||||
} else {
|
||||
QLineF l(QPointF(c1.lon(), c1.lat()), QPointF(c2.lon() - 360,
|
||||
c2.lat()));
|
||||
QLineF dl(QPointF(-180, -90), QPointF(-180, 90));
|
||||
l.INTERSECTS(dl, &p);
|
||||
l.intersects(dl, &p);
|
||||
_painterPath.lineTo(_map->ll2xy(Coordinates(-180, p.y())));
|
||||
_painterPath.moveTo(_map->ll2xy(Coordinates(180, p.y())));
|
||||
}
|
||||
|
@ -9,9 +9,6 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QApplication>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
#include <QDesktopWidget>
|
||||
#endif // QT 5.15
|
||||
#include "tooltip.h"
|
||||
#include "thumbnail.h"
|
||||
#include "flowlayout.h"
|
||||
@ -184,11 +181,7 @@ bool PopupFrame::eventFilter(QObject *o, QEvent *ev)
|
||||
|
||||
void PopupFrame::place(const QPoint &pos, QWidget *w)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
QRect screen = QApplication::desktop()->screenGeometry(w);
|
||||
#else // QT 5.15
|
||||
QRect screen = w->screen()->geometry();
|
||||
#endif // QT 5.15
|
||||
QPoint p(pos.x() + 2, pos.y() + 16);
|
||||
|
||||
if (p.x() + width() > screen.x() + screen.width())
|
||||
|
@ -64,6 +64,7 @@ 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;
|
||||
@ -117,6 +118,16 @@ 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);
|
||||
@ -124,6 +135,7 @@ void SpeedGraph::clear()
|
||||
|
||||
_avg.clear();
|
||||
_mavg.clear();
|
||||
_max.clear();
|
||||
|
||||
GraphTab::clear();
|
||||
}
|
||||
|
@ -26,12 +26,13 @@ private:
|
||||
GraphItem *loadGraph(const Graph &graph, const Track &track,
|
||||
const QColor &color, bool primary);
|
||||
qreal avg() const;
|
||||
qreal max() const {return bounds().bottom();}
|
||||
qreal max() const;
|
||||
void setYUnits();
|
||||
void setInfo();
|
||||
|
||||
QVector<QPointF> _avg;
|
||||
QVector<QPointF> _mavg;
|
||||
QVector<QPointF> _max;
|
||||
|
||||
Units _units;
|
||||
TimeType _timeType;
|
||||
|
@ -7,15 +7,18 @@ RFC 4180 parser with the following enchancements:
|
||||
- allows LF line ends in addition to CRLF line ends
|
||||
*/
|
||||
|
||||
bool CSV::readEntry(QByteArrayList &list)
|
||||
bool CSV::readEntry(QByteArrayList &list, int limit)
|
||||
{
|
||||
int state = 0;
|
||||
int state = 0, len = 0;
|
||||
char c;
|
||||
QByteArray field;
|
||||
|
||||
list.clear();
|
||||
|
||||
while (_device->getChar(&c)) {
|
||||
if (limit && ++len > limit)
|
||||
return false;
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (c == '\r')
|
||||
|
@ -9,7 +9,7 @@ public:
|
||||
CSV(QIODevice *device, char delimiter = ',')
|
||||
: _device(device), _delimiter(delimiter), _line(1) {}
|
||||
|
||||
bool readEntry(QByteArrayList &list);
|
||||
bool readEntry(QByteArrayList &list, int limit = 4096);
|
||||
bool atEnd() const {return _device->atEnd();}
|
||||
int line() const {return _line;}
|
||||
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
bool intersects(const RectC &r) const
|
||||
{return (right() >= r.left() && bottom() <= r.top() && left() <= r.right()
|
||||
&& top() >= r.bottom());}
|
||||
bool contains(const Coordinates&c) const
|
||||
bool contains(const Coordinates &c) const
|
||||
{return (c.lon() >= left() && c.lon() <= right() && c.lat() <= top()
|
||||
&& c.lat() >= bottom());}
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
|
||||
/// Count the data elements in this container. This is slow as no internal
|
||||
/// counter is maintained.
|
||||
int Count();
|
||||
int Count() const;
|
||||
|
||||
|
||||
/// Iterator is not remove safe.
|
||||
@ -363,7 +363,7 @@ protected:
|
||||
void* a_context) const;
|
||||
void RemoveAllRec(Node* a_node);
|
||||
void Reset();
|
||||
void CountRec(Node* a_node, int& a_count);
|
||||
void CountRec(Node* a_node, int& a_count) const;
|
||||
|
||||
/// Root of tree
|
||||
Node* m_root;
|
||||
@ -473,7 +473,7 @@ int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDI
|
||||
|
||||
|
||||
RTREE_TEMPLATE
|
||||
int RTREE_QUAL::Count()
|
||||
int RTREE_QUAL::Count() const
|
||||
{
|
||||
int count = 0;
|
||||
CountRec(m_root, count);
|
||||
@ -483,7 +483,7 @@ int RTREE_QUAL::Count()
|
||||
|
||||
|
||||
RTREE_TEMPLATE
|
||||
void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
|
||||
void RTREE_QUAL::CountRec(Node* a_node, int& a_count) const
|
||||
{
|
||||
if (a_node->IsInternalNode()) { // not a leaf node
|
||||
for (int index = 0; index < a_node->m_count; ++index)
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "onmoveparsers.h"
|
||||
#include "twonavparser.h"
|
||||
#include "gpsdumpparser.h"
|
||||
#include "txtparser.h"
|
||||
#include "vtkparser.h"
|
||||
#include "vkxparser.h"
|
||||
#include "data.h"
|
||||
|
||||
|
||||
@ -49,6 +52,9 @@ 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()
|
||||
{
|
||||
@ -82,6 +88,9 @@ 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;
|
||||
}
|
||||
@ -241,6 +250,9 @@ 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") + " (*)";
|
||||
|
@ -467,8 +467,7 @@ 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);
|
||||
|
@ -541,7 +541,7 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||
Waypoint w;
|
||||
QMap<QString, PolygonStyle> unused;
|
||||
QMap<QString, LineStyle> unused2;
|
||||
static QRegularExpression re("\\$\\[[^\\]]+\\]");
|
||||
static const QRegularExpression re("\\$\\[[^\\]]+\\]");
|
||||
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("name"))
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
class TCXParser : public Parser
|
||||
{
|
||||
public:
|
||||
|
@ -2,13 +2,6 @@
|
||||
#include "map/gcs.h"
|
||||
#include "twonavparser.h"
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
#define SKIP_EMPTY QString::SkipEmptyParts
|
||||
#else // Qt 5.14
|
||||
#define SKIP_EMPTY Qt::SkipEmptyParts
|
||||
#endif
|
||||
|
||||
static double lon(const QString &str)
|
||||
{
|
||||
QStringList l(str.split(QChar(0xBA)));
|
||||
@ -123,7 +116,8 @@ bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
}}
|
||||
break;
|
||||
case 'T':
|
||||
{QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
|
||||
{QStringList list(codec.toString(line).split(' ',
|
||||
Qt::SkipEmptyParts));
|
||||
if (list.size() < 4) {
|
||||
_errorString = "Parse error";
|
||||
return false;
|
||||
@ -159,7 +153,8 @@ bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
tracks.last().last().append(t);}
|
||||
break;
|
||||
case 'W':
|
||||
{QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
|
||||
{QStringList list(codec.toString(line).split(' ',
|
||||
Qt::SkipEmptyParts));
|
||||
if (list.size() < 5) {
|
||||
_errorString = "Parse error";
|
||||
return false;
|
||||
|
80
src/data/txtparser.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include <QTimeZone>
|
||||
#include "common/csv.h"
|
||||
#include "txtparser.h"
|
||||
|
||||
static Coordinates coordinates(const QByteArrayList &entry)
|
||||
{
|
||||
bool lonOk, latOk;
|
||||
double lon = entry.at(3).toDouble(&lonOk);
|
||||
double lat = entry.at(2).toDouble(&latOk);
|
||||
|
||||
return (lonOk && latOk) ? Coordinates(lon, lat) : Coordinates();
|
||||
}
|
||||
|
||||
bool TXTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
Q_UNUSED(routes);
|
||||
Q_UNUSED(polygons);
|
||||
Q_UNUSED(waypoints);
|
||||
CSV csv(file);
|
||||
QByteArrayList entry;
|
||||
SegmentData *sg = 0;
|
||||
|
||||
_errorLine = 1;
|
||||
_errorString.clear();
|
||||
|
||||
while (!csv.atEnd()) {
|
||||
if (!csv.readEntry(entry)) {
|
||||
_errorString = "CSV parse error";
|
||||
_errorLine = csv.line() - 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.size() == 1) {
|
||||
if (entry.at(0) == "$V02") {
|
||||
tracks.append(TrackData(SegmentData()));
|
||||
sg = &tracks.last().last();
|
||||
} else {
|
||||
_errorString = "Invalid track start marker";
|
||||
_errorLine = csv.line() - 1;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!sg) {
|
||||
_errorString = "Missing start marker";
|
||||
_errorLine = csv.line() - 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.size() == 13 && entry.at(1) == "A") {
|
||||
Coordinates c(coordinates(entry));
|
||||
if (!c.isValid()) {
|
||||
_errorString = "Invalid coordinates";
|
||||
_errorLine = csv.line() - 1;
|
||||
return false;
|
||||
}
|
||||
Trackpoint tp(c);
|
||||
|
||||
bool ok;
|
||||
qulonglong ts = entry.at(0).toULongLong(&ok);
|
||||
if (!ok) {
|
||||
_errorString = "Invalid timestamp";
|
||||
_errorLine = csv.line() - 1;
|
||||
return false;
|
||||
}
|
||||
tp.setTimestamp(QDateTime::fromSecsSinceEpoch(ts,
|
||||
QTimeZone::utc()));
|
||||
|
||||
uint speed = entry.at(5).toULong(&ok);
|
||||
if (ok)
|
||||
tp.setSpeed(speed * 0.01);
|
||||
|
||||
if (c != Coordinates(0, 0))
|
||||
sg->append(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
18
src/data/txtparser.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef TXTPARSER_H
|
||||
#define TXTPARSER_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
class TXTParser : public Parser
|
||||
{
|
||||
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
|
||||
QList<Area> &polygons, QVector<Waypoint> &waypoints);
|
||||
QString errorString() const {return _errorString;}
|
||||
int errorLine() const {return _errorLine;}
|
||||
|
||||
private:
|
||||
QString _errorString;
|
||||
int _errorLine;
|
||||
};
|
||||
|
||||
#endif // TXTPARSER_H
|
151
src/data/vkxparser.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#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;
|
||||
}
|
27
src/data/vkxparser.h
Normal file
@ -0,0 +1,27 @@
|
||||
#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
|
217
src/data/vtkparser.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
#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;
|
||||
}
|
18
src/data/vtkparser.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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
|
@ -39,15 +39,12 @@ bool AtlasData::polyCb(MapEntry *map, void *context)
|
||||
ctx->cacheLock.unlock();
|
||||
|
||||
MapData *data = new MapData(map->path);
|
||||
data->polygons(ctx->rect, ctx->polygons);
|
||||
data->lines(ctx->rect, ctx->lines);
|
||||
data->polys(ctx->rect, ctx->polygons, ctx->lines);
|
||||
|
||||
ctx->cacheLock.lock();
|
||||
ctx->cache.insert(map->path, data);
|
||||
} else {
|
||||
cached->polygons(ctx->rect, ctx->polygons);
|
||||
cached->lines(ctx->rect, ctx->lines);
|
||||
}
|
||||
} else
|
||||
cached->polys(ctx->rect, ctx->polygons, ctx->lines);
|
||||
|
||||
ctx->cacheLock.unlock();
|
||||
map->lock.unlock();
|
||||
|
@ -10,18 +10,18 @@ namespace ENC {
|
||||
|
||||
typedef QCache<QString, MapData> MapCache;
|
||||
|
||||
class AtlasData
|
||||
class AtlasData : public Data
|
||||
{
|
||||
public:
|
||||
AtlasData(MapCache &cache, QMutex &cacheLock)
|
||||
: _cache(cache), _cacheLock(cacheLock) {}
|
||||
~AtlasData();
|
||||
virtual ~AtlasData();
|
||||
|
||||
void addMap(const RectC &bounds, const QString &path);
|
||||
|
||||
void polys(const RectC &rect, QList<MapData::Poly> *polygons,
|
||||
virtual void polys(const RectC &rect, QList<MapData::Poly> *polygons,
|
||||
QList<MapData::Line> *lines);
|
||||
void points(const RectC &rect, QList<MapData::Point> *points);
|
||||
virtual void points(const RectC &rect, QList<MapData::Point> *points);
|
||||
|
||||
private:
|
||||
struct MapEntry {
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#define CATACH 8
|
||||
#define CATBUA 10
|
||||
#define CATCOV 18
|
||||
#define CATDIS 21
|
||||
#define CATHAF 30
|
||||
#define CATLMK 35
|
||||
|
79
src/map/ENC/data.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef ENC_DATA_H
|
||||
#define ENC_DATA_H
|
||||
|
||||
#include "common/rectc.h"
|
||||
#include "common/polygon.h"
|
||||
|
||||
namespace ENC {
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
typedef QMap<uint, QByteArray> Attributes;
|
||||
|
||||
class Poly {
|
||||
public:
|
||||
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
|
||||
|
||||
RectC bounds() const {return _path.boundingRect();}
|
||||
const Polygon &path() const {return _path;}
|
||||
uint type() const {return _type;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
uint HUNI() const {return _HUNI;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
Polygon _path;
|
||||
Attributes _attr;
|
||||
uint _HUNI;
|
||||
};
|
||||
|
||||
class Line {
|
||||
public:
|
||||
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
|
||||
|
||||
RectC bounds() const;
|
||||
const QVector<Coordinates> &path() const {return _path;}
|
||||
uint type() const {return _type;}
|
||||
const QString &label() const {return _label;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
QVector<Coordinates> _path;
|
||||
QString _label;
|
||||
Attributes _attr;
|
||||
};
|
||||
|
||||
class Point {
|
||||
public:
|
||||
Point(uint type, const Coordinates &c, const Attributes &attr,
|
||||
uint HUNI, bool polygon = false);
|
||||
Point(uint type, const Coordinates &s, const QString &label);
|
||||
|
||||
const Coordinates &pos() const {return _pos;}
|
||||
uint type() const {return _type;}
|
||||
const QString &label() const {return _label;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
bool polygon() const {return _polygon;}
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
{return _id < other._id;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
Coordinates _pos;
|
||||
QString _label;
|
||||
quint64 _id;
|
||||
Attributes _attr;
|
||||
bool _polygon;
|
||||
};
|
||||
|
||||
virtual void polys(const RectC &rect, QList<Data::Poly> *polygons,
|
||||
QList<Data::Line> *lines) = 0;
|
||||
virtual void points(const RectC &rect, QList<Data::Point> *points) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ENC_DATA_H
|
@ -1,3 +1,4 @@
|
||||
#include <QtEndian>
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include "common/util.h"
|
||||
@ -5,13 +6,6 @@
|
||||
|
||||
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;
|
||||
@ -29,18 +23,18 @@ struct DR {
|
||||
};
|
||||
|
||||
|
||||
const QVariant *ISO8211::Field::data(const QByteArray &name, int idx) const
|
||||
const QVariant *ISO8211::Field::data(quint32 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(const char *name, int *val, int idx) const
|
||||
bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const
|
||||
{
|
||||
bool ok;
|
||||
|
||||
@ -52,7 +46,7 @@ bool ISO8211::Field::subfield(const char *name, int *val, int idx) const
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const
|
||||
bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const
|
||||
{
|
||||
bool ok;
|
||||
|
||||
@ -64,7 +58,7 @@ bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool ISO8211::Field::subfield(const char *name, QByteArray *val, int idx) const
|
||||
bool ISO8211::Field::subfield(quint32 name, QByteArray *val, int idx) const
|
||||
{
|
||||
const QVariant *v = data(name, idx);
|
||||
if (!v)
|
||||
@ -101,6 +95,7 @@ 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))
|
||||
@ -115,20 +110,19 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
|
||||
if (len < 0 || offset < 0 || lenSize < 0 || posSize < 0 || tagSize < 0)
|
||||
return -1;
|
||||
|
||||
fields.resize((offset - 1 - sizeof(DR)) / (lenSize + posSize + tagSize));
|
||||
fields.resize((offset - 1 - sizeof(ddr)) / (lenSize + posSize + tagSize));
|
||||
fieldLen.resize(lenSize);
|
||||
fieldPos.resize(posSize);
|
||||
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
FieldDefinition &r = fields[i];
|
||||
|
||||
r.tag.resize(tagSize);
|
||||
|
||||
if (_file.read(r.tag.data(), tagSize) != tagSize
|
||||
if (_file.read(tag, sizeof(tag)) != 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);
|
||||
|
||||
@ -141,13 +135,13 @@ int ISO8211::readDR(QVector<FieldDefinition> &fields)
|
||||
|
||||
bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields)
|
||||
{
|
||||
static QRegularExpression re("(\\d*)(\\w+)\\(*(\\d*)\\)*");
|
||||
QByteArray ba;
|
||||
static const QRegularExpression re(
|
||||
"([0-9]*)(A|I|R|B|b11|b12|b14|b21|b22|b24)\\(*([0-9]*)\\)*");
|
||||
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
|
||||
bool repeat = false;
|
||||
QVector<SubFieldDefinition> defs;
|
||||
QVector<QByteArray> defTags;
|
||||
QVector<quint32> defTags;
|
||||
|
||||
ba.resize(def.size);
|
||||
if (!(_file.seek(def.pos) && _file.read(ba.data(), ba.size()) == ba.size()))
|
||||
return false;
|
||||
|
||||
@ -156,9 +150,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;
|
||||
|
||||
@ -188,11 +182,17 @@ 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);
|
||||
defTags[tag] = (tags.at(tag).length() == 4)
|
||||
? qFromLittleEndian<quint32>(tags.at(tag).constData()) : 0;
|
||||
tag++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag != tags.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
fields = SubFields(defTags, defs, repeat);
|
||||
@ -218,8 +218,10 @@ 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(fields.at(i).tag));
|
||||
.arg(QString(tag));
|
||||
return false;
|
||||
}
|
||||
_map.insert(fields.at(i).tag, def);
|
||||
@ -236,9 +238,8 @@ bool ISO8211::readDDR()
|
||||
bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
|
||||
const QVector<SubFieldDefinition> &fields, bool repeat, Data &data)
|
||||
{
|
||||
QByteArray ba;
|
||||
QByteArray ba(def.size, Qt::Initialization::Uninitialized);
|
||||
|
||||
ba.resize(def.size);
|
||||
if (!(_file.seek(pos + def.pos)
|
||||
&& _file.read(ba.data(), ba.size()) == ba.size()))
|
||||
return false;
|
||||
@ -248,8 +249,7 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
|
||||
const char *ep = ba.constData() + ba.size() - 1;
|
||||
|
||||
do {
|
||||
QVector<QVariant> row;
|
||||
row.resize(fields.size());
|
||||
QVector<QVariant> row(fields.size());
|
||||
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
const SubFieldDefinition &f = fields.at(i);
|
||||
@ -273,11 +273,11 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def,
|
||||
dp++;
|
||||
break;
|
||||
case S16:
|
||||
row[i] = QVariant(INT16(dp));
|
||||
row[i] = QVariant(qFromLittleEndian<qint16>(dp));
|
||||
dp += 2;
|
||||
break;
|
||||
case S32:
|
||||
row[i] = QVariant(INT32(dp));
|
||||
row[i] = QVariant(qFromLittleEndian<qint32>(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(UINT16(dp));
|
||||
row[i] = QVariant(qFromLittleEndian<quint16>(dp));
|
||||
dp += 2;
|
||||
break;
|
||||
case U32:
|
||||
row[i] = QVariant(UINT32(dp));
|
||||
row[i] = QVariant(qFromLittleEndian<quint32>(dp));
|
||||
dp += 4;
|
||||
break;
|
||||
default:
|
||||
@ -325,13 +325,16 @@ bool ISO8211::readRecord(Record &record)
|
||||
|
||||
FieldsMap::const_iterator it(_map.find(def.tag));
|
||||
if (it == _map.constEnd()) {
|
||||
_errorString = QString("%1: unknown record").arg(QString(def.tag));
|
||||
QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized);
|
||||
qToLittleEndian<quint32>(def.tag, tag.data());
|
||||
_errorString = QString("%1: unknown record").arg(QString(tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!readUDA(pos, def, it->defs(), it->repeat(), data)) {
|
||||
_errorString = QString("Error reading %1 record")
|
||||
.arg(QString(def.tag));
|
||||
QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized);
|
||||
qToLittleEndian<quint32>(def.tag, tag.data());
|
||||
_errorString = QString("Error reading %1 record").arg(QString(tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -341,8 +344,7 @@ bool ISO8211::readRecord(Record &record)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const ISO8211::Field *ISO8211::field(const Record &record, const QByteArray &name)
|
||||
const ISO8211::Field *ISO8211::field(const Record &record, quint32 name)
|
||||
{
|
||||
for (int i = 0; i < record.size(); i++)
|
||||
if (record.at(i).tag() == name)
|
||||
|
@ -4,13 +4,6 @@
|
||||
#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 {
|
||||
|
||||
@ -22,23 +15,22 @@ public:
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
Field() {}
|
||||
Field(const QByteArray &tag, const QVector<QByteArray> &subFields,
|
||||
const Data &data) : _tag(tag), _subFields(subFields), _data(data) {}
|
||||
Field() : _subFields(0) {}
|
||||
Field(quint32 tag, const QVector<quint32> &subFields, const Data &data)
|
||||
: _tag(tag), _subFields(&subFields), _data(data) {}
|
||||
|
||||
const QByteArray &tag() const {return _tag;}
|
||||
const QVector<QByteArray> &subFields() const {return _subFields;}
|
||||
quint32 tag() const {return _tag;}
|
||||
const Data &data() const {return _data;}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
private:
|
||||
const QVariant *data(const QByteArray &name, int idx = 0) const;
|
||||
const QVariant *data(quint32 name, int idx = 0) const;
|
||||
|
||||
QByteArray _tag;
|
||||
QVector<QByteArray> _subFields;
|
||||
quint32 _tag;
|
||||
const QVector<quint32> *_subFields;
|
||||
Data _data;
|
||||
};
|
||||
|
||||
@ -50,14 +42,21 @@ public:
|
||||
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
static const Field *field(const Record &record, const QByteArray &name);
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
enum FieldType {Unknown, String, Array, S8, S16, S32, U8, U16, U32};
|
||||
|
||||
struct FieldDefinition
|
||||
{
|
||||
QByteArray tag;
|
||||
quint32 tag;
|
||||
int pos;
|
||||
int size;
|
||||
};
|
||||
@ -81,22 +80,22 @@ private:
|
||||
{
|
||||
public:
|
||||
SubFields() : _repeat(false) {}
|
||||
SubFields(const QVector<QByteArray> &tags,
|
||||
SubFields(const QVector<quint32> &tags,
|
||||
const QVector<SubFieldDefinition> &defs, bool repeat)
|
||||
: _tags(tags), _defs(defs), _repeat(repeat) {}
|
||||
|
||||
const QVector<QByteArray> &tags() const {return _tags;}
|
||||
const QVector<quint32> &tags() const {return _tags;}
|
||||
const QVector<SubFieldDefinition> &defs() const {return _defs;}
|
||||
|
||||
bool repeat() const {return _repeat;}
|
||||
|
||||
private:
|
||||
QVector<QByteArray> _tags;
|
||||
QVector<quint32> _tags;
|
||||
QVector<SubFieldDefinition> _defs;
|
||||
bool _repeat;
|
||||
};
|
||||
|
||||
typedef QMap<QByteArray, SubFields> FieldsMap;
|
||||
typedef QMap<quint32, SubFields> FieldsMap;
|
||||
|
||||
static SubFieldDefinition fieldType(const QString &str, int cnt);
|
||||
|
||||
@ -110,14 +109,6 @@ 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
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <QtEndian>
|
||||
#include "GUI/units.h"
|
||||
#include "objects.h"
|
||||
#include "attributes.h"
|
||||
@ -14,6 +15,19 @@ 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;
|
||||
@ -90,20 +104,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;
|
||||
}
|
||||
}
|
||||
@ -132,7 +146,7 @@ static bool parseNAME(const ISO8211::Field *f, quint8 *type, quint32 *id,
|
||||
return false;
|
||||
|
||||
*type = (quint8)(*ba.constData());
|
||||
*id = UINT32(ba.constData() + 1);
|
||||
*id = qFromLittleEndian<quint32>(ba.constData() + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -141,9 +155,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;
|
||||
@ -212,12 +226,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)
|
||||
@ -226,7 +240,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)
|
||||
@ -362,6 +376,8 @@ MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr,
|
||||
subtype = CATACH;
|
||||
else if (type == I_ACHARE)
|
||||
subtype = I_CATACH;
|
||||
else if (type == MARKUL)
|
||||
subtype = CATMFA;
|
||||
|
||||
QList<QByteArray> list(_attr.value(subtype).split(','));
|
||||
std::sort(list.begin(), list.end());
|
||||
@ -423,6 +439,8 @@ MapData::Poly::Poly(uint type, const Polygon &path, const Attributes &attr,
|
||||
subtype = CATMFA;
|
||||
else if (type == I_BERTHS)
|
||||
subtype = I_CATBRT;
|
||||
else if (type == M_COVR)
|
||||
subtype = CATCOV;
|
||||
|
||||
switch (type) {
|
||||
case DEPARE:
|
||||
@ -473,10 +491,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>();
|
||||
|
||||
@ -485,24 +503,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) {
|
||||
@ -516,21 +534,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) {
|
||||
@ -544,55 +562,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]);
|
||||
@ -602,7 +620,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]);
|
||||
@ -613,26 +631,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();
|
||||
}
|
||||
@ -640,55 +658,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();
|
||||
}
|
||||
@ -704,12 +722,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());
|
||||
}
|
||||
|
||||
@ -722,64 +740,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);
|
||||
const QByteArray &ba = f.tag();
|
||||
quint32 tag = f.tag();
|
||||
|
||||
if (ba == "VRID") {
|
||||
if (tag == 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 (ba == "FRID") {
|
||||
} else if (tag == FRID) {
|
||||
fe.append(record);
|
||||
} else if (ba == "DSPM") {
|
||||
if (!(f.subfield("COMF", &COMF) && f.subfield("SOMF", &SOMF)))
|
||||
} else if (tag == DSPM) {
|
||||
if (!(f.subfield(COMF, &comf) && f.subfield(SOMF, &somf)))
|
||||
return false;
|
||||
if (!f.subfield("HUNI", &HUNI))
|
||||
if (!f.subfield(HUNI, &huni))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -792,7 +810,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;
|
||||
@ -802,7 +820,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++) {
|
||||
@ -811,39 +829,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;
|
||||
}
|
||||
}
|
||||
@ -864,7 +882,7 @@ MapData::~MapData()
|
||||
delete _points.GetAt(pit);
|
||||
}
|
||||
|
||||
void MapData::points(const RectC &rect, QList<Point> *points) const
|
||||
void MapData::points(const RectC &rect, QList<Point> *points)
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
@ -874,18 +892,12 @@ void MapData::points(const RectC &rect, QList<Point> *points) const
|
||||
_lines.Search(min, max, linePointCb, points);
|
||||
}
|
||||
|
||||
void MapData::lines(const RectC &rect, QList<Line> *lines) const
|
||||
void MapData::polys(const RectC &rect, QList<Poly> *polygons,
|
||||
QList<Line> *lines)
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
rectcBounds(rect, min, max);
|
||||
_lines.Search(min, max, lineCb, lines);
|
||||
}
|
||||
|
||||
void MapData::polygons(const RectC &rect, QList<Poly> *polygons) const
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
rectcBounds(rect, min, max);
|
||||
_areas.Search(min, max, polygonCb, polygons);
|
||||
}
|
||||
|
@ -1,82 +1,21 @@
|
||||
#ifndef ENC_MAPDATA_H
|
||||
#define ENC_MAPDATA_H
|
||||
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
#include "common/polygon.h"
|
||||
#include "iso8211.h"
|
||||
#include "data.h"
|
||||
|
||||
namespace ENC {
|
||||
|
||||
class MapData
|
||||
class MapData : public Data
|
||||
{
|
||||
public:
|
||||
typedef QMap<uint, QByteArray> Attributes;
|
||||
|
||||
class Poly {
|
||||
public:
|
||||
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
|
||||
|
||||
RectC bounds() const {return _path.boundingRect();}
|
||||
const Polygon &path() const {return _path;}
|
||||
uint type() const {return _type;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
uint HUNI() const {return _HUNI;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
Polygon _path;
|
||||
Attributes _attr;
|
||||
uint _HUNI;
|
||||
};
|
||||
|
||||
class Line {
|
||||
public:
|
||||
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
|
||||
|
||||
RectC bounds() const;
|
||||
const QVector<Coordinates> &path() const {return _path;}
|
||||
uint type() const {return _type;}
|
||||
const QString &label() const {return _label;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
QVector<Coordinates> _path;
|
||||
QString _label;
|
||||
Attributes _attr;
|
||||
};
|
||||
|
||||
class Point {
|
||||
public:
|
||||
Point(uint type, const Coordinates &c, const Attributes &attr,
|
||||
uint HUNI, bool polygon = false);
|
||||
Point(uint type, const Coordinates &s, const QString &label);
|
||||
|
||||
const Coordinates &pos() const {return _pos;}
|
||||
uint type() const {return _type;}
|
||||
const QString &label() const {return _label;}
|
||||
const Attributes &attributes() const {return _attr;}
|
||||
bool polygon() const {return _polygon;}
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
{return _id < other._id;}
|
||||
|
||||
private:
|
||||
uint _type;
|
||||
Coordinates _pos;
|
||||
QString _label;
|
||||
quint64 _id;
|
||||
Attributes _attr;
|
||||
bool _polygon;
|
||||
};
|
||||
|
||||
MapData(const QString &path);
|
||||
~MapData();
|
||||
virtual ~MapData();
|
||||
|
||||
void polygons(const RectC &rect, QList<Poly> *polygons) const;
|
||||
void lines(const RectC &rect, QList<Line> *lines) const;
|
||||
void points(const RectC &rect, QList<Point> *points) const;
|
||||
virtual void polys(const RectC &rect, QList<Poly> *polygons,
|
||||
QList<Line> *lines);
|
||||
virtual void points(const RectC &rect, QList<Point> *points);
|
||||
|
||||
private:
|
||||
struct Sounding {
|
||||
@ -93,28 +32,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;
|
||||
|
@ -14,6 +14,7 @@ using namespace ENC;
|
||||
#define TEXT_EXTENT 160
|
||||
#define TSSLPT_SIZE 24
|
||||
#define RANGE_FACTOR 4
|
||||
#define MAJOR_RANGE 10
|
||||
|
||||
static const float C1 = 0.866025f; /* sqrt(3)/2 */
|
||||
static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb);
|
||||
@ -27,14 +28,14 @@ static double angle(uint type, const QVariant ¶m)
|
||||
? 90 + param.toDouble() : NAN;
|
||||
}
|
||||
|
||||
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
|
||||
bool RasterTile::showLabel(const QImage *img, int type) const
|
||||
{
|
||||
if (type>>16 == I_DISMAR)
|
||||
return true;
|
||||
|
||||
int limit = (!range.size())
|
||||
? range.min() : range.min() + (range.size() + 1) / 2;
|
||||
if ((img || (type>>16 == SOUNDG)) && (zoom < limit))
|
||||
int limit = (!_zoomRange.size())
|
||||
? _zoomRange.min() : _zoomRange.min() + (_zoomRange.size() + 1) / 2;
|
||||
if ((img || (type>>16 == SOUNDG)) && (_zoom < limit))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -138,10 +139,10 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type)
|
||||
}
|
||||
|
||||
void RasterTile::drawArrows(QPainter *painter,
|
||||
const QList<MapData::Point> &points) const
|
||||
const QList<Data::Point> &points) const
|
||||
{
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
const Data::Point &point = points.at(i);
|
||||
|
||||
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
|
||||
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
|
||||
@ -152,11 +153,11 @@ void RasterTile::drawArrows(QPainter *painter,
|
||||
}
|
||||
|
||||
void RasterTile::drawPolygons(QPainter *painter,
|
||||
const QList<MapData::Poly> &polygons) const
|
||||
const QList<Data::Poly> &polygons) const
|
||||
{
|
||||
for (int n = 0; n < _style->drawOrder().size(); n++) {
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly &poly = polygons.at(i);
|
||||
const Data::Poly &poly = polygons.at(i);
|
||||
if (poly.type() != _style->drawOrder().at(n))
|
||||
continue;
|
||||
const Style::Polygon &style = _style->polygon(poly.type());
|
||||
@ -168,8 +169,13 @@ void RasterTile::drawPolygons(QPainter *painter,
|
||||
} else {
|
||||
if (style.brush() != Qt::NoBrush) {
|
||||
painter->setPen(Qt::NoPen);
|
||||
QPainterPath path(painterPath(poly.path()));
|
||||
if (poly.type() == TYPE(DRGARE)) {
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawPath(path);
|
||||
}
|
||||
painter->setBrush(style.brush());
|
||||
painter->drawPath(painterPath(poly.path()));
|
||||
painter->drawPath(path);
|
||||
}
|
||||
if (style.pen() != Qt::NoPen) {
|
||||
painter->setPen(style.pen());
|
||||
@ -184,12 +190,12 @@ void RasterTile::drawPolygons(QPainter *painter,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines) const
|
||||
void RasterTile::drawLines(QPainter *painter, const QList<Data::Line> &lines) const
|
||||
{
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Line &line = lines.at(i);
|
||||
const Data::Line &line = lines.at(i);
|
||||
const Style::Line &style = _style->line(line.type());
|
||||
|
||||
if (!style.img().isNull()) {
|
||||
@ -215,16 +221,16 @@ void RasterTile::drawTextItems(QPainter *painter,
|
||||
|
||||
static QRectF lightRect(const QPointF &pos, double range)
|
||||
{
|
||||
return QRectF(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR,
|
||||
2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR);
|
||||
double r = qMin(range * RANGE_FACTOR, (double)TEXT_EXTENT);
|
||||
return QRect(pos.x() - r, pos.y() - r, 2 * r, 2 * r);
|
||||
}
|
||||
|
||||
void RasterTile::drawSectorLights(QPainter *painter,
|
||||
const QList<SectorLight> &lights) const
|
||||
const QMultiMap<Coordinates, SectorLight> &lights) const
|
||||
{
|
||||
for (int i = 0; i < lights.size(); i++) {
|
||||
const SectorLight &l = lights.at(i);
|
||||
QPointF pos(ll2xy(l.pos));
|
||||
for (auto it = lights.cbegin(); it != lights.cend(); ++it) {
|
||||
const SectorLight &l = it.value();
|
||||
QPointF pos(ll2xy(it.key()));
|
||||
QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range));
|
||||
double a1 = -(l.end + 90);
|
||||
double a2 = -(l.start + 90);
|
||||
@ -256,49 +262,45 @@ void RasterTile::drawSectorLights(QPainter *painter,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lights,
|
||||
QList<SectorLight> §orLights)
|
||||
void RasterTile::processPoints(const QList<Data::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
|
||||
QMultiMap<Coordinates, SectorLight> §orLights, bool overZoom) const
|
||||
{
|
||||
LightMap lightsMap;
|
||||
SignalSet signalsSet;
|
||||
QSet<Coordinates> slMap;
|
||||
QMap<Coordinates, Style::Color> lights;
|
||||
QSet<Coordinates> sigs;
|
||||
int i;
|
||||
|
||||
std::sort(points.begin(), points.end());
|
||||
|
||||
/* Lights & Signals */
|
||||
for (i = 0; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
const Data::Point &point = points.at(i);
|
||||
|
||||
if (point.type()>>16 == LIGHTS) {
|
||||
const MapData::Attributes &attr = point.attributes();
|
||||
const Data::Attributes &attr = point.attributes();
|
||||
Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
|
||||
double range = attr.value(VALNMR).toDouble();
|
||||
|
||||
if (attr.contains(SECTR1)
|
||||
|| (range > 6 && !(point.type() & 0xFFFF))) {
|
||||
sectorLights.append(SectorLight(point.pos(), color,
|
||||
|| (range >= MAJOR_RANGE && !(point.type() & 0xFFFF))) {
|
||||
sectorLights.insert(point.pos(), SectorLight(color,
|
||||
attr.value(LITVIS).toUInt(), range,
|
||||
attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble()));
|
||||
slMap.insert(point.pos());
|
||||
} else
|
||||
lightsMap.insert(point.pos(), color);
|
||||
lights.insert(point.pos(), color);
|
||||
} else if (point.type()>>16 == FOGSIG)
|
||||
signalsSet.insert(point.pos());
|
||||
sigs.insert(point.pos());
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Everything else */
|
||||
for ( ; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
const Data::Point &point = points.at(i);
|
||||
QPoint pos(ll2xy(point.pos()).toPoint());
|
||||
const Style::Point &style = _style->point(point.type());
|
||||
|
||||
const QString *label = point.label().isEmpty() ? 0 : &(point.label());
|
||||
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
||||
const QFont *fnt = showLabel(img, _zoomRange, _zoom, point.type())
|
||||
const QFont *fnt = (overZoom || showLabel(img, point.type()))
|
||||
? _style->font(style.textFontSize()) : 0;
|
||||
const QColor *color = &style.textColor();
|
||||
const QColor *hColor = style.haloColor().isValid()
|
||||
@ -312,25 +314,25 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
|
||||
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
|
||||
color, hColor, 0, 2, rotate);
|
||||
if (item->isValid() && (slMap.contains(point.pos())
|
||||
if (item->isValid() && (sectorLights.contains(point.pos())
|
||||
|| (point.polygon() && img) || !item->collides(textItems))) {
|
||||
textItems.append(item);
|
||||
if (lightsMap.contains(point.pos()))
|
||||
lights.append(new TextPointItem(pos + _style->lightOffset(),
|
||||
0, 0, _style->light(lightsMap.value(point.pos())), 0, 0, 0, 0));
|
||||
if (signalsSet.contains(point.pos()))
|
||||
lights.append(new TextPointItem(pos + _style->signalOffset(),
|
||||
if (lights.contains(point.pos()))
|
||||
lightItems.append(new TextPointItem(pos + _style->lightOffset(),
|
||||
0, 0, _style->light(lights.value(point.pos())), 0, 0, 0, 0));
|
||||
if (sigs.contains(point.pos()))
|
||||
lightItems.append(new TextPointItem(pos + _style->signalOffset(),
|
||||
0, 0, _style->signal(), 0, 0, 0, 0));
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processLines(const QList<MapData::Line> &lines,
|
||||
QList<TextItem*> &textItems)
|
||||
void RasterTile::processLines(const QList<Data::Line> &lines,
|
||||
QList<TextItem*> &textItems) const
|
||||
{
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Line &line = lines.at(i);
|
||||
const Data::Line &line = lines.at(i);
|
||||
const Style::Line &style = _style->line(line.type());
|
||||
|
||||
if (style.img().isNull() && style.pen() == Qt::NoPen)
|
||||
@ -350,11 +352,46 @@ void RasterTile::processLines(const QList<MapData::Line> &lines,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
|
||||
QList<MapData::Line> &lines, QList<MapData::Point> &points)
|
||||
void RasterTile::drawLevels(QPainter *painter, const QList<Level> &levels)
|
||||
{
|
||||
QPoint ttl(_rect.topLeft());
|
||||
for (int i = levels.size() - 1; i >= 0; i--) {
|
||||
QList<TextItem*> textItems, lightItems;
|
||||
QMultiMap<Coordinates, SectorLight> sectorLights;
|
||||
const Level &l = levels.at(i);
|
||||
|
||||
processPoints(l.points, textItems, lightItems, sectorLights, l.overZoom);
|
||||
processLines(l.lines, textItems);
|
||||
|
||||
drawPolygons(painter, l.polygons);
|
||||
drawLines(painter, l.lines);
|
||||
drawArrows(painter, l.points);
|
||||
|
||||
drawTextItems(painter, lightItems);
|
||||
drawSectorLights(painter, sectorLights);
|
||||
drawTextItems(painter, textItems);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
qDeleteAll(lightItems);
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath RasterTile::shape(const QList<Data::Poly> &polygons) const
|
||||
{
|
||||
QPainterPath shp;
|
||||
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const Data::Poly &p = polygons.at(i);
|
||||
if (p.type() == SUBTYPE(M_COVR, 1))
|
||||
shp.addPath(painterPath(p.path()));
|
||||
}
|
||||
|
||||
return shp;
|
||||
}
|
||||
|
||||
QList<RasterTile::Level> RasterTile::fetchLevels()
|
||||
{
|
||||
QList<RasterTile::Level> list;
|
||||
QPoint ttl(_rect.topLeft());
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y()
|
||||
+ _rect.height()));
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
@ -367,50 +404,41 @@ void RasterTile::fetchData(QList<MapData::Poly> &polygons,
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
RectC pointRectC(pointRectD.toRectC(_proj, 20));
|
||||
|
||||
if (_map) {
|
||||
_map->lines(polyRectC, &lines);
|
||||
_map->polygons(polyRectC, &polygons);
|
||||
_map->points(pointRectC, &points);
|
||||
} else {
|
||||
_atlas->polys(polyRectC, &polygons, &lines);
|
||||
_atlas->points(pointRectC, &points);
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
Level level;
|
||||
|
||||
_data.at(i)->polys(polyRectC, &level.polygons, &level.lines);
|
||||
_data.at(i)->points(pointRectC, &level.points);
|
||||
level.overZoom = i > 0;
|
||||
|
||||
std::sort(level.points.begin(), level.points.end());
|
||||
|
||||
if (!level.isNull())
|
||||
list.append(level);
|
||||
|
||||
if (_data.size() > 1 && shape(level.polygons).contains(_rect))
|
||||
break;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<Level> levels(fetchLevels());
|
||||
|
||||
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
QList<MapData::Line> lines;
|
||||
QList<MapData::Poly> polygons;
|
||||
QList<MapData::Point> points;
|
||||
QList<TextItem*> textItems, lights;
|
||||
QList<SectorLight> sectorLights;
|
||||
|
||||
img.setDevicePixelRatio(_ratio);
|
||||
img.fill(Qt::transparent);
|
||||
|
||||
fetchData(polygons, lines, points);
|
||||
|
||||
processPoints(points, textItems, lights, sectorLights);
|
||||
processLines(lines, textItems);
|
||||
|
||||
QPainter painter(&img);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPolygons(&painter, polygons);
|
||||
drawLines(&painter, lines);
|
||||
drawArrows(&painter, points);
|
||||
|
||||
|
||||
drawTextItems(&painter, lights);
|
||||
drawSectorLights(&painter, sectorLights);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
qDeleteAll(lights);
|
||||
drawLevels(&painter, levels);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setBrush(Qt::NoBrush);
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "common/range.h"
|
||||
#include "map/projection.h"
|
||||
#include "map/transform.h"
|
||||
#include "mapdata.h"
|
||||
#include "data.h"
|
||||
#include "style.h"
|
||||
#include "atlasdata.h"
|
||||
|
||||
@ -17,14 +17,17 @@ class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Style *style, const MapData *data, int zoom, const Range &zoomRange,
|
||||
const QRect &rect, qreal ratio) :
|
||||
_proj(proj), _transform(transform), _style(style), _map(data), _atlas(0),
|
||||
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
|
||||
const Style *style, Data *data, int zoom,
|
||||
const Range &zoomRange, const QRect &rect, qreal ratio) :
|
||||
_proj(proj), _transform(transform), _style(style),
|
||||
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio)
|
||||
{
|
||||
_data.append(data);
|
||||
}
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Style *style, AtlasData *data, int zoom, const Range &zoomRange,
|
||||
const QRect &rect, qreal ratio) :
|
||||
_proj(proj), _transform(transform), _style(style), _map(0), _atlas(data),
|
||||
const Style *style, const QList<Data*> &data, int zoom,
|
||||
const Range &zoomRange, const QRect &rect, qreal ratio) :
|
||||
_proj(proj), _transform(transform), _style(style), _data(data),
|
||||
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -36,11 +39,10 @@ public:
|
||||
private:
|
||||
struct SectorLight
|
||||
{
|
||||
SectorLight(const Coordinates &pos, Style::Color color, uint visibility,
|
||||
double range, double start, double end) : pos(pos), color(color),
|
||||
visibility(visibility), range(range), start(start), end(end) {}
|
||||
SectorLight(Style::Color color, uint visibility, double range,
|
||||
double start, double end) : color(color), visibility(visibility),
|
||||
range(range), start(start), end(end) {}
|
||||
|
||||
Coordinates pos;
|
||||
Style::Color color;
|
||||
uint visibility;
|
||||
double range;
|
||||
@ -48,11 +50,16 @@ private:
|
||||
double end;
|
||||
};
|
||||
|
||||
typedef QMap<Coordinates, Style::Color> LightMap;
|
||||
typedef QSet<Coordinates> SignalSet;
|
||||
struct Level {
|
||||
QList<Data::Line> lines;
|
||||
QList<Data::Poly> polygons;
|
||||
QList<Data::Point> points;
|
||||
bool overZoom;
|
||||
|
||||
bool isNull() const
|
||||
{return lines.isEmpty() && polygons.isEmpty() && points.isEmpty();}
|
||||
};
|
||||
|
||||
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines,
|
||||
QList<MapData::Point> &points);
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
QPainterPath painterPath(const Polygon &polygon) const;
|
||||
@ -60,25 +67,26 @@ private:
|
||||
QVector<QPolygonF> polylineM(const QVector<Coordinates> &path) const;
|
||||
QPolygonF tsslptArrow(const QPointF &p, qreal angle) const;
|
||||
QPointF centroid(const QVector<Coordinates> &polygon) const;
|
||||
void processPoints(QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem *> &lights,
|
||||
QList<SectorLight> §orLights);
|
||||
void processLines(const QList<MapData::Line> &lines,
|
||||
QList<TextItem*> &textItems);
|
||||
void drawArrows(QPainter *painter, const QList<MapData::Point> &points) const;
|
||||
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const;
|
||||
void drawLines(QPainter *painter, const QList<MapData::Line> &lines) const;
|
||||
void processPoints(const QList<Data::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lightItems,
|
||||
QMultiMap<Coordinates, SectorLight> §orLights, bool overZoom) const;
|
||||
void processLines(const QList<Data::Line> &lines,
|
||||
QList<TextItem*> &textItems) const;
|
||||
void drawArrows(QPainter *painter, const QList<Data::Point> &points) const;
|
||||
void drawPolygons(QPainter *painter, const QList<Data::Poly> &polygons) const;
|
||||
void drawLines(QPainter *painter, const QList<Data::Line> &lines) const;
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
|
||||
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights) const;
|
||||
|
||||
static bool polyCb(MapData *data, void *context);
|
||||
static bool pointCb(MapData *data, void *context);
|
||||
void drawSectorLights(QPainter *painter,
|
||||
const QMultiMap<Coordinates, SectorLight> &lights) const;
|
||||
bool showLabel(const QImage *img, int type) const;
|
||||
void drawLevels(QPainter *painter, const QList<Level> &levels);
|
||||
QList<Level> fetchLevels();
|
||||
QPainterPath shape(const QList<Data::Poly> &polygons) const;
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
const Style *_style;
|
||||
const MapData *_map;
|
||||
AtlasData *_atlas;
|
||||
QList<Data *> _data;
|
||||
int _zoom;
|
||||
Range _zoomRange;
|
||||
QRect _rect;
|
||||
|
@ -27,7 +27,6 @@ static QFont pixelSizeFont(int pixelSize)
|
||||
|
||||
void Style::polygonStyle()
|
||||
{
|
||||
_polygons[TYPE(M_COVR)] = Polygon(QBrush(QColor(0xff, 0xff, 0xff)));
|
||||
_polygons[TYPE(LNDARE)] = Polygon(QBrush(QColor(0xe8, 0xe0, 0x64)));
|
||||
_polygons[TYPE(BUAARE)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)));
|
||||
_polygons[TYPE(BUISGL)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)),
|
||||
@ -141,6 +140,7 @@ void Style::polygonStyle()
|
||||
1.5, Qt::DashLine));
|
||||
_polygons[TYPE(CBLARE)] = Polygon(QImage(":/marine/cable-area-line.png"));
|
||||
_polygons[TYPE(PIPARE)] = Polygon(QImage(":/marine/pipeline-area-line.png"));
|
||||
_polygons[SUBTYPE(MARKUL, 0)] = Polygon(QImage(":/marine/fishing-farm-line.png"));
|
||||
_polygons[SUBTYPE(MARKUL, 3)] = Polygon(QImage(":/marine/fishing-farm-line.png"));
|
||||
_polygons[TYPE(BERTHS)] = Polygon(Qt::NoBrush, QPen(QColor(0xeb, 0x49, 0xeb),
|
||||
1, Qt::DashLine));
|
||||
@ -152,19 +152,19 @@ void Style::polygonStyle()
|
||||
1, Qt::DashDotLine));
|
||||
|
||||
_drawOrder
|
||||
<< TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0)
|
||||
<< SUBTYPE(DEPARE, 1) << SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3)
|
||||
<< TYPE(UNSARE) << SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5)
|
||||
<< SUBTYPE(DEPARE, 6) << TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON)
|
||||
<< TYPE(RIVERS) << TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN)
|
||||
<< TYPE(I_LOKBSN) << TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK)
|
||||
<< TYPE(AIRARE) << TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL)
|
||||
<< TYPE(I_TERMNL) << TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON)
|
||||
<< TYPE(I_PONTON) << TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC)
|
||||
<< TYPE(I_FLODOC) << TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS)
|
||||
<< TYPE(MORFAC) << TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS)
|
||||
<< TYPE(I_BERTHS) << SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE)
|
||||
<< TYPE(OBSTRN) << TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
|
||||
<< TYPE(LNDARE) << SUBTYPE(DEPARE, 0) << SUBTYPE(DEPARE, 1)
|
||||
<< SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3) << TYPE(UNSARE)
|
||||
<< SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5) << SUBTYPE(DEPARE, 6)
|
||||
<< TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON) << TYPE(RIVERS)
|
||||
<< TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN) << TYPE(I_LOKBSN)
|
||||
<< TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK) << TYPE(AIRARE)
|
||||
<< TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL) << TYPE(I_TERMNL)
|
||||
<< TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON) << TYPE(I_PONTON)
|
||||
<< TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC) << TYPE(I_FLODOC)
|
||||
<< TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS) << TYPE(MORFAC)
|
||||
<< TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS) << TYPE(I_BERTHS)
|
||||
<< SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN)
|
||||
<< TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
|
||||
<< SUBTYPE(ACHARE, 2) << SUBTYPE(ACHARE, 3) << SUBTYPE(ACHARE, 4)
|
||||
<< SUBTYPE(ACHARE, 5) << SUBTYPE(ACHARE, 6) << SUBTYPE(ACHARE, 7)
|
||||
<< SUBTYPE(ACHARE, 8) << SUBTYPE(ACHARE, 9) << SUBTYPE(I_ACHARE, 1)
|
||||
@ -180,7 +180,8 @@ void Style::polygonStyle()
|
||||
<< SUBTYPE(RESARE, 17) << SUBTYPE(I_RESARE, 17) << SUBTYPE(RESARE, 22)
|
||||
<< SUBTYPE(I_RESARE, 22) << SUBTYPE(RESARE, 23) << SUBTYPE(I_RESARE, 23)
|
||||
<< SUBTYPE(RESARE, 1) << TYPE(CBLARE) << TYPE(PIPARE) << TYPE(PRCARE)
|
||||
<< TYPE(I_TRNBSN) << SUBTYPE(MARKUL, 3) << TYPE(CONZNE);
|
||||
<< TYPE(I_TRNBSN) << SUBTYPE(MARKUL, 0) << SUBTYPE(MARKUL, 3)
|
||||
<< TYPE(CONZNE);
|
||||
}
|
||||
|
||||
void Style::lineStyle(qreal ratio)
|
||||
@ -393,6 +394,8 @@ void Style::pointStyle(qreal ratio)
|
||||
_points[TYPE(LNDARE)].setHaloColor(QColor());
|
||||
_points[TYPE(LNDRGN)].setHaloColor(QColor());
|
||||
_points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png"));
|
||||
_points[SUBTYPE(MARKUL, 0)] = Point(QImage(":/marine/fishing-farm.png"));
|
||||
_points[SUBTYPE(MARKUL, 3)] = Point(QImage(":/marine/fishing-farm.png"));
|
||||
|
||||
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"),
|
||||
Small);
|
||||
@ -482,6 +485,7 @@ Style::Style(qreal ratio)
|
||||
_lightRed = QImage(":/marine/light-red.png");
|
||||
_lightGreen = QImage(":/marine/light-green.png");
|
||||
_lightYellow = QImage(":/marine/light-yellow.png");
|
||||
_lightWhite = QImage(":/marine/light-white.png");
|
||||
_lightOffset = QPoint(11, 11);
|
||||
_signal = QImage(":/marine/fog-signal.png");
|
||||
_signalOffset = QPoint(-9, 9);
|
||||
@ -541,6 +545,7 @@ const QImage *Style::light(Color color) const
|
||||
case Green:
|
||||
return &_lightGreen;
|
||||
case White:
|
||||
return &_lightWhite;
|
||||
case Yellow:
|
||||
case Amber:
|
||||
case Orange:
|
||||
@ -558,6 +563,7 @@ QColor Style::color(Style::Color c)
|
||||
case Green:
|
||||
return Qt::green;
|
||||
case White:
|
||||
return Qt::white;
|
||||
case Yellow:
|
||||
case Amber:
|
||||
case Orange:
|
||||
|
@ -121,7 +121,7 @@ private:
|
||||
|
||||
/* Fonts and images must be initialized after QGuiApplication! */
|
||||
QFont _small, _normal, _large;
|
||||
QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
|
||||
QImage _light, _lightRed, _lightGreen, _lightYellow, _lightWhite, _signal;
|
||||
QPoint _lightOffset, _signalOffset;
|
||||
};
|
||||
|
||||
|
64
src/map/IMG/light.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef IMG_LIGHT_H
|
||||
#define IMG_LIGHT_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
namespace IMG {
|
||||
|
||||
class Light
|
||||
{
|
||||
public:
|
||||
enum Color {None, Red, Green, White, Blue, Yellow, Violet, Amber};
|
||||
|
||||
class Sector
|
||||
{
|
||||
public:
|
||||
Sector() : _color(None), _angle(0), _range(0) {}
|
||||
Sector(Color color, quint32 angle, quint32 range)
|
||||
: _color(color), _angle(angle), _range(range) {}
|
||||
|
||||
Color color() const {return _color;}
|
||||
quint32 angle() const {return _angle;}
|
||||
quint32 range() const {return _range;}
|
||||
|
||||
private:
|
||||
Color _color;
|
||||
quint32 _angle;
|
||||
quint32 _range;
|
||||
};
|
||||
|
||||
Light() : _color(None), _range(0) {}
|
||||
Light(Color color, quint32 range) : _color(color), _range(range) {}
|
||||
Light(const QVector<Sector> §ors)
|
||||
: _color(None), _range(0), _sectors(sectors) {}
|
||||
|
||||
Color color() const {return _color;}
|
||||
quint32 range() const {return _range;}
|
||||
const QVector<Sector> §ors() const {return _sectors;}
|
||||
|
||||
private:
|
||||
Color _color;
|
||||
quint32 _range;
|
||||
QVector<Sector> _sectors;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const IMG::Light::Sector §or)
|
||||
{
|
||||
dbg.nospace() << "Sector(" << sector.color() << ", " << sector.angle()
|
||||
<< ", " << sector.range() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const IMG::Light &light)
|
||||
{
|
||||
dbg.nospace() << "Light(" << light.color() << ", " << light.range() << ", "
|
||||
<< light.sectors() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // IMG_LIGHT_H
|
@ -1,52 +0,0 @@
|
||||
#ifndef IMG_LIGHTS_H
|
||||
#define IMG_LIGHTS_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
namespace IMG {
|
||||
|
||||
class Lights
|
||||
{
|
||||
public:
|
||||
enum Color {None, Red, Green, White, Blue, Yellow, Violet, Amber};
|
||||
|
||||
struct Sector
|
||||
{
|
||||
Sector() : color(None), angle(0), range(0) {}
|
||||
Sector(Color color, quint32 angle, quint32 range)
|
||||
: color(color), angle(angle), range(range) {}
|
||||
|
||||
Color color;
|
||||
quint32 angle;
|
||||
quint32 range;
|
||||
};
|
||||
|
||||
Lights() : color(None), range(0) {}
|
||||
bool isSectorLight() const
|
||||
{return ((color && range > 6) || !sectors.isEmpty());}
|
||||
|
||||
Color color;
|
||||
quint32 range;
|
||||
QVector<Sector> sectors;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const IMG::Lights::Sector §or)
|
||||
{
|
||||
dbg.nospace() << "Sector(" << sector.color << ", " << sector.angle
|
||||
<< ", " << sector.range << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const IMG::Lights &lights)
|
||||
{
|
||||
dbg.nospace() << "Lights(" << lights.color << ", " << lights.range << ", "
|
||||
<< lights.sectors << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // IMG_LIGHTS_H
|
@ -14,7 +14,7 @@
|
||||
#include "map/matrix.h"
|
||||
#include "label.h"
|
||||
#include "raster.h"
|
||||
#include "lights.h"
|
||||
#include "light.h"
|
||||
#include "zoom.h"
|
||||
|
||||
namespace IMG {
|
||||
@ -56,7 +56,7 @@ public:
|
||||
|
||||
Coordinates coordinates;
|
||||
Label label;
|
||||
Lights lights;
|
||||
QVector<Light> lights;
|
||||
quint64 id;
|
||||
quint32 type;
|
||||
quint32 flags;
|
||||
|
@ -19,6 +19,7 @@ using namespace IMG;
|
||||
#define TEXT_EXTENT 160
|
||||
#define ICON_PADDING 2
|
||||
#define RANGE_FACTOR 4
|
||||
#define MAJOR_RANGE 10
|
||||
#define ROAD 0
|
||||
#define WATER 1
|
||||
|
||||
@ -228,64 +229,82 @@ void RasterTile::drawTextItems(QPainter *painter,
|
||||
|
||||
static QRect lightRect(const QPoint &pos, quint32 range)
|
||||
{
|
||||
return QRect(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR,
|
||||
2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR);
|
||||
quint32 r = qMin(range * RANGE_FACTOR, (quint32)TEXT_EXTENT);
|
||||
return QRect(pos.x() - r, pos.y() - r, 2 * r, 2 * r);
|
||||
}
|
||||
|
||||
void RasterTile::drawSectorLights(QPainter *painter,
|
||||
const QList<const MapData::Point *> &lights) const
|
||||
const QList<const MapData::Point*> &lights) const
|
||||
{
|
||||
for (int i = 0; i < lights.size(); i++) {
|
||||
const MapData::Point *p = lights.at(i);
|
||||
QPoint pos(p->coordinates.lon(), p->coordinates.lat());
|
||||
QMap<Sector, quint32> rangeMap;
|
||||
|
||||
if (p->lights.sectors.size()) {
|
||||
for (int j = 0; j < p->lights.sectors.size(); j++) {
|
||||
const Lights::Sector &start = p->lights.sectors.at(j);
|
||||
const Lights::Sector &end = (j == p->lights.sectors.size() - 1)
|
||||
? p->lights.sectors.at(0) : p->lights.sectors.at(j+1);
|
||||
for (int j = 0; j < p->lights.size(); j++) {
|
||||
const Light &l = p->lights.at(j);
|
||||
|
||||
if (start.color) {
|
||||
double a1 = -(end.angle / 10.0 + 90.0);
|
||||
double a2 = -(start.angle / 10.0 + 90.0);
|
||||
if (a1 > a2)
|
||||
a2 += 360;
|
||||
double as = (a2 - a1);
|
||||
if (as == 0)
|
||||
as = 360;
|
||||
if (l.sectors().size()) {
|
||||
for (int k = 0; k < l.sectors().size(); k++) {
|
||||
const Light::Sector &start = l.sectors().at(k);
|
||||
const Light::Sector &end = (k == l.sectors().size() - 1)
|
||||
? l.sectors().at(0) : l.sectors().at(k+1);
|
||||
quint32 angle = end.angle() - start.angle();
|
||||
|
||||
QRect rect(lightRect(pos, start.range ? start.range : 6));
|
||||
if (start.color() && (angle || start.range() >= MAJOR_RANGE)) {
|
||||
quint32 range = start.range() ? start.range() : 6;
|
||||
Sector s(start.color(), start.angle(), end.angle());
|
||||
if (rangeMap.value(s) >= range)
|
||||
continue;
|
||||
else
|
||||
rangeMap.insert(s, range);
|
||||
|
||||
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine,
|
||||
Qt::FlatCap));
|
||||
painter->drawArc(rect, a1 * 16, as * 16);
|
||||
painter->setPen(QPen(Style::color(start.color), 4,
|
||||
Qt::SolidLine, Qt::FlatCap));
|
||||
painter->drawArc(rect, a1 * 16, as * 16);
|
||||
double a1 = -(end.angle() / 10.0 + 90.0);
|
||||
double a2 = -(start.angle() / 10.0 + 90.0);
|
||||
if (a1 > a2)
|
||||
a2 += 360;
|
||||
double as = (a2 - a1);
|
||||
if (as == 0)
|
||||
as = 360;
|
||||
|
||||
if (a2 - a1 != 0) {
|
||||
QLineF ln(pos, QPointF(pos.x() + rect.width(), pos.y()));
|
||||
ln.setAngle(a1);
|
||||
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
|
||||
painter->drawLine(ln);
|
||||
ln.setAngle(a2);
|
||||
painter->drawLine(ln);
|
||||
QRect rect(lightRect(pos, range));
|
||||
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine,
|
||||
Qt::FlatCap));
|
||||
painter->drawArc(rect, a1 * 16, as * 16);
|
||||
painter->setPen(QPen(Style::color(start.color()), 4,
|
||||
Qt::SolidLine, Qt::FlatCap));
|
||||
painter->drawArc(rect, a1 * 16, as * 16);
|
||||
|
||||
if (angle) {
|
||||
QLineF ln(pos, QPointF(pos.x() + rect.width(),
|
||||
pos.y()));
|
||||
ln.setAngle(a1);
|
||||
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
|
||||
painter->drawLine(ln);
|
||||
ln.setAngle(a2);
|
||||
painter->drawLine(ln);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QRect rect(lightRect(pos, p->lights.range));
|
||||
} else if (l.color() && l.range() >= MAJOR_RANGE) {
|
||||
Sector s(l.color(), 0, 3600);
|
||||
if (rangeMap.value(s) >= l.range())
|
||||
continue;
|
||||
else
|
||||
rangeMap.insert(s, l.range());
|
||||
|
||||
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
|
||||
painter->drawArc(rect, 0, 360 * 16);
|
||||
painter->setPen(QPen(Style::color(p->lights.color), 4,
|
||||
Qt::SolidLine, Qt::FlatCap));
|
||||
painter->drawArc(rect, 0, 360 * 16);
|
||||
QRect rect(lightRect(pos, l.range()));
|
||||
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
|
||||
painter->drawArc(rect, 0, 360 * 16);
|
||||
painter->setPen(QPen(Style::color(l.color()), 4, Qt::SolidLine,
|
||||
Qt::FlatCap));
|
||||
painter->drawArc(rect, 0, 360 * 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void removeDuplicitLabel(QList<TextItem *> &labels, const QString &text,
|
||||
static void removeDuplicitLabel(QList<TextItem*> &labels, const QString &text,
|
||||
const QRectF &tileRect)
|
||||
{
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
@ -456,8 +475,47 @@ void RasterTile::processShields(const QList<MapData::Poly> &lines,
|
||||
}
|
||||
}
|
||||
|
||||
static bool sectorLight(const QVector<Light> &lights)
|
||||
{
|
||||
for (int i = 0; i < lights.size(); i++) {
|
||||
const Light &l = lights.at(i);
|
||||
if (l.color() && l.range() >= MAJOR_RANGE)
|
||||
return true;
|
||||
for (int j = 0; j < l.sectors().size(); j++) {
|
||||
const Light::Sector &start = l.sectors().at(j);
|
||||
const Light::Sector &end = (j == l.sectors().size() - 1)
|
||||
? l.sectors().at(0) : l.sectors().at(j+1);
|
||||
quint32 angle = end.angle() - start.angle();
|
||||
if (start.color() && (angle || start.range() >= MAJOR_RANGE))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Light::Color ordinaryLight(const QVector<Light> &lights)
|
||||
{
|
||||
for (int i = 0; i < lights.size(); i++) {
|
||||
const Light &l = lights.at(i);
|
||||
if (l.color() && l.range() < MAJOR_RANGE)
|
||||
return l.color();
|
||||
for (int j = 0; j < l.sectors().size(); j++) {
|
||||
const Light::Sector &start = l.sectors().at(j);
|
||||
const Light::Sector &end = (j == l.sectors().size() - 1)
|
||||
? l.sectors().at(0) : l.sectors().at(j+1);
|
||||
quint32 angle = end.angle() - start.angle();
|
||||
if (start.color() && !angle && start.range() < MAJOR_RANGE)
|
||||
return start.color();
|
||||
}
|
||||
}
|
||||
|
||||
return Light::None;
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems, QList<const MapData::Point*> &lights)
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lights,
|
||||
QList<const MapData::Point*> §orLights)
|
||||
{
|
||||
std::sort(points.begin(), points.end());
|
||||
|
||||
@ -466,9 +524,10 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
const Style *style = _data->style();
|
||||
const Style::Point &ps = style->point(point.type);
|
||||
bool poi = Style::isPOI(point.type);
|
||||
bool sl = sectorLight(point.lights);
|
||||
|
||||
if (point.lights.isSectorLight())
|
||||
lights.append(&point);
|
||||
if (sl)
|
||||
sectorLights.append(&point);
|
||||
|
||||
const QString *label = point.label.text().isEmpty()
|
||||
? 0 : &(point.label.text());
|
||||
@ -490,15 +549,17 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
|
||||
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
|
||||
color, hcolor, 0, ICON_PADDING);
|
||||
if (item->isValid() && (point.lights.isSectorLight()
|
||||
|| !item->collides(textItems))) {
|
||||
if (item->isValid() && (sl || !item->collides(textItems))) {
|
||||
textItems.append(item);
|
||||
if (point.lights.color && !point.lights.isSectorLight())
|
||||
textItems.append(new TextPointItem(pos + style->lightOffset(),
|
||||
0, 0, style->light(point.lights.color), 0, 0, 0, 0));
|
||||
Light::Color color = ordinaryLight(point.lights);
|
||||
if (color)
|
||||
lights.append(new TextPointItem(pos + style->lightOffset(),
|
||||
0, 0, style->light(color), 0, 0, 0, 0));
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
|
||||
@ -583,8 +644,8 @@ void RasterTile::render()
|
||||
QList<MapData::Poly> polygons;
|
||||
QList<MapData::Poly> lines;
|
||||
QList<MapData::Point> points;
|
||||
QList<TextItem*> textItems;
|
||||
QList<const MapData::Point*> lights;
|
||||
QList<TextItem*> textItems, lights;
|
||||
QList<const MapData::Point*> sectorLights;
|
||||
QImage arrows[2];
|
||||
|
||||
arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio);
|
||||
@ -595,7 +656,7 @@ void RasterTile::render()
|
||||
ll2xy(lines);
|
||||
ll2xy(points);
|
||||
|
||||
processPoints(points, textItems, lights);
|
||||
processPoints(points, textItems, lights, sectorLights);
|
||||
processPolygons(polygons, textItems);
|
||||
processLines(lines, textItems, arrows);
|
||||
|
||||
@ -610,9 +671,11 @@ void RasterTile::render()
|
||||
drawPolygons(&painter, polygons);
|
||||
drawHillShading(&painter);
|
||||
drawLines(&painter, lines);
|
||||
drawSectorLights(&painter, lights);
|
||||
drawTextItems(&painter, lights);
|
||||
drawSectorLights(&painter, sectorLights);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
qDeleteAll(lights);
|
||||
qDeleteAll(textItems);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
|