1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-16 11:54:23 +02:00

Compare commits

..

64 Commits
13.34 ... 13.36

Author SHA1 Message Date
71a757983f Some more obsolete stuff cleanup 2025-02-20 08:57:50 +01:00
cc7209ad70 Removed obsolete stuff 2025-02-20 08:53:04 +01:00
ba49497608 Code cleanup 2025-02-20 08:50:17 +01:00
48404ea43b Limit the sector lights ranges 2025-02-20 07:34:47 +01:00
b9fb9eece3 Use 10NM as the major/minor light threshold 2025-02-19 23:00:39 +01:00
0cac0369aa Distinguish major/minor lights 2025-02-19 22:49:19 +01:00
cdf198ec1d Fixed clazy warning 2025-02-19 22:48:12 +01:00
0896b54831 Improved marine lights presentation 2025-02-19 19:26:14 +01:00
9f1808274f Use Qt 6.8.2 for the OS X builds 2025-02-19 00:49:40 +01:00
5d2465cffc Remove all Qt5 < 5.15 workarounds.
Qt 5.15 is now the minimal required Qt version.
2025-02-19 00:20:18 +01:00
2ab7bff3f8 Cosmetics 2025-02-18 23:11:13 +01:00
060cfb574d Build both release and debug configurations on Linux 2025-02-18 22:44:55 +01:00
5c178b4088 Fixed debug builds 2025-02-18 22:24:43 +01:00
2f4a7f8053 Improved IMG marine style 2025-02-18 22:09:59 +01:00
5f1838ea30 Code cleanup 2025-02-18 22:09:16 +01:00
bdf75169c5 Read the marine lights info from the local navaid data if present 2025-02-17 22:45:24 +01:00
9295f8f4a9 Merge branch 'origin/master' into Weblate. 2025-02-12 23:59:23 +01:00
3fc8e69ebb Removed unused metadata 2025-02-12 23:58:57 +01:00
4438bc8d52 Version++ 2025-02-12 23:46:36 +01:00
f9e99fcc73 Merge branch 'origin/master' into Weblate. 2025-02-12 20:01:32 +01:00
8041aa454c Fixed restricted areas labels colors 2025-02-12 20:01:06 +01:00
f494543e54 Merge branch 'origin/master' into Weblate. 2025-02-12 19:45:34 +01:00
1ee60b4f96 Do not show area labels when the area is not shown 2025-02-12 19:45:11 +01:00
70936cafe3 Merge branch 'origin/master' into Weblate. 2025-02-12 19:14:09 +01:00
ca17ec9e5f Fixed color artefacts 2025-02-12 19:13:32 +01:00
74781d6462 Merge branch 'origin/master' into Weblate. 2025-02-12 19:06:11 +01:00
d3781e7f0b Improved restricted areas rendering 2025-02-12 19:05:47 +01:00
466e8f2909 Merge branch 'origin/master' into Weblate. 2025-02-12 09:05:22 +01:00
c4e44c8796 Alwas show the area pictograms 2025-02-12 09:04:46 +01:00
1c9dd610d5 Merge branch 'origin/master' into Weblate. 2025-02-12 01:55:34 +01:00
59be4aaf1a Unify the lights display logic between ENC ad IMG 2025-02-12 01:55:02 +01:00
538ec4f71b Merge branch 'origin/master' into Weblate. 2025-02-11 08:13:28 +00:00
398ef2c4f5 Code cleanup 2025-02-11 09:13:09 +01:00
9bb56032b0 Merge branch 'origin/master' into Weblate. 2025-02-11 08:25:54 +01:00
5df43d3fb5 Removed forgotten debug stuff 2025-02-11 08:25:25 +01:00
c3e76e1d3d Merge branch 'origin/master' into Weblate. 2025-02-10 23:36:45 +01:00
ac41483530 Handle multi key attributes 2025-02-10 23:36:03 +01:00
766000458d Merge branch 'origin/master' into Weblate. 2025-02-10 19:26:27 +00:00
e0000d7299 Sector lights rendering polishing 2025-02-10 20:25:53 +01:00
9059e6d30d Use a standard color for the pipelines 2025-02-10 20:25:02 +01:00
0d029636be Merge branch 'origin/master' into Weblate. 2025-02-10 09:30:14 +01:00
819a67158a IMG marine lights 2025-02-10 09:29:46 +01:00
89b4bc56e4 Merge branch 'origin/master' into Weblate. 2025-02-09 23:01:10 +01:00
610dd0a009 Fixed function definitions 2025-02-09 23:00:45 +01:00
08d09d038e Merge branch 'origin/master' into Weblate. 2025-02-06 01:25:12 +01:00
41e8b7094a Outline sector lights 2025-02-06 01:24:48 +01:00
02c236a49e Merge branch 'origin/master' into Weblate. 2025-02-06 01:11:17 +01:00
0ee28d7f45 Colored lights + sector lights in ENC maps 2025-02-06 01:10:44 +01:00
98acd3f75a Marine icons polishing 2025-02-06 01:08:53 +01:00
f67c262292 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (488 of 488 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2025-01-27 08:01:49 +01:00
7cfd62ca97 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.7% (487 of 488 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2025-01-26 07:10:38 +01:00
a3459e34e0 Added geo URI support info 2025-01-25 16:19:00 +01:00
d43f58deb9 Added Android geo URI scheme desktop integration 2025-01-25 11:55:15 +01:00
73e7a1dbf4 Added geo URI support info to appdata.xml 2025-01-23 00:55:34 +01:00
319cdbf838 Added support for file scheme URIs 2025-01-23 00:54:23 +01:00
213ab73ceb Properly handle axis order in geo URIs 2025-01-21 21:45:49 +01:00
db2d81042b Use the common URL:$protocol naming scheme 2025-01-21 06:20:37 +01:00
e27bc437fa geo URI Windows desktop integration 2025-01-21 05:34:26 +01:00
3dd21ade19 geo URI MacOS desktop integration 2025-01-20 23:45:36 +01:00
46ea3dd257 geo URI linux desktop integration 2025-01-20 23:45:11 +01:00
0ed630dd20 Added support for geo URIs (RFC 5870) 2025-01-20 23:27:44 +01:00
9cd82319e9 Cosmetics 2025-01-20 23:26:58 +01:00
335df85fae Code cleanup 2025-01-17 07:38:31 +01:00
f1b52c7005 Version++ 2025-01-17 07:37:49 +01:00
75 changed files with 1266 additions and 503 deletions

View File

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

View File

@ -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

View File

@ -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

View File

@ -6,6 +6,7 @@ GPS log file formats.
* 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.
* Opens geo URIs (RFC 5870).
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS,
QuadTiles).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
@ -28,8 +29,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:

View File

@ -3,8 +3,7 @@ unix:!macx:!android {
} else {
TARGET = GPXSee
}
VERSION = 13.34
VERSION = 13.36
QT += core \
gui \
@ -118,6 +117,7 @@ HEADERS += src/common/config.h \
src/data/gpsdumpparser.h \
src/data/style.h \
src/data/twonavparser.h \
src/map/IMG/light.h \
src/map/downloader.h \
src/map/demloader.h \
src/map/ENC/attributes.h \

View File

@ -193,6 +193,10 @@
<file alias="overfalls.png">icons/map/marine/overfalls.png</file>
<file alias="boarding-place.png">icons/map/marine/boarding-place.png</file>
<file alias="light.png">icons/map/marine/light.png</file>
<file alias="light-red.png">icons/map/marine/light-red.png</file>
<file alias="light-green.png">icons/map/marine/light-green.png</file>
<file alias="light-yellow.png">icons/map/marine/light-yellow.png</file>
<file alias="light-white.png">icons/map/marine/light-white.png</file>
<file alias="building.png">icons/map/marine/building.png</file>
<file alias="fog-signal.png">icons/map/marine/fog-signal.png</file>
<file alias="construction.png">icons/map/marine/construction.png</file>
@ -210,6 +214,8 @@
<file alias="24h-anchorage.png">icons/map/marine/24h-anchorage.png</file>
<file alias="dw-anchorage.png">icons/map/marine/dw-anchorage.png</file>
<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>
</qresource>
<!-- Patterns (Mapsforge) -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 266 B

View File

@ -486,17 +486,17 @@
<message>
<location filename="../src/GUI/gui.cpp" line="370"/>
<source>All</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="374"/>
<source>Raster only</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="378"/>
<source>Vector only</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="385"/>
@ -733,7 +733,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="695"/>
<source>Layers</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="704"/>
@ -1692,7 +1692,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="388"/>
<source>Detect pauses</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="391"/>
@ -1796,7 +1796,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="537"/>
<source>Detection:</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="538"/>
@ -1821,7 +1821,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="552"/>
<source>Pause detection</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="564"/>
@ -1870,7 +1870,7 @@
<location filename="../src/GUI/optionsdialog.cpp" line="314"/>
<location filename="../src/GUI/optionsdialog.cpp" line="655"/>
<source>Opacity:</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="657"/>
@ -1922,7 +1922,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="656"/>
<source>Lightening:</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="713"/>

View File

@ -21,6 +21,12 @@
<data android:scheme="content" android:mimeType="image/jpeg"/>
<data android:scheme="content" android:mimeType="image/tiff"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="geo"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/>

View File

@ -17,6 +17,7 @@
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN, ONmove OMD/GHP,
TwoNav (TRK, RTE, WPT), GPSDump WPT and geotagged JPEG
files.</li>
<li>Opens geo URIs (RFC 5870).</li>
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
WMS, TMS, QuadTiles).</li>
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
@ -112,5 +113,6 @@
<mimetype>application/vnd.iho.s57-catalogue</mimetype>
<mimetype>application/vnd.gpsdump.wpt</mimetype>
<mimetype>application/vnd.gpstuner.gmi</mimetype>
<mimetype>x-scheme-handler/geo</mimetype>
</mimetypes>
</component>

View File

@ -11,9 +11,9 @@ Comment[ru]=Программа для просмотра и анализа GPS
Comment[sv]=GPS-loggfilsläsare och analysator
Comment[tr]=GPS günlük dosyası görüntüleyici ve analizcisi
Comment[uk]=Переглядач та аналізатор GPS логів
Exec=gpxsee %F
Exec=gpxsee %U
Icon=gpxsee
Terminal=false
Type=Application
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt
MimeType=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

View File

@ -738,6 +738,20 @@
</dict>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>geo</string>
</array>
<key>CFBundleURLName</key>
<string>org.geouri.geo</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>

View File

@ -18,6 +18,18 @@
DeleteRegKey HKCR ".${EXT}"
!macroend
; URI association
!macro URI_ASSOCIATION_ADD PROTO
WriteRegStr HKCR "${PROTO}" "" "URL:${PROTO}"
WriteRegStr HKCR "${PROTO}" "URL Protocol" ""
WriteRegStr HKCR "${PROTO}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,0"
WriteRegStr HKCR "${PROTO}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
!macroend
!macro URI_ASSOCIATION_REMOVE PROTO
DeleteRegKey HKCR "${PROTO}"
!macroend
; Translations
!macro LOCALIZATION LANG CODE
Section "${LANG}"
@ -37,7 +49,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "13.34"
!define VERSION "13.36"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -200,6 +212,8 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 33
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 34
!insertmacro URI_ASSOCIATION_ADD "geo"
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".tcx\OpenWithList" "GPXSee.exe" ""
@ -426,6 +440,8 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "000"
!insertmacro FILE_ASSOCIATION_REMOVE "031"
!insertmacro URI_ASSOCIATION_REMOVE "geo"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".kml\OpenWithList" "GPXSee.exe"

View File

@ -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();

View File

@ -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);
}

View File

@ -1069,18 +1069,33 @@ void GUI::openDir()
bool GUI::openFile(const QString &fileName, bool tryUnknown, int &showError)
{
QFileInfo fi(fileName);
QString canonicalFileName(fi.canonicalFilePath());
QString path;
if (_files.contains(canonicalFileName))
QUrl url(fileName);
if (url.scheme() == "geo") {
if (loadURL(url, showError)) {
_fileActionGroup->setEnabled(true);
_reloadFileAction->setEnabled(false);
return true;
} else if (showError)
return false;
} else if (url.isLocalFile())
path = url.toLocalFile();
else
path = fileName;
QFileInfo fi(path);
QString canonicalPath(fi.canonicalFilePath());
if (_files.contains(canonicalPath))
return true;
if (!loadFile(fileName, tryUnknown, showError))
if (!loadFile(path, tryUnknown, showError))
return false;
_files.append(canonicalFileName);
_files.append(canonicalPath);
#ifndef Q_OS_ANDROID
_browser->setCurrent(fileName);
_browser->setCurrent(path);
#endif // Q_OS_ANDROID
_fileActionGroup->setEnabled(true);
// Explicitly enable the reload action as it may be disabled by loadMapDir()
@ -1093,12 +1108,42 @@ bool GUI::openFile(const QString &fileName, bool tryUnknown, int &showError)
if (_files.count() > 1)
_mapView->showExtendedInfo(true);
#ifndef Q_OS_ANDROID
updateRecentFiles(canonicalFileName);
updateRecentFiles(canonicalPath);
#endif // Q_OS_ANDROID
return true;
}
bool GUI::loadURL(const QUrl &url, int &showError)
{
Data data(url);
if (data.isValid()) {
loadData(data);
return true;
} else {
if (showError) {
QString error = tr("Error loading geo URI:") + "\n" + url.toString()
+ ": " + data.errorString();
if (showError > 1) {
QMessageBox message(QMessageBox::Critical, APP_NAME, error,
QMessageBox::Ok, this);
QCheckBox checkBox(tr("Don't show again"));
message.setCheckBox(&checkBox);
message.exec();
if (checkBox.isChecked())
showError = 0;
} else
QMessageBox::critical(this, APP_NAME, error);
} else
qWarning("%s: %s", qUtf8Printable(url.toString()),
qUtf8Printable(data.errorString()));
return false;
}
}
bool GUI::loadFile(const QString &fileName, bool tryUnknown, int &showError)
{
Data data(fileName, tryUnknown);
@ -1850,7 +1895,13 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
bool GUI::loadMap(const QString &fileName, MapAction *&action, int &showError)
{
TreeNode<Map*> maps(MapList::loadMaps(fileName, _mapView->inputProjection()));
QString path;
QUrl url(fileName);
path = url.isLocalFile() ? url.toLocalFile() : fileName;
TreeNode<Map*> maps(MapList::loadMaps(path, _mapView->inputProjection()));
QList<QAction*> existingActions(_mapsActionGroup->actions());
return loadMapNode(maps, action, existingActions, showError);
@ -2447,12 +2498,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);

View File

@ -158,6 +158,7 @@ private:
#endif // Q_OS_ANDROID
bool openPOIFile(const QString &fileName);
bool loadFile(const QString &fileName, bool tryUnknown, int &showError);
bool loadURL(const QUrl &url, int &showError);
void loadData(const Data &data);
bool loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
const QList<QAction*> &existingActions, int &showError);

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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())));
}

View File

@ -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())

View File

@ -2,6 +2,7 @@
#include <QFile>
#include <QFileInfo>
#include "common/util.h"
#include "map/crs.h"
#include "gpxparser.h"
#include "tcxparser.h"
#include "csvparser.h"
@ -154,6 +155,70 @@ Data::Data(const QString &fileName, bool tryUnknown)
}
}
Data::Data(const QUrl &url)
{
bool caOk, cbOk, ccOk;
Projection proj(GCS::WGS84());
_valid = false;
QStringList parts(url.path().split(';'));
if (parts.size() < 1) {
_errorString = "Syntax error";
return;
}
QStringList coords(parts.at(0).split(','));
if (coords.size() < 2 || coords.size() > 3) {
_errorString = "Syntax error";
return;
}
double ca = coords.at(0).toDouble(&caOk);
double cb = coords.at(1).toDouble(&cbOk);
double cc = NAN;
if (!(caOk && cbOk)) {
_errorString = "Invalid coordinates";
return;
}
if (coords.size() > 2) {
cc = coords.at(2).toDouble(&ccOk);
if (!ccOk) {
_errorString = "Invalid elevation";
return;
}
}
if (parts.size() > 1) {
QStringList crsp(parts.at(1).split('='));
if (crsp.size() != 2) {
_errorString = "Syntax error";
return;
}
if (!crsp.at(0).compare("crs", Qt::CaseInsensitive)) {
if (crsp.at(1).compare("wgs84", Qt::CaseInsensitive)) {
proj = CRS::projection(crsp.at(1));
if (!proj.isValid()) {
_errorString = "Unknown CRS";
return;
}
}
}
}
CoordinateSystem::AxisOrder ao = proj.coordinateSystem().axisOrder();
PointD p(ao == CoordinateSystem::XY ? PointD(ca, cb) : PointD(cb, ca));
Coordinates c(proj.xy2ll(p));
if (!c.isValid()) {
_errorString = "Invalid coordinates";
return;
}
Waypoint w(c);
w.setElevation(cc);
_waypoints.append(w);
_valid = true;
}
QString Data::formats()
{
return

View File

@ -14,6 +14,7 @@ class Data
{
public:
Data(const QString &fileName, bool tryUnknown = true);
Data(const QUrl &url);
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}

View File

@ -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;

View File

@ -6,6 +6,7 @@
#define CATDIS 21
#define CATHAF 30
#define CATLMK 35
#define CATLIT 37
#define CATMFA 38
#define CATMOR 40
#define CATTRK 54
@ -16,16 +17,21 @@
#define CATWAT 69
#define CATWED 70
#define CATWRK 71
#define COLOUR 75
#define COMCHA 77
#define CURVEL 84
#define DRVAL1 87
#define ELEVAT 90
#define FUNCTN 94
#define LITVIS 108
#define OBJNAM 116
#define ORIENT 117
#define RESTRN 131
#define SECTR1 136
#define SECTR2 137
#define TRAFIC 172
#define VALDCO 174
#define VALNMR 178
#define VERCLR 181
#define WATLEV 187

View File

@ -173,19 +173,41 @@ static bool polygonCb(const MapData::Poly *polygon, void *context)
static bool polygonPointCb(const MapData::Poly *polygon, void *context)
{
QList<MapData::Point> *points = (QList<MapData::Point>*)context;
uint baseType = polygon->type()>>16;
uint type = polygon->type();
uint baseType = type>>16;
if (!polygon->label().isEmpty() || baseType == TSSLPT || baseType == RCTLPT
|| baseType == I_TRNBSN
|| polygon->type() == SUBTYPE(ACHARE, 2)
|| polygon->type() == SUBTYPE(ACHARE, 3)
|| polygon->type() == SUBTYPE(ACHARE, 9)
|| polygon->type() == SUBTYPE(I_ACHARE, 2)
|| polygon->type() == SUBTYPE(I_ACHARE, 3)
|| polygon->type() == SUBTYPE(I_ACHARE, 9)
|| polygon->type() == SUBTYPE(I_BERTHS, 6))
points->append(MapData::Point(polygon->type(), polygon->bounds().center(),
polygon->label(), polygon->param()));
if (baseType == TSSLPT || baseType == RCTLPT || baseType == I_TRNBSN
|| baseType == BRIDGE || baseType == I_BRIDGE || baseType == BUAARE
|| baseType == LNDARE || baseType == LNDRGN
|| type == SUBTYPE(ACHARE, 2) || type == SUBTYPE(I_ACHARE, 2)
|| type == SUBTYPE(ACHARE, 3) || type == SUBTYPE(I_ACHARE, 3)
|| type == SUBTYPE(ACHARE, 9) || type == SUBTYPE(I_ACHARE, 9)
|| type == SUBTYPE(I_BERTHS, 6)
|| type == SUBTYPE(RESARE, 1) || type == SUBTYPE(I_RESARE, 1)
|| type == SUBTYPE(RESARE, 2) || type == SUBTYPE(I_RESARE, 2)
|| type == SUBTYPE(RESARE, 4) || type == SUBTYPE(I_RESARE, 4)
|| type == SUBTYPE(RESARE, 5) || type == SUBTYPE(I_RESARE, 5)
|| type == SUBTYPE(RESARE, 6) || type == SUBTYPE(I_RESARE, 6)
|| type == SUBTYPE(RESARE, 7) || type == SUBTYPE(I_RESARE, 7)
|| type == SUBTYPE(RESARE, 9) || type == SUBTYPE(I_RESARE, 9)
|| type == SUBTYPE(RESARE, 12) || type == SUBTYPE(I_RESARE, 12)
|| type == SUBTYPE(RESARE, 17) || type == SUBTYPE(I_RESARE, 17)
|| type == SUBTYPE(RESARE, 22) || type == SUBTYPE(I_RESARE, 22)
|| type == SUBTYPE(RESARE, 23) || type == SUBTYPE(I_RESARE, 23))
points->append(MapData::Point(baseType, polygon->bounds().center(),
polygon->attributes(), polygon->HUNI(), true));
return true;
}
static bool linePointCb(const MapData::Line *line, void *context)
{
QList<MapData::Point> *points = (QList<MapData::Point>*)context;
uint baseType = line->type()>>16;
if (baseType == RDOCAL || baseType == I_RDOCAL)
points->append(MapData::Point(baseType, line->bounds().center(),
line->attributes(), 1));
return true;
}
@ -207,10 +229,8 @@ static Coordinates point(const ISO8211::Record &r, uint COMF)
return coordinates(x, y, COMF);
}
static uint depthLevel(const QByteArray &ba)
static uint depthLevel(double minDepth)
{
double minDepth = ba.isEmpty() ? -1 : ba.toDouble();
if (minDepth < 0)
return 0;
else if (minDepth < 2)
@ -275,72 +295,171 @@ static QString weed(uint type)
}
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
const QVector<QByteArray> &params) : _type(type), _pos(c), _label(label)
static uint restrictionCategory(uint type, const MapData::Attributes &attr)
{
_id = ((quint64)order(type))<<32 | (uint)qHash(c);
uint catrea = attr.value(CATREA).toUInt();
if (type>>16 == I_DISMAR && params.size()) {
_label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0));
_type = SUBTYPE(I_DISMAR, type & 0xFF);
} else if ((type>>16 == I_RDOCAL || type>>16 == RDOCAL) && params.size() > 1) {
if (!params.at(1).isEmpty())
_label = QString("VHF ") + QString::fromLatin1(params.at(1));
_param = QVariant(params.at(0).toDouble());
} else if (type>>16 == CURENT && params.size() > 1) {
if (!params.at(1).isEmpty())
_label = QString::fromLatin1(params.at(1))
+ QString::fromUtf8("\xE2\x80\x89kt");
_param = QVariant(params.at(0).toDouble());
} else if (type>>16 == I_SISTAT || type>>16 == SISTAT) {
if (!catrea) {
uint restrn = attr.value(
(type == RESARE) ? RESTRN : I_RESTRN).toUInt();
if (restrn == 1)
return 2;
else if (restrn == 7)
return 17;
else
return 0;
} else
return catrea;
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label)
: _type(SUBTYPE(type, 0)), _pos(c), _label(label), _polygon(false)
{
_id = ((quint64)order(_type))<<32 | (uint)qHash(c);
}
MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr,
uint HUNI, bool polygon) : _pos(c), _attr(attr), _polygon(polygon)
{
uint subtype = 0;
if (type == HRBFAC)
subtype = CATHAF;
else if (type == I_HRBFAC)
subtype = I_CATHAF;
else if (type == LNDMRK)
subtype = CATLMK;
else if (type == WRECKS)
subtype = CATWRK;
else if (type == MORFAC)
subtype = CATMOR;
else if (type == UWTROC)
subtype = WATLEV;
else if (type == BUAARE)
subtype = CATBUA;
else if (type == SMCFAC)
subtype = CATSCF;
else if (type == BUISGL)
subtype = FUNCTN;
else if (type == WATTUR)
subtype = CATWAT;
else if (type == RDOCAL)
subtype = TRAFIC;
else if (type == I_RDOCAL)
subtype = TRAFIC;
else if (type == SILTNK)
subtype = CATSIL;
else if (type == WEDKLP)
subtype = CATWED;
else if (type == LIGHTS)
subtype = CATLIT;
else if (type == I_DISMAR)
subtype = CATDIS;
else if (type == I_BERTHS)
subtype = I_CATBRT;
else if (type == ACHARE)
subtype = CATACH;
else if (type == I_ACHARE)
subtype = I_CATACH;
QList<QByteArray> list(_attr.value(subtype).split(','));
std::sort(list.begin(), list.end());
_type = (type == RESARE || type == I_RESARE)
? SUBTYPE(type, restrictionCategory(type, _attr))
: SUBTYPE(type, list.first().toUInt());
_id = ((quint64)order(_type))<<32 | (uint)qHash(c);
_label = QString::fromLatin1(_attr.value(OBJNAM));
if (type == I_DISMAR) {
if (_attr.contains(I_WTWDIS) && _attr.contains(I_HUNITS))
_label = hUnits(_attr.value(I_HUNITS).toUInt()) + " "
+ QString::fromLatin1(_attr.value(I_WTWDIS));
} else if (type == I_RDOCAL || type == RDOCAL) {
QByteArray cc(_attr.value(COMCHA));
if (!cc.isEmpty())
_label = QString("VHF ") + QString::fromLatin1(cc);
} else if (type == CURENT) {
QByteArray cv(_attr.value(CURVEL));
if (!cv.isEmpty())
_label = QString::fromLatin1(cv) + QString::fromUtf8("\xE2\x80\x89kt");
} else if (type == SISTAT) {
if (_label.isEmpty() && _attr.contains(CATSIT))
_label = sistat(_attr.value(CATSIT).toUInt());
} else if (type == I_SISTAT) {
if (_label.isEmpty() && _attr.contains(I_CATSIT))
_label = sistat(_attr.value(I_CATSIT).toUInt());
} else if (type == WEDKLP) {
if (_label.isEmpty())
_label = sistat(type & 0xFF);
_type = TYPE(SISTAT);
} else if (type>>16 == WEDKLP) {
_label = weed(_type & 0xFF);
} else if (type == LNDELV) {
if (_label.isEmpty())
_label = weed(type & 0xFF);
} else if (type>>16 == LNDELV && params.size()) {
if (_label.isEmpty())
_label = QString::fromLatin1(params.at(0))
_label = QString::fromLatin1(_attr.value(ELEVAT))
+ QString::fromUtf8("\xE2\x80\x89m");
else
_label += "\n(" + QString::fromLatin1(params.at(0))
_label += "\n(" + QString::fromLatin1(_attr.value(ELEVAT))
+ "\xE2\x80\x89m)";
} else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size())
_param = QVariant(params.at(0).toDouble());
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
const QVariant &param) : _type(type), _pos(c), _label(label), _param(param)
{
_id = ((quint64)order(type))<<32 | (uint)qHash(c);
}
MapData::Poly::Poly(uint type, const Polygon &path, const QString &label,
const QVector<QByteArray> &params, uint HUNI) : _type(type), _path(path)
{
if (type == TYPE(DEPARE) && params.size())
_type = SUBTYPE(DEPARE, depthLevel(params.at(0)));
else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size())
_param = QVariant(params.at(0).toDouble());
else if ((type == TYPE(BRIDGE) || type == TYPE(I_BRIDGE))
&& params.size()) {
double clr = params.at(0).toDouble();
} else if (type == BRIDGE || type == I_BRIDGE) {
double clr = _attr.value(VERCLR).toDouble();
if (clr > 0) {
_label = QString::fromUtf8("\xE2\x86\x95") + UNIT_SPACE
+ QString::number(clr) + UNIT_SPACE + hUnits(HUNI);
}
} else if (type>>16 == LNDARE || type>>16 == SEAARE || type>>16 == BERTHS
|| type>>16 == I_BERTHS || type>>16 == BUAARE)
_label = label;
}
}
MapData::Poly::Poly(uint type, const Polygon &path, const Attributes &attr,
uint HUNI) : _path(path), _attr(attr), _HUNI(HUNI)
{
uint subtype = 0;
if (type == ACHARE)
subtype = CATACH;
else if (type == I_ACHARE)
subtype = I_CATACH;
else if (type == HRBFAC)
subtype = CATHAF;
else if (type == MARKUL)
subtype = CATMFA;
else if (type == I_BERTHS)
subtype = I_CATBRT;
switch (type) {
case DEPARE:
_type = SUBTYPE(type, depthLevel(_attr.value(DRVAL1).toDouble()));
break;
case RESARE:
case I_RESARE:
_type = SUBTYPE(type, restrictionCategory(type, attr));
break;
default:
_type = SUBTYPE(type, _attr.value(subtype).toUInt());
}
}
MapData::Line::Line(uint type, const QVector<Coordinates> &path,
const QString &label, const QVector<QByteArray> &params)
: _type(type), _path(path), _label(label)
const Attributes &attr) : _path(path), _attr(attr)
{
if ((type == TYPE(DEPCNT) || type == TYPE(LNDELV)) && params.size())
_label = QString::fromLatin1(params.at(0));
uint subtype = 0;
if (type == RECTRC)
subtype = CATTRK;
else if (type == RCRTCL)
subtype = CATTRK;
else if (type == RDOCAL)
subtype = TRAFIC;
else if (type == I_RDOCAL)
subtype = TRAFIC;
_type = SUBTYPE(type, _attr.value(subtype).toUInt());
if (type == DEPCNT)
_label = QString::fromLatin1(_attr.value(VALDCO));
else if (type == LNDELV)
_label = QString::fromLatin1(_attr.value(ELEVAT));
else
_label = QString::fromLatin1(_attr.value(OBJNAM));
}
RectC MapData::Line::bounds() const
@ -581,169 +700,46 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
return path;
}
MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
MapData::Attributes MapData::attributes(const ISO8211::Record &r)
{
QString label;
QVector<QByteArray> params(2);
uint subtype = 0;
Attributes attr;
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2))
return Attr();
return attr;
for (int i = 0; i < ATTF->data().size(); i++) {
const QVector<QVariant> &av = ATTF->data().at(i);
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == HRBFAC && key == CATHAF)
|| (OBJL == I_HRBFAC && key == I_CATHAF)
|| (OBJL == LNDMRK && key == CATLMK)
|| (OBJL == WRECKS && key == CATWRK)
|| (OBJL == MORFAC && key == CATMOR)
|| (OBJL == UWTROC && key == WATLEV)
|| (OBJL == BUAARE && key == CATBUA)
|| (OBJL == SMCFAC && key == CATSCF)
|| (OBJL == BUISGL && key == FUNCTN)
|| (OBJL == WATTUR && key == CATWAT)
|| (OBJL == SISTAT && key == CATSIT)
|| (OBJL == I_SISTAT && key == I_CATSIT)
|| (OBJL == RDOCAL && key == TRAFIC)
|| (OBJL == I_RDOCAL && key == TRAFIC)
|| (OBJL == SILTNK && key == CATSIL)
|| (OBJL == WEDKLP && key == CATWED))
subtype = av.at(1).toByteArray().toUInt();
else if (OBJL == I_DISMAR && key == CATDIS)
subtype |= av.at(1).toByteArray().toUInt();
else if (OBJL == I_DISMAR && key == I_HUNITS)
subtype |= av.at(1).toByteArray().toUInt() << 8;
if ((OBJL == I_DISMAR && key == I_WTWDIS)
|| (OBJL == RDOCAL && key == ORIENT)
|| (OBJL == I_RDOCAL && key == ORIENT)
|| (OBJL == CURENT && key == ORIENT)
|| (OBJL == LNDELV && key == ELEVAT)
|| (OBJL == TSSLPT && key == ORIENT)
|| (OBJL == RCTLPT && key == ORIENT))
params[0] = av.at(1).toByteArray();
if ((OBJL == I_RDOCAL && key == COMCHA)
|| (OBJL == RDOCAL && key == COMCHA)
|| (OBJL == CURENT && key == CURVEL))
params[1] = av.at(1).toByteArray();
attr.insert(av.at(0).toUInt(), av.at(1).toByteArray());
}
return Attr(subtype, label, params);
}
MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QVector<QByteArray> params(1);
uint subtype = 0;
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);
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == RECTRC || OBJL == RCRTCL) && key == CATTRK)
subtype = av.at(1).toByteArray().toUInt();
if ((OBJL == DEPCNT && key == VALDCO)
|| (OBJL == LNDELV && key == ELEVAT))
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, params);
}
MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QVector<QByteArray> params(1);
uint subtype = 0;
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);
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == RESARE && key == CATREA)
|| (OBJL == I_RESARE && key == CATREA)
|| (OBJL == ACHARE && key == CATACH)
|| (OBJL == I_ACHARE && key == I_CATACH)
|| (OBJL == HRBFAC && key == CATHAF)
|| (OBJL == MARKUL && key == CATMFA)
|| (OBJL == I_BERTHS && key == I_CATBRT))
subtype = av.at(1).toByteArray().toUInt();
else if ((OBJL == RESARE && key == RESTRN)
|| (OBJL == I_RESARE && key == I_RESTRN)) {
if (av.at(1).toByteArray().toUInt() == 1)
subtype = 2;
if (av.at(1).toByteArray().toUInt() == 7)
subtype = 17;
}
if ((OBJL == TSSLPT && key == ORIENT)
|| (OBJL == RCTLPT && key == ORIENT)
|| (OBJL == DEPARE && key == DRVAL1))
params[0] = av.at(1).toByteArray();
if ((OBJL == BRIDGE && key == VERCLR)
|| (OBJL == I_BRIDGE && key == VERCLR))
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, params);
return attr;
}
MapData::Point *MapData::pointObject(const Sounding &s)
{
return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth),
QVector<QByteArray>());
return new Point(SOUNDG, s.c, QString::number(s.depth));
}
MapData::Point *MapData::pointObject(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL)
const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL, uint HUNI)
{
Coordinates c(pointGeometry(r, vi, vc, COMF));
Attr attr(pointAttr(r, OBJL));
return (c.isNull() ? 0 : new Point(SUBTYPE(OBJL,attr.subtype()), c,
attr.label(), attr.params()));
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)
{
QVector<Coordinates> path(lineGeometry(r, vc, ve, COMF));
Attr attr(lineAttr(r, OBJL));
return (path.isEmpty() ? 0 : new Line(SUBTYPE(OBJL, attr.subtype()), path,
attr.label(), attr.params()));
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)
{
Polygon path(polyGeometry(r, vc, ve, COMF));
Attr attr(polyAttr(r, OBJL));
return (path.isEmpty() ? 0 : new Poly(SUBTYPE(OBJL, attr.subtype()), path,
attr.label(), attr.params(), HUNI));
return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI));
}
bool MapData::processRecord(const ISO8211::Record &record,
@ -828,7 +824,7 @@ MapData::MapData(const QString &path)
_points.Insert(min, max, point);
}
} else {
if ((point = pointObject(r, vi, vc, COMF, OBJL))) {
if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) {
pointBounds(point->pos(), min, max);
_points.Insert(min, max, point);
} else
@ -875,6 +871,7 @@ void MapData::points(const RectC &rect, QList<Point> *points) const
rectcBounds(rect, min, max);
_points.Search(min, max, pointCb, points);
_areas.Search(min, max, polygonPointCb, points);
_lines.Search(min, max, linePointCb, points);
}
void MapData::lines(const RectC &rect, QList<Line> *lines) const

View File

@ -11,51 +11,53 @@ namespace ENC {
class MapData
{
public:
typedef QMap<uint, QByteArray> Attributes;
class Poly {
public:
Poly(uint type, const Polygon &path, const QString &label,
const QVector<QByteArray> &params, uint HUNI);
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 QString &label() const {return _label;}
const QVariant &param() const {return _param;}
const Attributes &attributes() const {return _attr;}
uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
QString _label;
QVariant _param;
Attributes _attr;
uint _HUNI;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const QString &label,
const QVector<QByteArray> &params);
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 QString &label,
const QVector<QByteArray> &params);
Point(uint type, const Coordinates &c, const QString &label,
const QVariant &param);
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 QVariant &param() const {return _param;}
const Attributes &attributes() const {return _attr;}
bool polygon() const {return _polygon;}
bool operator<(const Point &other) const
{return _id < other._id;}
@ -65,7 +67,8 @@ public:
Coordinates _pos;
QString _label;
quint64 _id;
QVariant _param;
Attributes _attr;
bool _polygon;
};
MapData(const QString &path);
@ -76,23 +79,6 @@ public:
void points(const RectC &rect, QList<Point> *points) const;
private:
class Attr {
public:
Attr() : _subtype(0) {}
Attr(uint subtype, const QString &label,
const QVector<QByteArray> &params)
: _subtype(subtype), _label(label), _params(params) {}
unsigned subtype() const {return _subtype;}
const QString &label() const {return _label;}
const QVector<QByteArray> &params() const {return _params;}
private:
unsigned _subtype;
QString _label;
QVector<QByteArray> _params;
};
struct Sounding {
Sounding() : depth(NAN) {}
Sounding(const Coordinates &c, double depth) : c(c), depth(depth) {}
@ -117,12 +103,10 @@ private:
const RecordMap &vc, const RecordMap &ve, uint COMF);
static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint COMF);
static Attr pointAttr(const ISO8211::Record &r, uint OBJL);
static Attr lineAttr(const ISO8211::Record &r, uint OBJL);
static Attr polyAttr(const ISO8211::Record &r, uint OBJL);
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);
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);
static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc,

View File

@ -51,6 +51,7 @@
#define LAKARE 69
#define LNDARE 71
#define LNDELV 72
#define LNDRGN 73
#define LNDMRK 74
#define LIGHTS 75
#define LOKBSN 79

View File

@ -5,6 +5,7 @@
#include "map/textpointitem.h"
#include "map/rectd.h"
#include "objects.h"
#include "attributes.h"
#include "style.h"
#include "rastertile.h"
@ -12,8 +13,8 @@ using namespace ENC;
#define TEXT_EXTENT 160
#define TSSLPT_SIZE 24
typedef QSet<Coordinates> PointSet;
#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);
@ -138,21 +139,21 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type)
}
void RasterTile::drawArrows(QPainter *painter,
const QList<MapData::Point> &points)
const QList<MapData::Point> &points) const
{
for (int i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
deg2rad(point.param().toDouble())));
deg2rad(point.attributes().value(ORIENT).toDouble())));
drawArrow(painter, polygon, point.type());
}
}
}
void RasterTile::drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons)
const QList<MapData::Poly> &polygons) const
{
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
@ -184,7 +185,7 @@ void RasterTile::drawPolygons(QPainter *painter,
}
}
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines)
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines) const
{
painter->setBrush(Qt::NoBrush);
@ -202,7 +203,7 @@ void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines)
}
void RasterTile::drawTextItems(QPainter *painter,
const QList<TextItem*> &textItems)
const QList<TextItem*> &textItems) const
{
QRectF rect(_rect);
@ -213,10 +214,56 @@ void RasterTile::drawTextItems(QPainter *painter,
}
}
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights)
static QRectF lightRect(const QPointF &pos, double range)
{
PointSet lightsSet, signalsSet;
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
{
for (int i = 0; i < lights.size(); i++) {
const SectorLight &l = lights.at(i);
QPointF pos(ll2xy(l.pos));
QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range));
double a1 = -(l.end + 90);
double a2 = -(l.start + 90);
if (a1 > a2)
a2 += 360;
double as = (a2 - a1);
if (as == 0)
as = 360;
if (l.visibility == 3 || l.visibility >= 6)
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
else {
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
painter->drawArc(rect, a1 * 16, as * 16);
painter->setPen(QPen(Style::color(l.color), 4, Qt::SolidLine,
Qt::FlatCap));
}
painter->drawArc(rect, a1 * 16, as * 16);
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);
}
}
}
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<SectorLight> &sectorLights)
{
LightMap lightsMap;
SignalSet signalsSet;
QSet<Coordinates> slMap;
int i;
std::sort(points.begin(), points.end());
@ -224,9 +271,21 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
/* Lights & Signals */
for (i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
if (point.type()>>16 == LIGHTS)
lightsSet.insert(point.pos());
else if (point.type()>>16 == FOGSIG)
if (point.type()>>16 == LIGHTS) {
const MapData::Attributes &attr = point.attributes();
Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
double range = attr.value(VALNMR).toDouble();
if (attr.contains(SECTR1)
|| (range >= MAJOR_RANGE && !(point.type() & 0xFFFF))) {
sectorLights.append(SectorLight(point.pos(), color,
attr.value(LITVIS).toUInt(), range,
attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble()));
slMap.insert(point.pos());
} else
lightsMap.insert(point.pos(), color);
} else if (point.type()>>16 == FOGSIG)
signalsSet.insert(point.pos());
else
break;
@ -245,7 +304,7 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
? &style.haloColor() : 0;
double rotate = angle(point.type(), point.param());
double rotate = angle(point.type(), point.attributes().value(ORIENT));
if ((!label || !fnt) && !img)
continue;
@ -254,11 +313,12 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
color, hColor, 0, 2, rotate);
if (item->isValid() && !item->collides(textItems)) {
if (item->isValid() && (slMap.contains(point.pos())
|| (point.polygon() && img) || !item->collides(textItems))) {
textItems.append(item);
if (lightsSet.contains(point.pos()))
if (lightsMap.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->lightOffset(),
0, 0, _style->light(), 0, 0, 0, 0));
0, 0, _style->light(lightsMap.value(point.pos())), 0, 0, 0, 0));
if (signalsSet.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->signalOffset(),
0, 0, _style->signal(), 0, 0, 0, 0));
@ -326,13 +386,14 @@ void RasterTile::render()
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);
processPoints(points, textItems, lights, sectorLights);
processLines(lines, textItems);
QPainter painter(&img);
@ -344,7 +405,9 @@ void RasterTile::render()
drawLines(&painter, lines);
drawArrows(&painter, points);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);

View File

@ -34,6 +34,23 @@ public:
void render();
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) {}
Coordinates pos;
Style::Color color;
uint visibility;
double range;
double start;
double end;
};
typedef QMap<Coordinates, Style::Color> LightMap;
typedef QSet<Coordinates> SignalSet;
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines,
QList<MapData::Point> &points);
QPointF ll2xy(const Coordinates &c) const
@ -44,15 +61,15 @@ private:
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<TextItem*> &textItems, QList<TextItem *> &lights,
QList<SectorLight> &sectorLights);
void processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems);
void drawBitmapPath(QPainter *painter, const QImage &img,
const Polygon &polygon);
void drawArrows(QPainter *painter, const QList<MapData::Point> &points);
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
void drawLines(QPainter *painter, const QList<MapData::Line> &lines);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void drawArrows(QPainter *painter, const QList<MapData::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<MapData::Line> &lines) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights) const;
static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context);

View File

@ -70,17 +70,26 @@ void Style::polygonStyle()
_polygons[TYPE(DRGARE)] = Polygon(QBrush(QColor(0xa0, 0xa0, 0xff),
Qt::Dense4Pattern));
_polygons[TYPE(UNSARE)] = Polygon(QBrush(QColor(0x99, 0x99, 0x99)));
_polygons[SUBTYPE(RESARE, 1)] = Polygon(QImage(":/marine/safety-zone-line.png"));
_polygons[SUBTYPE(RESARE, 2)] = Polygon(QImage(":/marine/noanchor-line.png"));
_polygons[SUBTYPE(RESARE, 4)] = Polygon(QImage(":/marine/nature-reserve-line.png"));
_polygons[SUBTYPE(RESARE, 5)] = Polygon(QImage(":/marine/sanctuary-line.png"));
_polygons[SUBTYPE(RESARE, 6)] = Polygon(QImage(":/marine/sanctuary-line.png"));
_polygons[SUBTYPE(RESARE, 7)] = Polygon(QImage(":/marine/sanctuary-line.png"));
_polygons[SUBTYPE(RESARE, 9)] = Polygon(QBrush(QColor(0xff, 0x00, 0x00),
Qt::BDiagPattern));
_polygons[SUBTYPE(RESARE, 2)] = Polygon(QImage(":/marine/noanchor-line.png"));
_polygons[SUBTYPE(I_RESARE, 2)] = Polygon(QImage(":/marine/noanchor-line.png"));
_polygons[SUBTYPE(RESARE, 17)] = Polygon(
QImage(":/marine/entry-prohibited-line.png"));
_polygons[SUBTYPE(I_RESARE, 17)] = Polygon(
QImage(":/marine/entry-prohibited-line.png"));
_polygons[SUBTYPE(RESARE, 12)] = Polygon(QImage(":/marine/safety-zone-line.png"));
_polygons[SUBTYPE(I_RESARE, 12)] = Polygon(QImage(":/marine/safety-zone-line.png"));
_polygons[SUBTYPE(RESARE, 1)] = Polygon(QImage(":/marine/safety-zone-line.png"));
_polygons[SUBTYPE(RESARE, 17)] = Polygon(QImage(":/marine/entry-prohibited-line.png"));
_polygons[SUBTYPE(RESARE, 22)] = Polygon(QImage(":/marine/sanctuary-line.png"));
_polygons[SUBTYPE(RESARE, 23)] = Polygon(QImage(":/marine/nature-reserve-line.png"));
_polygons[SUBTYPE(I_RESARE, 1)] = _polygons[SUBTYPE(RESARE, 1)];
_polygons[SUBTYPE(I_RESARE, 2)] = _polygons[SUBTYPE(RESARE, 2)];
_polygons[SUBTYPE(I_RESARE, 4)] = _polygons[SUBTYPE(RESARE, 4)];
_polygons[SUBTYPE(I_RESARE, 9)] = _polygons[SUBTYPE(RESARE, 9)];
_polygons[SUBTYPE(I_RESARE, 12)] = _polygons[SUBTYPE(RESARE, 12)];
_polygons[SUBTYPE(I_RESARE, 17)] = _polygons[SUBTYPE(RESARE, 17)];
_polygons[SUBTYPE(I_RESARE, 22)] = _polygons[SUBTYPE(RESARE, 22)];
_polygons[SUBTYPE(I_RESARE, 23)] = _polygons[SUBTYPE(RESARE, 23)];
_polygons[SUBTYPE(ACHARE, 1)] = Polygon(QImage(":/marine/anchor-line.png"));
_polygons[SUBTYPE(ACHARE, 2)] = _polygons[SUBTYPE(ACHARE, 1)];
_polygons[SUBTYPE(ACHARE, 3)] = _polygons[SUBTYPE(ACHARE, 1)];
@ -162,9 +171,14 @@ void Style::polygonStyle()
<< SUBTYPE(I_ACHARE, 2) << SUBTYPE(I_ACHARE, 3) << SUBTYPE(I_ACHARE, 4)
<< SUBTYPE(I_ACHARE, 5) << SUBTYPE(I_ACHARE, 6) << SUBTYPE(I_ACHARE, 7)
<< SUBTYPE(I_ACHARE, 8) << SUBTYPE(I_ACHARE, 9) << SUBTYPE(I_ACHARE, 10)
<< SUBTYPE(I_ACHARE, 11) << SUBTYPE(I_ACHARE, 12) << SUBTYPE(RESARE, 9)
<< SUBTYPE(RESARE, 2) << SUBTYPE(I_RESARE, 2) << SUBTYPE(RESARE, 17)
<< SUBTYPE(I_RESARE, 17) << SUBTYPE(RESARE, 12) << SUBTYPE(I_RESARE, 12)
<< SUBTYPE(I_ACHARE, 11) << SUBTYPE(I_ACHARE, 12) << SUBTYPE(RESARE, 1)
<< SUBTYPE(I_RESARE, 1) << SUBTYPE(RESARE, 2) << SUBTYPE(I_RESARE, 2)
<< SUBTYPE(RESARE, 4) << SUBTYPE(I_RESARE, 4) << SUBTYPE(RESARE, 5)
<< SUBTYPE(I_RESARE, 5) << SUBTYPE(RESARE, 6) << SUBTYPE(I_RESARE, 6)
<< SUBTYPE(RESARE, 7) << SUBTYPE(I_RESARE, 7) << SUBTYPE(RESARE, 9)
<< SUBTYPE(I_RESARE, 9) << SUBTYPE(RESARE, 12) << SUBTYPE(I_RESARE, 12)
<< 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);
}
@ -222,6 +236,14 @@ void Style::lineStyle(qreal ratio)
_lines[TYPE(PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png"));
_lines[TYPE(I_PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png"));
_lines[TYPE(CANALS)] = Line(QPen(QColor(0x9f, 0xc4, 0xe1), 2));
_lines[SUBTYPE(RDOCAL, 1)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 2)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 3)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 4)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
}
void Style::pointStyle(qreal ratio)
@ -302,7 +324,9 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(I_HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png"));
_points[SUBTYPE(I_HRBFAC, 9)] = Point(QImage(":/marine/shipyard.png"));
_points[TYPE(ACHBRT)] = Point(QImage(":/marine/anchorage.png"));
_points[TYPE(I_ACHBRT)] = Point(QImage(":/marine/anchorage.png"));
_points[TYPE(ACHBRT)].setTextColor(QColor(0xeb, 0x49, 0xeb));
_points[TYPE(ACHBRT)].setHaloColor(QColor());
_points[TYPE(I_ACHBRT)] = _points[TYPE(ACHBRT)];
_points[TYPE(OFSPLF)] = Point(QImage(":/marine/platform.png"));
_points[TYPE(PILPNT)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 1)] = Point(QImage(":/marine/pile.png"), Small);
@ -366,10 +390,14 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(WEDKLP, 0)] = Point(QImage(":/marine/kelp.png"));
_points[SUBTYPE(WEDKLP, 1)] = Point(QImage(":/marine/kelp.png"));
_points[TYPE(SEAARE)].setHaloColor(QColor());
_points[TYPE(LNDARE)].setHaloColor(QColor());
_points[TYPE(LNDRGN)].setHaloColor(QColor());
_points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png"));
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"),
Small);
_points[SUBTYPE(I_BERTHS, 6)].setTextColor(QColor(0xeb, 0x49, 0xeb));
_points[SUBTYPE(I_BERTHS, 6)].setHaloColor(QColor());
_points[SUBTYPE(ACHARE, 2)] = Point(QImage(":/marine/dw-anchorage.png"),
Small);
_points[SUBTYPE(ACHARE, 3)] = Point(QImage(":/marine/tanker-anchorage.png"),
@ -379,6 +407,30 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(I_ACHARE, 2)] = _points[SUBTYPE(ACHARE, 2)];
_points[SUBTYPE(I_ACHARE, 3)] = _points[SUBTYPE(ACHARE, 3)];
_points[SUBTYPE(I_ACHARE, 9)] = _points[SUBTYPE(ACHARE, 9)];
_points[SUBTYPE(RESARE, 1)].setTextColor(QColor(0xeb, 0x49, 0xeb));
_points[SUBTYPE(RESARE, 1)].setHaloColor(QColor());
_points[SUBTYPE(RESARE, 2)] = _points[SUBTYPE(RESARE, 1)];
_points[SUBTYPE(RESARE, 4)].setTextColor(QColor(0x30, 0xa0, 0x1b));
_points[SUBTYPE(RESARE, 4)].setHaloColor(QColor());
_points[SUBTYPE(RESARE, 5)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(RESARE, 6)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(RESARE, 7)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(RESARE, 9)] = _points[SUBTYPE(RESARE, 1)];
_points[SUBTYPE(RESARE, 12)] = _points[SUBTYPE(RESARE, 1)];
_points[SUBTYPE(RESARE, 17)] = _points[SUBTYPE(RESARE, 1)];
_points[SUBTYPE(RESARE, 22)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(RESARE, 23)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(I_RESARE, 1)] = _points[SUBTYPE(RESARE, 1)];
_points[SUBTYPE(I_RESARE, 2)] = _points[SUBTYPE(RESARE, 2)];
_points[SUBTYPE(I_RESARE, 4)] = _points[SUBTYPE(RESARE, 4)];
_points[SUBTYPE(I_RESARE, 5)] = _points[SUBTYPE(RESARE, 5)];
_points[SUBTYPE(I_RESARE, 6)] = _points[SUBTYPE(RESARE, 6)];
_points[SUBTYPE(I_RESARE, 7)] = _points[SUBTYPE(RESARE, 7)];
_points[SUBTYPE(I_RESARE, 9)] = _points[SUBTYPE(RESARE, 9)];
_points[SUBTYPE(I_RESARE, 12)] = _points[SUBTYPE(RESARE, 12)];
_points[SUBTYPE(I_RESARE, 17)] = _points[SUBTYPE(RESARE, 17)];
_points[SUBTYPE(I_RESARE, 22)] = _points[SUBTYPE(RESARE, 22)];
_points[SUBTYPE(I_RESARE, 23)] = _points[SUBTYPE(RESARE, 23)];
_points[SUBTYPE(SMCFAC, 7)] = Point(svg2img(":/POI/restaurant-11.svg",
ratio), Small);
@ -427,6 +479,9 @@ void Style::pointStyle(qreal ratio)
Style::Style(qreal ratio)
{
_light = QImage(":/marine/light.png");
_lightRed = QImage(":/marine/light-red.png");
_lightGreen = QImage(":/marine/light-green.png");
_lightYellow = QImage(":/marine/light-yellow.png");
_lightOffset = QPoint(11, 11);
_signal = QImage(":/marine/fog-signal.png");
_signalOffset = QPoint(-9, 9);
@ -477,3 +532,37 @@ const QFont *Style::font(Style::FontSize size) const
return &_normal;
}
}
const QImage *Style::light(Color color) const
{
switch (color) {
case Red:
return &_lightRed;
case Green:
return &_lightGreen;
case White:
case Yellow:
case Amber:
case Orange:
return &_lightYellow;
default:
return &_light;
}
}
QColor Style::color(Style::Color c)
{
switch (c) {
case Red:
return Qt::red;
case Green:
return Qt::green;
case White:
case Yellow:
case Amber:
case Orange:
return Qt::yellow;
default:
return Qt::magenta;
}
}

View File

@ -89,6 +89,11 @@ public:
QPoint _offset;
};
enum Color {
Unknown, White, Black, Red, Green, Blue, Yellow, Gray,
Brown, Amber, Violet, Orange, Magenta, Pink
};
Style(qreal ratio);
const Line &line(uint type) const;
@ -97,11 +102,13 @@ public:
const QVector<uint> &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size) const;
const QImage *light() const {return &_light;}
const QImage *light(Color color) const;
const QImage *signal() const {return &_signal;}
const QPoint &lightOffset() const {return _lightOffset;}
const QPoint &signalOffset() const {return _signalOffset;}
static QColor color(Color c);
private:
void polygonStyle();
void lineStyle(qreal ratio);
@ -114,7 +121,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */
QFont _small, _normal, _large;
QImage _light, _signal;
QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
QPoint _lightOffset, _signalOffset;
};

View File

@ -111,3 +111,13 @@ double DEMTree::elevation(const Coordinates &c) const
return ele;
}
MatrixD DEMTree::elevation(const MatrixC &m) const
{
MatrixD ret(m.h(), m.w());
for (int i = 0; i < m.size(); i++)
ret.at(i) = elevation(m.at(i));
return ret;
}

View File

@ -2,6 +2,7 @@
#define IMG_DEMTREE_H
#include "common/rtree.h"
#include "map/matrix.h"
#include "mapdata.h"
namespace IMG {
@ -11,6 +12,7 @@ public:
DEMTree(const QList<MapData::Elevation> &tiles);
double elevation(const Coordinates &c) const;
MatrixD elevation(const MatrixC &m) const;
private:
typedef RTree<const MapData::Elevation*, double, 2> Tree;

64
src/map/IMG/light.h Normal file
View 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> &sectors)
: _color(None), _range(0), _sectors(sectors) {}
Color color() const {return _color;}
quint32 range() const {return _range;}
const QVector<Sector> &sectors() const {return _sectors;}
private:
Color _color;
quint32 _range;
QVector<Sector> _sectors;
};
}
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const IMG::Light::Sector &sector)
{
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

View File

@ -14,6 +14,7 @@
#include "map/matrix.h"
#include "label.h"
#include "raster.h"
#include "light.h"
#include "zoom.h"
namespace IMG {
@ -51,11 +52,11 @@ public:
enum Flags {
NoFlag = 0,
ClassLabel = 1,
Light = 2
};
Coordinates coordinates;
Label label;
QVector<Light> lights;
quint64 id;
quint32 type;
quint32 flags;

View File

@ -18,13 +18,14 @@ 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
#define AREA(rect) \
(rect.size().width() * rect.size().height())
#define ROAD 0
#define WATER 1
static const QColor textColor(Qt::black);
static const QColor haloColor(Qt::white);
static const QColor shieldColor(Qt::white);
@ -226,7 +227,84 @@ void RasterTile::drawTextItems(QPainter *painter,
}
}
static void removeDuplicitLabel(QList<TextItem *> &labels, const QString &text,
static QRect lightRect(const QPoint &pos, quint32 range)
{
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
{
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;
for (int j = 0; j < p->lights.size(); j++) {
const Light &l = p->lights.at(j);
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();
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);
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;
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 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());
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,
const QRectF &tileRect)
{
for (int i = 0; i < labels.size(); i++) {
@ -397,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<TextItem*> &textItems, QList<TextItem*> &lights,
QList<const MapData::Point*> &sectorLights)
{
std::sort(points.begin(), points.end());
@ -407,6 +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 (sl)
sectorLights.append(&point);
const QString *label = point.label.text().isEmpty()
? 0 : &(point.label.text());
@ -428,14 +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() && !item->collides(textItems)) {
if (item->isValid() && (sl || !item->collides(textItems))) {
textItems.append(item);
if (Style::isLight(point.type) || point.flags & MapData::Point::Light)
textItems.append(new TextPointItem(pos + style->lightOffset(),
0, 0, style->light(), 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,
@ -483,22 +607,18 @@ MatrixD RasterTile::elevation(int extend) const
if (_data->hasDEM()) {
RectC rect;
QList<MapData::Elevation> tiles;
for (int i = 0; i < ll.size(); i++)
rect = rect.united(ll.at(i));
// Extra margin for always including the next DEM tile on the map tile
// edges (the DEM tile resolution is usally 0.5-15% of the map tile)
/* Extra margin for always including the next DEM tile on the map tile
edges (the DEM tile resolution is usally 0.5-15% of the map tile) */
double factor = 6 - (_zoom - 24) * 1.7;
_data->elevations(_file, rect.adjusted(0, 0, rect.width() / factor,
-rect.height() / factor), _zoom, &tiles);
RectC br(rect.adjusted(0, 0, rect.width() / factor, -rect.height()
/ factor));
DEMTree tree(tiles);
MatrixD m(ll.h(), ll.w());
for (int i = 0; i < ll.size(); i++)
m.at(i) = tree.elevation(ll.at(i));
QList<MapData::Elevation> tiles;
_data->elevations(_file, br, _zoom, &tiles);
return m;
return DEMTree(tiles).elevation(ll);
} else
return DEM::elevation(ll);
}
@ -524,7 +644,8 @@ void RasterTile::render()
QList<MapData::Poly> polygons;
QList<MapData::Poly> lines;
QList<MapData::Point> points;
QList<TextItem*> textItems;
QList<TextItem*> textItems, lights;
QList<const MapData::Point*> sectorLights;
QImage arrows[2];
arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio);
@ -535,7 +656,7 @@ void RasterTile::render()
ll2xy(lines);
ll2xy(points);
processPoints(points, textItems);
processPoints(points, textItems, lights, sectorLights);
processPolygons(polygons, textItems);
processLines(lines, textItems, arrows);
@ -550,8 +671,11 @@ void RasterTile::render()
drawPolygons(&painter, polygons);
drawHillShading(&painter);
drawLines(&painter, lines);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(lights);
qDeleteAll(textItems);
//painter.setPen(Qt::red);

View File

@ -9,7 +9,6 @@
#include "style.h"
class QPainter;
class IMGMap;
class TextItem;
namespace IMG {
@ -32,21 +31,30 @@ public:
void render();
private:
typedef RTree<const MapData::Elevation*, double, 2> DEMTRee;
struct Sector
{
Sector(Light::Color color, quint32 start, quint32 end)
: color(color), start(start), end(end) {}
struct ElevationCTX {
ElevationCTX(const DEMTRee &tree, const Coordinates &c, double &ele)
: tree(tree), c(c), ele(ele) {}
bool operator==(const Sector &other) const
{
return (color == other.color && start == other.start
&& end == other.end);
}
bool operator<(const Sector &other) const
{
if (color == other.color) {
if (start == other.start)
return end < other.end;
else
return start < other.start;
} else
return color < other.color;
}
const DEMTRee &tree;
const Coordinates &c;
double &ele;
};
struct EdgeCTX {
EdgeCTX(const Coordinates &c, double &ele) : c(c), ele(ele) {}
const Coordinates &c;
double &ele;
Light::Color color;
quint32 start;
quint32 end;
};
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Poly> &lines,
@ -58,17 +66,22 @@ private:
void ll2xy(QList<MapData::Poly> &polys) const;
void ll2xy(QList<MapData::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const;
void drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<MapData::Poly> &lines) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
void drawTextItems(QPainter *painter,
const QList<TextItem*> &textItems) const;
void drawHillShading(QPainter *painter) const;
void drawSectorLights(QPainter *painter,
const QList<const MapData::Point*> &lights) const;
void processPolygons(const QList<MapData::Poly> &polygons,
QList<TextItem *> &textItems);
QList<TextItem*> &textItems);
void processLines(QList<MapData::Poly> &lines, QList<TextItem*> &textItems,
const QImage (&arrows)[2]);
void processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems);
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<const MapData::Point*> &sectorLights);
void processShields(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems);
void processStreetNames(const QList<MapData::Poly> &lines,

View File

@ -13,6 +13,7 @@ using namespace Garmin;
using namespace IMG;
#define MASK(bits) ((1U << (bits)) - 1U)
#define COLOR(color) static_cast<Light::Color>(color)
static quint64 pointId(const QPoint &pos, quint32 type, const QString &label)
{
@ -107,7 +108,8 @@ bool RGNFile::readObstructionInfo(Handle &hdl, quint8 flags, quint32 size,
return true;
}
bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const
bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const
{
quint16 val;
quint8 lc;
@ -115,7 +117,7 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con
if ((flags & 0xe0) != 0xe0)
return true;
if (!readUInt16(hdl, val))
if (!(size >= 2 && readUInt16(hdl, val)))
return false;
lc = (val >> 10) & 0x0f;
@ -123,7 +125,107 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con
lc = (val >> 6) & 7;
if (lc)
point->flags |= MapData::Point::Light;
point->lights.append(Light(COLOR(lc), 0));
return true;
}
bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const
{
quint16 flags1;
quint8 flags2;
quint32 unused;
if (!(size >= 3 && readUInt16(hdl, flags1) && readUInt8(hdl, flags2)))
return false;
size -= 3;
if (flags2 >> 6) {
if (!(size >= (flags2 >> 6) && readVUInt32(hdl, (flags2 >> 6), unused)))
return false;
size -= (flags2 >> 6);
}
if (flags2 >> 2 & 3) {
if (!(size >= (flags2 >> 2 & 3)
&& readVUInt32(hdl, (flags2 >> 2 & 3), unused)))
return false;
size -= (flags2 >> 2 & 3);
}
if (flags1 & 0xc0) {
if (flags1 & 0x80) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
unused |= ((flags1 & 0x40) << 2);
size--;
} else {
if (!(size >= 2 && readUInt16(hdl, unused)))
return false;
size -= 2;
}
}
if (flags & 2) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags & 4) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags & 8) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags1 & 0x200) {
if (!(size >= 2 && readUInt16(hdl, unused)))
return false;
size -= 2;
}
if (flags1 & 0x400) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
}
if (flags1 & 0x800) {
quint16 la;
quint8 cf, range = 0;
QVector<Light::Sector> sectors;
do {
if (!(size >= 2 && readUInt16(hdl, la)))
return false;
size -= 2;
cf = la >> 8;
Light::Color c = COLOR(cf >> 4 & 7);
if (c) {
if (!(size >= 1 && readUInt8(hdl, range)))
return false;
size--;
}
sectors.append(Light::Sector(c, la & 0xfff, range));
} while (!(cf >> 7));
point->lights.append(Light(sectors));
} else {
quint8 v1, v2, range;
if (!(size >= 1 && readUInt8(hdl, v1)))
return false;
size--;
range = v1 & 0x1f;
if ((v1 & 0x1f) == 0x1f) {
if (!(size >= 1 && readUInt8(hdl, v2)))
return false;
size--;
range += v2;
}
point->lights.append(Light(COLOR(v1 >> 5), range));
}
return true;
}
@ -183,13 +285,183 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
if (point && Style::isObstructionPoint(point->type))
readObstructionInfo(hdl, flags, rs, point);
if (point && Style::isBuoy(point->type))
readBuoyInfo(hdl, flags, point);
readBuoyInfo(hdl, flags, rs, point);
if (point && Style::isLight(point->type))
readLightInfo(hdl, flags, rs, point);
return seek(hdl, off + rs);
}
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3]) const
bool RGNFile::readLclSectors(Handle &hdl, quint32 &size, quint32 flags,
Light &light) const
{
quint32 unused, cnt = flags & 0x1f;
QVector<Light::Sector> sectors;
for (quint32 j = 0; j < cnt; j++) {
quint32 cf, range = 0;
if (!(size >= 1 && readUInt8(hdl, cf)))
return false;
size--;
if (cf >> 6) {
if (!(size >= (cf >> 6) && readVUInt32(hdl, cf >> 6, range)))
return false;
size -= (cf >> 6);
}
if (cnt > 1) {
quint32 angle;
if (!(size >= 2 && readUInt16(hdl, angle)))
return false;
size -= 2;
if ((flags >> 0x13) & 1) {
quint32 sflags;
if (!(size >= 1 && readUInt8(hdl, sflags)))
return false;
size--;
if (0x3f < sflags) {
if (sflags & 0x80) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
unused |= (sflags & 0x40) << 2;
} else {
if (!(size >= 2 && readUInt16(hdl, unused)))
return false;
size -= 2;
}
}
}
sectors.append(Light::Sector(COLOR(cf & 0x7), angle, range));
} else {
light = Light(COLOR(cf & 0x7), range);
return true;
}
}
light = Light(sectors);
return true;
}
bool RGNFile::readLclLights(Handle &hdl, quint32 &size, quint32 lights,
MapData::Point *point) const
{
quint32 unused;
for (quint32 i = 0; i < lights; i++) {
quint32 fs, vs, flags;
Light light;
if (!(readVUInt32(hdl, fs, &vs) && size >= vs))
return false;
size -= vs;
if (!(size >= 4 && readUInt32(hdl, flags)))
return false;
size -= 4;
if (flags >> 0x11 & 3) {
if (!(size >= (flags >> 0x11 & 3)
&& readVUInt32(hdl, flags >> 0x11 & 3, unused)))
return false;
size -= (flags >> 0x11 & 3);
}
if (flags & 0x3000) {
if (flags & 0x2000) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
unused |= (flags >> 4) & 0x100;
} else {
if (!(size >= 2 && readUInt16(hdl, unused)))
return false;
size -= 2;
}
}
if (flags & 0x100000) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
if (unused & 0x80) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
}
}
if (!readLclSectors(hdl, size, flags, light))
return false;
point->lights.append(light);
}
return true;
}
bool RGNFile::readLclNavaid(Handle &hdl, quint32 size,
MapData::Point *point) const
{
quint32 unused, flags;
// Discard the class lights info if any (marine points may have both!)
point->lights.clear();
if (!(size >= 4 && readUInt32(hdl, flags)))
return false;
size -= 4;
if (flags & 1) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
}
if (flags & 2) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
}
if (flags & 4) {
if (!(size >= 1 && readUInt8(hdl, unused)))
return false;
size--;
}
if (flags & 8) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags & 0x10) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags & 0x20) {
if (!(size >= 3 && readUInt24(hdl, unused)))
return false;
size -= 3;
}
if (flags & 0x200) {
quint8 b;
do {
if (!(size >= 1 && readUInt8(hdl, b)))
return false;
size--;
} while (b & 0x80);
}
if (!readLclLights(hdl, size, (flags >> 6) & 7, point))
return false;
return (size == 0);
}
bool RGNFile::readLclFields(Handle &hdl, const quint32 flags[3],
SegmentType segmentType, void *object) const
{
MapData::Point *point = (segmentType == Point)
? (MapData::Point *) object : 0;
quint32 bitfield = 0xFFFFFFFF;
if (flags[0] & 0x20000000)
@ -201,14 +473,20 @@ bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3]) const
if (bitfield & 1) {
quint32 m = flags[(j >> 4) + 1] >> ((j * 2) & 0x1e) & 3;
quint32 skip = 0;
quint32 size = 0;
if (m == 3) {
if (!readVUInt32(hdl, skip))
if (!readVUInt32(hdl, size))
return false;
} else
skip = m + 1;
if (!seek(hdl, pos(hdl) + skip))
return false;
size = m + 1;
if (i == 2 && point) {
if (!readLclNavaid(hdl, size, point))
return false;
} else {
if (!seek(hdl, pos(hdl) + size))
return false;
}
}
bitfield >>= 1;
j++;
@ -462,8 +740,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
if (subtype & 0x80 && !readClassFields(hdl, segmentType, &poly, lbl,
lblHdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
? _linesLclFlags : _polygonsLclFlags))
if (subtype & 0x40 && !readLclFields(hdl, segmentType == Line
? _linesLclFlags : _polygonsLclFlags, segmentType, &poly))
return false;
quint32 gblFlags = (segmentType == Line)
? _linesGblFlags : _polygonsGblFlags;
@ -553,7 +831,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
return false;
if (subtype & 0x80 && !readClassFields(hdl, Point, &point, lbl, lblHdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags))
if (subtype & 0x40 && !readLclFields(hdl, _pointsLclFlags, Point, &point))
return false;
if (_pointsGblFlags && !skipGblFields(hdl, _pointsGblFlags))
return false;

View File

@ -56,7 +56,8 @@ private:
bool segments(Handle &hdl, SubDiv *subdiv, SubDiv::Segment seg[5]) const;
bool readClassFields(Handle &hdl, SegmentType segmentType, void *object,
LBLFile *lbl, Handle &lblHdl) const;
bool skipLclFields(Handle &hdl, const quint32 flags[3]) const;
bool readLclFields(Handle &hdl, const quint32 flags[3],
SegmentType segmentType, void *object) const;
bool skipGblFields(Handle &hdl, quint32 flags) const;
bool readRasterInfo(Handle &hdl, const LBLFile *lbl, quint32 size,
MapData::Poly *poly) const;
@ -64,9 +65,18 @@ private:
MapData::Point *point) const;
bool readObstructionInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const;
bool readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const;
bool readBuoyInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const;
bool readLightInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const;
bool readLabel(Handle &hdl, LBLFile *lbl, Handle &lblHdl,
quint8 flags, quint32 size, MapData::Point *point) const;
bool readLclNavaid(Handle &hdl, quint32 size,
MapData::Point *point) const;
bool readLclSectors(Handle &hdl, quint32 &size, quint32 flags,
Light &light) const;
bool readLclLights(Handle &hdl, quint32 &size, quint32 lights,
MapData::Point *point) const;
HuffmanTable *_huffmanTable;
Section _base, _dict, _polygons, _lines, _points;

View File

@ -323,6 +323,8 @@ void Style::defaultPolygonStyle()
Qt::FDiagPattern));
_polygons[0x10503] = Polygon(QBrush(QColor(0xff, 0x40, 0x40),
Qt::FDiagPattern));
_polygons[0x10504] = Polygon(QBrush(QColor(0xff, 0x40, 0x40),
Qt::FDiagPattern));
_polygons[0x10601] = Polygon(QBrush(QColor(0xaa, 0xaa, 0xaa)));
_polygons[0x1060a] = Polygon(QBrush(QColor(0xfc, 0xb4, 0xfc)));
_polygons[0x10614] = Polygon(QBrush(QColor(0xff, 0xff, 0xff)));
@ -348,7 +350,8 @@ void Style::defaultPolygonStyle()
<< TYPE(0x0a) << 0x10907 << TYPE(0x0b) << 0x10908 << TYPE(0x0c) << 0x10909
<< TYPE(0x26) << TYPE(0x0d) << 0x1090a << TYPE(0x0e) << 0x1090b << TYPE(0x0f)
<< TYPE(0x10) << TYPE(0x11) << TYPE(0x12) << TYPE(0x19) << 0x1090d
<< TYPE(0x13) << 0x10900 << 0x10613 << 0x10409 << 0x10503 << 0x1060a;
<< TYPE(0x13) << 0x10900 << 0x10613 << 0x10409 << 0x10503 << 0x10504
<< 0x1060a;
}
void Style::defaultLineStyle(qreal ratio)
@ -464,7 +467,9 @@ void Style::defaultLineStyle(qreal ratio)
_lines[0x10409] = Line(QPen(QColor(0, 0, 0), 1, Qt::DotLine));
_lines[0x10501] = Line(QImage(":/marine/noanchor-line.png"));
_lines[0x10503] = Line(QPen(QColor(0xe7, 0x28, 0xe7), 1, Qt::DashLine));
_lines[0x10504] = Line(QPen(QColor(0xe7, 0x28, 0xe7), 1, Qt::DashLine));
_lines[0x10505] = Line(QImage(":/marine/safety-zone-line.png"));
_lines[0x10506] = Line(QImage(":/marine/nature-reserve-line.png"));
_lines[0x10507] = Line(QPen(QColor(0xe7, 0x28, 0xe7), 1, Qt::DashLine));
_lines[0x10601] = Line(QPen(QColor(0, 0, 0), 1, Qt::SolidLine));
_lines[0x10603] = Line(QPen(QColor(0xe7, 0x28, 0xe7), 2, Qt::DashDotLine));
@ -1319,6 +1324,10 @@ Style::Style(qreal ratio, SubFile *typ)
_extraSmall = pixelSizeFont(10);
_light = QImage(":/marine/light.png");
_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);
defaultLineStyle(ratio);
@ -1373,6 +1382,40 @@ const QFont *Style::font(Style::FontSize size, Style::FontSize defaultSize) cons
}
}
const QImage *Style::light(Light::Color color) const
{
switch (color) {
case Light::Red:
return &_lightRed;
case Light::Green:
return &_lightGreen;
case Light::White:
return &_lightWhite;
case Light::Yellow:
case Light::Amber:
return &_lightYellow;
default:
return &_light;
}
}
QColor Style::color(Light::Color c)
{
switch (c) {
case Light::Red:
return Qt::red;
case Light::Green:
return Qt::green;
case Light::White:
return Qt::white;
case Light::Yellow:
case Light::Amber:
return Qt::yellow;
default:
return Qt::magenta;
}
}
#ifndef QT_NO_DEBUG
static QString penColor(const QPen &pen)
{

View File

@ -5,6 +5,7 @@
#include <QBrush>
#include <QFont>
#include <QDebug>
#include "light.h"
#include "subfile.h"
#define TYPE(t) ((t)<<8)
@ -112,8 +113,7 @@ public:
const QList<quint32> &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size, Style::FontSize defaultSize
= Style::Normal) const;
const QImage *light() const {return &_light;}
const QImage *light(Light::Color color) const;
const QPoint &lightOffset() const {return _lightOffset;}
static bool isPOI(quint32 type)
@ -157,6 +157,8 @@ public:
static bool isMarina(quint32 type)
{return type == 0x10703;}
static QColor color(Light::Color c);
private:
struct Section {
quint32 offset;
@ -203,7 +205,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */
QFont _large, _normal, _small, _extraSmall;
QImage _light;
QImage _light, _lightRed, _lightGreen, _lightYellow, _lightWhite;
QPoint _lightOffset;
};

View File

@ -41,7 +41,7 @@ bool SubFile::seek(Handle &handle, quint32 pos) const
return true;
}
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
bool SubFile::readVUInt32(Handle &hdl, quint32 &val, quint32 *size) const
{
quint8 bytes, shift, b;
@ -69,6 +69,9 @@ bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
val |= (((quint32)b) << (i * 8)) >> (8 - shift);
}
if (size)
*size = 1 + bytes;
return true;
}

View File

@ -169,7 +169,7 @@ public:
return true;
}
bool readVUInt32(Handle &hdl, quint32 &val) const;
bool readVUInt32(Handle &hdl, quint32 &val, quint32 *size = 0) const;
bool readVUInt32(Handle &hdl, quint32 bytes, quint32 &val) const;
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;

View File

@ -27,14 +27,6 @@
#define MAX_REDIRECT_LEVEL 5
#define RETRIES 3
#define ATTR_REDIRECT_POLICY QNetworkRequest::RedirectPolicyAttribute
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#define ATTR_HTTP2_ALLOWED QNetworkRequest::HTTP2AllowedAttribute
#else // QT 5.15
#define ATTR_HTTP2_ALLOWED QNetworkRequest::Http2AllowedAttribute
#endif // QT 5.15
#define TMP_SUFFIX ".download"
// QNetworkReply::errorString() returns bullshit, use our own reporting
@ -129,31 +121,6 @@ Authorization::Authorization(const QString &username, const QString &password)
_header = HTTPHeader("Authorization", "Basic " + data);
}
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
NetworkTimeout::NetworkTimeout(int timeout, QNetworkReply *reply)
: QObject(reply), _timeout(timeout)
{
connect(reply, &QIODevice::readyRead, this, &NetworkTimeout::reset);
_timer.start(timeout * 1000, this);
}
void NetworkTimeout::reset()
{
_timer.start(_timeout * 1000, this);
}
void NetworkTimeout::timerEvent(QTimerEvent *ev)
{
if (!_timer.isActive() || ev->timerId() != _timer.timerId())
return;
QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
if (reply->isRunning())
reply->abort();
_timer.stop();
}
#endif // QT 5.15
QNetworkAccessManager *Downloader::_manager = 0;
int Downloader::_timeout = 30;
bool Downloader::_http2 = true;
@ -176,12 +143,10 @@ bool Downloader::doDownload(const Download &dl, const QList<HTTPHeader> &headers
QNetworkRequest request(url);
request.setMaximumRedirectsAllowed(MAX_REDIRECT_LEVEL);
request.setAttribute(ATTR_REDIRECT_POLICY,
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
QNetworkRequest::NoLessSafeRedirectPolicy);
request.setAttribute(ATTR_HTTP2_ALLOWED, QVariant(_http2));
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(_http2));
request.setTransferTimeout(_timeout * 1000);
#endif // QT 5.15
for (int i = 0; i < headers.size(); i++) {
const HTTPHeader &hdr = headers.at(i);
@ -208,9 +173,6 @@ bool Downloader::doDownload(const Download &dl, const QList<HTTPHeader> &headers
_currentDownloads.insert(url, file);
if (reply->isRunning()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
new NetworkTimeout(_timeout, reply);
#endif // QT 5.15
connect(reply, &QIODevice::readyRead, this, &Downloader::emitReadReady);
connect(reply, &QNetworkReply::finished, this, &Downloader::emitFinished);
} else {

View File

@ -3,9 +3,6 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#include <QBasicTimer>
#endif // QT 5.15
#include <QUrl>
#include <QList>
#include <QHash>
@ -41,25 +38,6 @@ private:
HTTPHeader _header;
};
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
class NetworkTimeout : public QObject
{
Q_OBJECT
public:
NetworkTimeout(int timeout, QNetworkReply *reply);
private slots:
void reset();
private:
void timerEvent(QTimerEvent *ev);
QBasicTimer _timer;
int _timeout;
};
#endif // QT 5.15
class Downloader : public QObject
{
Q_OBJECT

View File

@ -63,7 +63,7 @@ MapList::ParserMap MapList::parsers()
return map;
}
MapList::ParserMap MapList::_parsers = parsers();
MapList::ParserMap MapList::_parsers = MapList::parsers();
Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
{

View File

@ -39,9 +39,7 @@ static QPainterPath parallelPath(const QPainterPath &p, double dy)
QVector<QPointF> u(n);
QPainterPath h;
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
h.reserve(p.elementCount());
#endif // QT 5.13
for (int k = 0; k < n; k++) {
qreal c = p.elementAt(k + 1).x - p.elementAt(k).x;
@ -251,12 +249,10 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
QPainterPath path;
if (curve) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
int size = 0;
for (int i = 0; i < polygon.size(); i++)
size += polygon.at(i).size();
path.reserve(size);
#endif // QT 5.13
for (int i = 0; i < polygon.size(); i++) {
const QVector<Coordinates> &subpath = polygon.at(i);

View File

@ -6,16 +6,8 @@
#define MAX_ANGLE 30
#define PADDING 2
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#define INTERSECTS intersect
#else // QT 5.15
#define INTERSECTS intersects
#endif // QT 5.15
static void swap(const QLineF &line, QPointF *p1, QPointF *p2)
{
QPointF lp1(line.p1());
QPointF lp2(line.p2());
@ -34,10 +26,10 @@ static bool intersection(const QLineF &line, const QRectF &rect, QPointF *p1,
{
QPointF *p = p1;
if (line.INTERSECTS(QLineF(rect.topLeft(), rect.topRight()), p)
if (line.intersects(QLineF(rect.topLeft(), rect.topRight()), p)
== QLineF::BoundedIntersection)
p = p2;
if (line.INTERSECTS(QLineF(rect.topLeft(), rect.bottomLeft()), p)
if (line.intersects(QLineF(rect.topLeft(), rect.bottomLeft()), p)
== QLineF::BoundedIntersection) {
if (p == p2) {
swap(line, p1, p2);
@ -45,7 +37,7 @@ static bool intersection(const QLineF &line, const QRectF &rect, QPointF *p1,
}
p = p2;
}
if (line.INTERSECTS(QLineF(rect.bottomRight(), rect.bottomLeft()), p)
if (line.intersects(QLineF(rect.bottomRight(), rect.bottomLeft()), p)
== QLineF::BoundedIntersection) {
if (p == p2) {
swap(line, p1, p2);
@ -53,7 +45,7 @@ static bool intersection(const QLineF &line, const QRectF &rect, QPointF *p1,
}
p = p2;
}
if (line.INTERSECTS(QLineF(rect.bottomRight(), rect.topRight()), p)
if (line.intersects(QLineF(rect.bottomRight(), rect.topRight()), p)
== QLineF::BoundedIntersection) {
if (p == p2) {
swap(line, p1, p2);
@ -68,16 +60,16 @@ static bool intersection(const QLineF &line, const QRectF &rect, QPointF *p1,
static bool intersection(const QLineF &line, const QRectF &rect, QPointF *p)
{
if (line.INTERSECTS(QLineF(rect.topLeft(), rect.topRight()), p)
if (line.intersects(QLineF(rect.topLeft(), rect.topRight()), p)
== QLineF::BoundedIntersection)
return true;
if (line.INTERSECTS(QLineF(rect.topLeft(), rect.bottomLeft()), p)
if (line.intersects(QLineF(rect.topLeft(), rect.bottomLeft()), p)
== QLineF::BoundedIntersection)
return true;
if (line.INTERSECTS(QLineF(rect.bottomRight(), rect.bottomLeft()), p)
if (line.intersects(QLineF(rect.bottomRight(), rect.bottomLeft()), p)
== QLineF::BoundedIntersection)
return true;
if (line.INTERSECTS(QLineF(rect.bottomRight(), rect.topRight()), p)
if (line.intersects(QLineF(rect.bottomRight(), rect.topRight()), p)
== QLineF::BoundedIntersection)
return true;