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

Compare commits

...

81 Commits
7.20 ... 7.22

Author SHA1 Message Date
2002b828dd Version++ 2020-02-12 20:35:59 +01:00
71f0e1d0ac Cleanup the data loading code 2020-02-12 20:33:23 +01:00
eb9767f2dd Cleanup the map loading code 2020-02-12 20:32:57 +01:00
8d06ab6208 Enable loading of GMAP maps when Garmin BaseCamp has associated them 2020-02-12 09:37:03 +01:00
187cb77858 Added missing Hungarian localization copy 2020-02-12 08:36:56 +01:00
8167a995f6 Added GMAP support info 2020-02-11 23:31:51 +01:00
b5aed7314e Merge branch 'origin/master' into Weblate. 2020-02-11 21:16:44 +01:00
464d4c5327 Removed forgotten devel code 2020-02-11 21:16:31 +01:00
11f4dc4b41 Merge branch 'origin/master' into Weblate. 2020-02-11 21:04:43 +01:00
2d3ad41d69 Use the GMAP basemaps rather than discarding them
+ some minor point rendering issues fixes
2020-02-11 21:03:55 +01:00
a7dcc57dd1 Translated using Weblate (Spanish)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/es/
2020-02-11 18:50:35 +01:00
2d5e11f001 Properly handle basemap entries with './xxx' paths 2020-02-10 19:40:39 +01:00
e86f89308b Decreased GMAP read block size to 4K 2020-02-10 19:40:04 +01:00
378fa8dc0e Make caching work for both IMG and GMAP maps 2020-02-10 19:38:45 +01:00
dde8903013 Merge branch 'origin/master' into Weblate. 2020-02-10 09:33:37 +01:00
37c4fe1eba Cosmetics 2020-02-10 09:33:31 +01:00
f9db0acb03 Merge branch 'origin/master' into Weblate. 2020-02-10 09:26:32 +01:00
1aa07a6a34 Removed duplicit code 2020-02-10 09:26:23 +01:00
c302a67299 Merge branch 'origin/master' into Weblate. 2020-02-10 09:11:05 +01:00
8b6d7acec5 Give the compiler more posibilities for optimization 2020-02-10 09:10:09 +01:00
ba70fd159d Merge branch 'origin/master' into Weblate. 2020-02-10 08:55:45 +01:00
1773a1ae0d Cosmetics 2020-02-10 08:55:34 +01:00
136f08aa76 Merge branch 'origin/master' into Weblate. 2020-02-09 23:27:36 +01:00
f70d92805b Version++ 2020-02-09 23:27:22 +01:00
69e66f1856 Merge branch 'origin/master' into Weblate. 2020-02-09 23:25:25 +01:00
911c63df0c Added support for GMAP maps 2020-02-09 23:24:48 +01:00
d16899530a Merge branch 'origin/master' into Weblate. 2020-02-08 16:17:00 +01:00
e2339c67cd Fixed bitstream4 flush 2020-02-08 16:16:24 +01:00
c809d2f17e Merge branch 'origin/master' into Weblate. 2020-02-08 16:02:00 +01:00
fac0bae006 Fixed crash on GMP tiles without LBL or NET parts 2020-02-08 16:01:22 +01:00
9bd03c1225 Merge branch 'origin/master' into Weblate. 2020-02-08 10:55:07 +01:00
d63c666997 Code cleanup 2020-02-08 10:54:59 +01:00
0cd20a1e57 Unions can not have non-POD members 2020-02-08 10:52:26 +01:00
2f70d46be8 Merge branch 'origin/master' into Weblate. 2020-02-07 22:11:25 +01:00
325e83569c Redesigned IMG caching
(Cache encoded data rather than raw data)
2020-02-07 22:10:06 +01:00
56b374ed30 Merge branch 'origin/master' into Weblate. 2020-02-04 23:04:08 +01:00
df1be4aeb9 Added missing reference 2020-02-04 23:03:50 +01:00
d79bdaef78 Merge branch 'origin/master' into Weblate. 2020-02-04 23:02:01 +01:00
fa0c09b30c Code cleanup 2020-02-04 23:01:47 +01:00
95c82c501a Merge branch 'origin/master' into Weblate. 2020-02-04 21:48:14 +01:00
3b16f37e66 Some micro-optimizatoins and code cleanup 2020-02-04 21:47:31 +01:00
661e26fbdb Merge branch 'origin/master' into Weblate. 2020-02-03 23:18:28 +01:00
25939cfa62 Fixed typo
(I'd rather not investigate how it could work...)
2020-02-03 23:18:00 +01:00
c59ea4e5cd Merge branch 'origin/master' into Weblate. 2020-02-03 22:58:35 +01:00
5de1bc7e7d Update gpxsee.desktop (#271) 2020-02-03 22:58:29 +01:00
7c3399575b Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2020-02-03 09:37:41 +01:00
7bedd17071 Translated using Weblate (Polish)
Currently translated at 98.3% (345 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2020-02-03 09:37:39 +01:00
06a84dcea2 Code cleanup 2020-02-02 09:03:35 +01:00
ca204626a1 Some hot path inlining 2020-02-01 19:21:41 +01:00
d16ef7b081 Translated using Weblate (Hungarian)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-01-30 09:01:52 +01:00
ef013dc036 Translated using Weblate (Hungarian)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-01-28 23:51:08 +01:00
633d52daca Added Hungarian localization 2020-01-28 22:02:16 +01:00
adbb5e5684 Translated using Weblate (Hungarian)
Currently translated at 98.0% (344 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-01-28 14:34:01 +01:00
bd9b09df3d Merge branch 'origin/master' into Weblate. 2020-01-26 18:24:52 +01:00
ede2b6004f Added SML info 2020-01-26 18:24:48 +01:00
a516055dc2 Merge branch 'origin/master' into Weblate. 2020-01-26 18:06:26 +01:00
1ba3ada96e Added Hungarian localization stub 2020-01-26 18:05:50 +01:00
1667e0ca70 Merge branch 'origin/master' into Weblate. 2020-01-26 15:59:41 +01:00
b50d5227a5 Merge branch 'origin/master' into Weblate. 2020-01-26 14:08:23 +01:00
f38db3227f Merge branch 'origin/master' into Weblate. 2020-01-26 13:24:27 +01:00
c3aeb95660 Merge branch 'origin/master' into Weblate. 2020-01-26 13:14:09 +01:00
6bdd97611d Merge branch 'origin/master' into Weblate. 2020-01-26 13:08:16 +01:00
15e09539c7 Merge branch 'origin/master' into Weblate. 2020-01-26 13:02:48 +01:00
a225c6d308 Merge branch 'origin/master' into Weblate. 2020-01-26 12:57:56 +01:00
a94056ac7e Merge branch 'origin/master' into Weblate. 2020-01-26 12:56:15 +01:00
aea7bbdf09 Merge branch 'origin/master' into Weblate. 2020-01-26 12:51:40 +01:00
1c9b31d7c9 Merge branch 'origin/master' into Weblate. 2020-01-26 12:50:07 +01:00
7a9b26756a Merge branch 'origin/master' into Weblate. 2020-01-26 12:40:03 +01:00
eaae965719 Merge branch 'origin/master' into Weblate. 2020-01-26 12:33:41 +01:00
ca6e8638d8 Merge branch 'origin/master' into Weblate. 2020-01-26 12:17:38 +01:00
66a22fbfee Merge branch 'origin/master' into Weblate. 2020-01-26 12:08:32 +01:00
2d3ca7c5f8 Merge branch 'origin/master' into Weblate. 2020-01-26 12:02:53 +01:00
8c71d11fa6 Merge branch 'origin/master' into Weblate. 2020-01-26 11:59:36 +01:00
857c5050f4 Merge branch 'origin/master' into Weblate. 2020-01-26 11:52:39 +01:00
44d1d27c93 Merge branch 'origin/master' into Weblate. 2020-01-26 11:50:38 +01:00
68e20cff5b Merge branch 'origin/master' into Weblate. 2020-01-26 11:43:41 +01:00
1c67f1cac9 Merge branch 'origin/master' into Weblate. 2020-01-26 11:41:12 +01:00
a09d13594d Merge branch 'origin/master' into Weblate. 2020-01-26 11:28:42 +01:00
6916d0e6b4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-01-25 22:21:36 +01:00
757ec98108 Translated using Weblate (Russian)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-01-25 22:21:35 +01:00
2ddb5dc28b Translated using Weblate (Finnish)
Currently translated at 100.0% (351 of 351 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-01-25 22:21:35 +01:00
44 changed files with 3124 additions and 841 deletions

View File

@ -1,4 +1,4 @@
version: 7.20.{build} version: 7.22.{build}
configuration: configuration:
- Release - Release
@ -17,7 +17,7 @@ environment:
LIBSSL: libcrypto-1_1.dll LIBSSL: libcrypto-1_1.dll
- QTDIR: C:\Qt\5.13\msvc2017_64 - QTDIR: C:\Qt\5.13\msvc2017_64
NSI: gpxsee64.nsi NSI: gpxsee64.nsi
VCVARS: vcvars64.bat" VCVARS: vcvars64.bat
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
LIBCRYPTO: libssl-1_1-x64.dll LIBCRYPTO: libssl-1_1-x64.dll
LIBSSL: libcrypto-1_1-x64.dll LIBSSL: libcrypto-1_1-x64.dll

View File

@ -2,9 +2,9 @@
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats. GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
## Features ## Features
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV and geotagged JPEG files. * Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV and geotagged JPEG files.
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles). * User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images). * Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images).
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs. * Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
* Support for DEM files (SRTM HGT). * Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view. * Support for multiple tracks in one view.

View File

@ -3,7 +3,7 @@ unix:!macx {
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 7.20 VERSION = 7.22
QT += core \ QT += core \
gui \ gui \
@ -91,8 +91,10 @@ HEADERS += src/common/config.h \
src/map/IMG/bitmapline.h \ src/map/IMG/bitmapline.h \
src/map/IMG/bitstream.h \ src/map/IMG/bitstream.h \
src/map/IMG/deltastream.h \ src/map/IMG/deltastream.h \
src/map/IMG/gmap.h \
src/map/IMG/huffmanstream.h \ src/map/IMG/huffmanstream.h \
src/map/IMG/huffmantable.h \ src/map/IMG/huffmantable.h \
src/map/IMG/mapdata.h \
src/map/IMG/textpathitem.h \ src/map/IMG/textpathitem.h \
src/map/IMG/textpointitem.h \ src/map/IMG/textpointitem.h \
src/map/projection.h \ src/map/projection.h \
@ -249,8 +251,10 @@ SOURCES += src/main.cpp \
src/map/IMG/bitmapline.cpp \ src/map/IMG/bitmapline.cpp \
src/map/IMG/bitstream.cpp \ src/map/IMG/bitstream.cpp \
src/map/IMG/deltastream.cpp \ src/map/IMG/deltastream.cpp \
src/map/IMG/gmap.cpp \
src/map/IMG/huffmanstream.cpp \ src/map/IMG/huffmanstream.cpp \
src/map/IMG/huffmantable.cpp \ src/map/IMG/huffmantable.cpp \
src/map/IMG/mapdata.cpp \
src/map/IMG/textpathitem.cpp \ src/map/IMG/textpathitem.cpp \
src/map/IMG/textpointitem.cpp \ src/map/IMG/textpointitem.cpp \
src/map/maplist.cpp \ src/map/maplist.cpp \
@ -359,7 +363,8 @@ TRANSLATIONS = lang/gpxsee_en.ts \
lang/gpxsee_tr.ts \ lang/gpxsee_tr.ts \
lang/gpxsee_es.ts \ lang/gpxsee_es.ts \
lang/gpxsee_pt_BR.ts \ lang/gpxsee_pt_BR.ts \
lang/gpxsee_uk.ts lang/gpxsee_uk.ts \
lang/gpxsee_hu.ts
macx { macx {
ICON = icons/gpxsee.icns ICON = icons/gpxsee.icns
@ -378,7 +383,8 @@ macx {
lang/gpxsee_tr.qm \ lang/gpxsee_tr.qm \
lang/gpxsee_es.qm \ lang/gpxsee_es.qm \
lang/gpxsee_pt_BR.qm \ lang/gpxsee_pt_BR.qm \
lang/gpxsee_uk.qm lang/gpxsee_uk.qm \
lang/gpxsee_hu.qm
csv.path = Contents/Resources csv.path = Contents/Resources
csv.files = pkg/csv csv.files = pkg/csv
maps.path = Contents/Resources maps.path = Contents/Resources

View File

@ -49,7 +49,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="179"/> <location filename="../src/data/data.cpp" line="179"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Formatos soportados</translation> <translation>Formatos admitidos</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="180"/> <location filename="../src/data/data.cpp" line="180"/>
@ -89,7 +89,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="189"/> <location filename="../src/data/data.cpp" line="189"/>
<source>JPEG images</source> <source>JPEG images</source>
<translation>Imagen JPEG</translation> <translation>Imágenes JPEG</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="190"/> <location filename="../src/data/data.cpp" line="190"/>
@ -168,7 +168,7 @@
<message> <message>
<location filename="../src/GUI/elevationgraph.cpp" line="144"/> <location filename="../src/GUI/elevationgraph.cpp" line="144"/>
<source>ft</source> <source>ft</source>
<translation>pies</translation> <translation>ft</translation>
</message> </message>
</context> </context>
<context> <context>
@ -181,7 +181,7 @@
<message> <message>
<location filename="../src/GUI/elevationgraphitem.cpp" line="33"/> <location filename="../src/GUI/elevationgraphitem.cpp" line="33"/>
<source>ft</source> <source>ft</source>
<translation></translation> <translation>ft</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/elevationgraphitem.cpp" line="36"/> <location filename="../src/GUI/elevationgraphitem.cpp" line="36"/>
@ -234,7 +234,7 @@
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="66"/> <location filename="../src/GUI/exportdialog.cpp" line="66"/>
<source>in</source> <source>in</source>
<translation></translation> <translation>in</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="94"/> <location filename="../src/GUI/exportdialog.cpp" line="94"/>
@ -301,7 +301,7 @@
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="157"/> <location filename="../src/GUI/exportdialog.cpp" line="157"/>
<source>%1 is not writable.</source> <source>%1 is not writable.</source>
<translation>%1 es de sólo lectura.</translation> <translation>%1 es de solo lectura.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -319,7 +319,7 @@
<location filename="../src/GUI/format.cpp" line="61"/> <location filename="../src/GUI/format.cpp" line="61"/>
<location filename="../src/GUI/format.cpp" line="84"/> <location filename="../src/GUI/format.cpp" line="84"/>
<source>ft</source> <source>ft</source>
<translation></translation> <translation>ft</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/format.cpp" line="57"/> <location filename="../src/GUI/format.cpp" line="57"/>
@ -403,17 +403,17 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="256"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Cargar archivo de POI&apos;s...</translation> <translation>Cargar archivo de POI...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="260"/> <location filename="../src/GUI/gui.cpp" line="260"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Cerrar archivo de POI&apos;s</translation> <translation>Cerrar archivos de POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="264"/> <location filename="../src/GUI/gui.cpp" line="264"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>Sobrescribir POI&apos;s</translation> <translation>Sobreponer POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="269"/> <location filename="../src/GUI/gui.cpp" line="269"/>
@ -423,7 +423,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="274"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Ver POI&apos;s</translation> <translation>Ver POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
@ -438,7 +438,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="296"/> <location filename="../src/GUI/gui.cpp" line="296"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Limpiar cache de teselas</translation> <translation>Limpiar antememoria de teselas</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="301"/> <location filename="../src/GUI/gui.cpp" line="301"/>
@ -455,7 +455,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="322"/> <location filename="../src/GUI/gui.cpp" line="322"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Ver tracks</translation> <translation>Ver pistas</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="327"/> <location filename="../src/GUI/gui.cpp" line="327"/>
@ -465,7 +465,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="332"/> <location filename="../src/GUI/gui.cpp" line="332"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Ver waypoints</translation> <translation>Ver puntos de referencia</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="337"/>
@ -480,7 +480,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="347"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Waypoints de ruta</translation> <translation>Puntos de referencia de ruta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="352"/> <location filename="../src/GUI/gui.cpp" line="352"/>
@ -622,7 +622,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="529"/> <location filename="../src/GUI/gui.cpp" line="529"/>
<source>POI files</source> <source>POI files</source>
<translation>Archivos de POI&apos;s</translation> <translation>Archivos de POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="540"/> <location filename="../src/GUI/gui.cpp" line="540"/>
@ -727,22 +727,22 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="707"/> <location filename="../src/GUI/gui.cpp" line="707"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Zoom +</translation> <translation>Acercar</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="709"/> <location filename="../src/GUI/gui.cpp" line="709"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Zoom -</translation> <translation>Alejar</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="711"/> <location filename="../src/GUI/gui.cpp" line="711"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Zoom digital</translation> <translation>Escala digital</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="712"/> <location filename="../src/GUI/gui.cpp" line="712"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Escala</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="725"/> <location filename="../src/GUI/gui.cpp" line="725"/>
@ -752,7 +752,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="727"/> <location filename="../src/GUI/gui.cpp" line="727"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>Carpeta de POIs:</translation> <translation>Carpeta de POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="729"/> <location filename="../src/GUI/gui.cpp" line="729"/>
@ -788,17 +788,17 @@
<location filename="../src/GUI/gui.cpp" line="842"/> <location filename="../src/GUI/gui.cpp" line="842"/>
<location filename="../src/GUI/gui.cpp" line="877"/> <location filename="../src/GUI/gui.cpp" line="877"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Linea: %1</translation> <translation>Renglón: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="850"/> <location filename="../src/GUI/gui.cpp" line="850"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Cargar archivo de POI&apos;s</translation> <translation>Cargar archivo de POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="874"/> <location filename="../src/GUI/gui.cpp" line="874"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Error cargando archivo de POI&apos;s:</translation> <translation>Error al cargar el archivo de POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1028"/> <location filename="../src/GUI/gui.cpp" line="1028"/>
@ -816,7 +816,7 @@
<location filename="../src/GUI/gui.cpp" line="1034"/> <location filename="../src/GUI/gui.cpp" line="1034"/>
<location filename="../src/GUI/gui.cpp" line="1103"/> <location filename="../src/GUI/gui.cpp" line="1103"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Waypoints</translation> <translation>Puntos de referencia</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1037"/> <location filename="../src/GUI/gui.cpp" line="1037"/>
@ -851,7 +851,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1336"/> <location filename="../src/GUI/gui.cpp" line="1336"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Error cargando archivo de mapa:</translation> <translation>Error al cargar el archivo de mapa:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1347"/> <location filename="../src/GUI/gui.cpp" line="1347"/>
@ -878,7 +878,7 @@
<message> <message>
<location filename="../src/GUI/gearratiograph.cpp" line="27"/> <location filename="../src/GUI/gearratiograph.cpp" line="27"/>
<source>Most used</source> <source>Most used</source>
<translation>Mas usada</translation> <translation>Más usada</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gearratiograph.cpp" line="29"/> <location filename="../src/GUI/gearratiograph.cpp" line="29"/>
@ -914,7 +914,7 @@
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="46"/> <location filename="../src/GUI/graphview.cpp" line="46"/>
<source>Data not available</source> <source>Data not available</source>
<translation>Sin datos</translation> <translation>Sin datos disponibles</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="66"/> <location filename="../src/GUI/graphview.cpp" line="66"/>
@ -926,7 +926,7 @@
<location filename="../src/GUI/graphview.cpp" line="110"/> <location filename="../src/GUI/graphview.cpp" line="110"/>
<location filename="../src/GUI/graphview.cpp" line="118"/> <location filename="../src/GUI/graphview.cpp" line="118"/>
<source>ft</source> <source>ft</source>
<translation></translation> <translation>ft</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="113"/> <location filename="../src/GUI/graphview.cpp" line="113"/>
@ -1017,7 +1017,7 @@
<message> <message>
<location filename="../src/map/maplist.cpp" line="121"/> <location filename="../src/map/maplist.cpp" line="121"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Formatos soportados</translation> <translation>Formatos admitidos</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="126"/> <location filename="../src/map/maplist.cpp" line="126"/>
@ -1047,7 +1047,7 @@
<message> <message>
<location filename="../src/map/maplist.cpp" line="128"/> <location filename="../src/map/maplist.cpp" line="128"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>Imagenes GeoTIFF</translation> <translation>Imágenes GeoTIFF</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="129"/> <location filename="../src/map/maplist.cpp" line="129"/>
@ -1057,7 +1057,7 @@
<message> <message>
<location filename="../src/map/maplist.cpp" line="130"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Mapas Online</translation> <translation>Fuentes de mapas en nea</translation>
</message> </message>
</context> </context>
<context> <context>
@ -1065,12 +1065,12 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="61"/> <location filename="../src/GUI/optionsdialog.cpp" line="61"/>
<source>High-resolution</source> <source>High-resolution</source>
<translation>Alta resolución</translation> <translation>Resolución alta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="62"/> <location filename="../src/GUI/optionsdialog.cpp" line="62"/>
<source>Standard</source> <source>Standard</source>
<translation>Estandar</translation> <translation>Estándar</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="67"/> <location filename="../src/GUI/optionsdialog.cpp" line="67"/>
@ -1185,12 +1185,12 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="211"/> <location filename="../src/GUI/optionsdialog.cpp" line="211"/>
<source>Waypoint color:</source> <source>Waypoint color:</source>
<translation>Color de waypoints:</translation> <translation>Color de puntos de referencia:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="212"/> <location filename="../src/GUI/optionsdialog.cpp" line="212"/>
<source>Waypoint size:</source> <source>Waypoint size:</source>
<translation>Tamaño de wapoints:</translation> <translation>Tamaño de puntos de referencia:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="214"/> <location filename="../src/GUI/optionsdialog.cpp" line="214"/>
@ -1207,27 +1207,27 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="216"/> <location filename="../src/GUI/optionsdialog.cpp" line="216"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Waypoints</translation> <translation>Puntos de referencia</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="227"/> <location filename="../src/GUI/optionsdialog.cpp" line="227"/>
<source>POI color:</source> <source>POI color:</source>
<translation>Color de POI&apos;s:</translation> <translation>Color de POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="228"/> <location filename="../src/GUI/optionsdialog.cpp" line="228"/>
<source>POI size:</source> <source>POI size:</source>
<translation>Tamaño de POI&apos;s:</translation> <translation>Tamaño de POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="232"/> <location filename="../src/GUI/optionsdialog.cpp" line="232"/>
<source>POIs</source> <source>POIs</source>
<translation>POI&apos;s</translation> <translation>POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="258"/> <location filename="../src/GUI/optionsdialog.cpp" line="258"/>
<source>Line width:</source> <source>Line width:</source>
<translation>Anchura de linea:</translation> <translation>Anchura de línea:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="259"/> <location filename="../src/GUI/optionsdialog.cpp" line="259"/>
@ -1435,17 +1435,17 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="509"/> <location filename="../src/GUI/optionsdialog.cpp" line="509"/>
<source>High-Resolution</source> <source>High-Resolution</source>
<translation>Alta resolución</translation> <translation>Resolución alta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="514"/> <location filename="../src/GUI/optionsdialog.cpp" line="514"/>
<source>The printed area is approximately the display area. The map zoom level does not change.</source> <source>The printed area is approximately the display area. The map zoom level does not change.</source>
<translation>El área que se imprime es la que muestra la pantalla. El zoom del mapa no cambiará.</translation> <translation>El área que se imprime es aproximadamente la que muestra la pantalla. La escala del mapa no cambiará.</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="516"/> <location filename="../src/GUI/optionsdialog.cpp" line="516"/>
<source>The zoom level will be changed so that the whole content (tracks/waypoints) fits to the printed area and the map resolution is as close as possible to the print resolution.</source> <source>The zoom level will be changed so that the whole content (tracks/waypoints) fits to the printed area and the map resolution is as close as possible to the print resolution.</source>
<translation>El zoom del mapa se cambia para que el area impresa se ajuste a todos los elementos( tracks, waypoints...) y la resolución sea lo mas próxima posible a la de impresión.</translation> <translation>La escala del mapa se cambia para que el área impresa se ajuste a todos los elementos (pistas, puntos de referencia...) y la resolución sea lo mas próxima posible a la de impresión.</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="538"/> <location filename="../src/GUI/optionsdialog.cpp" line="538"/>
@ -1500,17 +1500,17 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="585"/> <location filename="../src/GUI/optionsdialog.cpp" line="585"/>
<source>Enable HTTP/2</source> <source>Enable HTTP/2</source>
<translation>Habilitar HTTP/2</translation> <translation>Activar HTTP/2</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="592"/> <location filename="../src/GUI/optionsdialog.cpp" line="592"/>
<source>MB</source> <source>MB</source>
<translation>Mo</translation> <translation>MB</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="602"/> <location filename="../src/GUI/optionsdialog.cpp" line="602"/>
<source>Image cache size:</source> <source>Image cache size:</source>
<translation>Tamaño del cache de imágenes:</translation> <translation>Tamaño de antememoria de imágenes:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="603"/> <location filename="../src/GUI/optionsdialog.cpp" line="603"/>
@ -1591,7 +1591,7 @@
<message> <message>
<location filename="../src/GUI/powergraphitem.cpp" line="17"/> <location filename="../src/GUI/powergraphitem.cpp" line="17"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maxima</translation> <translation>Máxima</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/powergraphitem.cpp" line="18"/> <location filename="../src/GUI/powergraphitem.cpp" line="18"/>
@ -1639,7 +1639,7 @@
<location filename="../src/GUI/scaleitem.cpp" line="109"/> <location filename="../src/GUI/scaleitem.cpp" line="109"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/> <location filename="../src/GUI/scaleitem.cpp" line="112"/>
<source>ft</source> <source>ft</source>
<translation></translation> <translation>ft</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/scaleitem.cpp" line="111"/> <location filename="../src/GUI/scaleitem.cpp" line="111"/>

View File

@ -114,7 +114,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="195"/> <location filename="../src/data/data.cpp" line="195"/>
<source>SML files</source> <source>SML files</source>
<translation type="unfinished"></translation> <translation>SML-tiedostot</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="196"/> <location filename="../src/data/data.cpp" line="196"/>

1900
lang/gpxsee_hu.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
<location filename="../src/GUI/cadencegraph.cpp" line="12"/> <location filename="../src/GUI/cadencegraph.cpp" line="12"/>
<location filename="../src/GUI/cadencegraph.h" line="16"/> <location filename="../src/GUI/cadencegraph.h" line="16"/>
<source>Cadence</source> <source>Cadence</source>
<translation type="unfinished">Stegfrekvens</translation> <translation>Stegfrekvens</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/cadencegraph.cpp" line="27"/> <location filename="../src/GUI/cadencegraph.cpp" line="27"/>
@ -214,7 +214,7 @@
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="25"/> <location filename="../src/GUI/exportdialog.cpp" line="25"/>
<source>All files</source> <source>All files</source>
<translation type="unfinished">Alle filer</translation> <translation>Alle filer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="52"/> <location filename="../src/GUI/exportdialog.cpp" line="52"/>
@ -239,7 +239,7 @@
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="94"/> <location filename="../src/GUI/exportdialog.cpp" line="94"/>
<source>Page Setup</source> <source>Page Setup</source>
<translation>Sideinnstilling</translation> <translation>Sideoppsett</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/exportdialog.cpp" line="97"/> <location filename="../src/GUI/exportdialog.cpp" line="97"/>
@ -373,17 +373,17 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="217"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation type="unfinished">Åpne</translation> <translation>Åpne</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="222"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation type="unfinished">Skriv ut</translation> <translation>Skriv ut</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="229"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation type="unfinished">Eksporter til PDF</translation> <translation>Eksporter til PDF</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="235"/>
@ -398,12 +398,12 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="248"/>
<source>Statistics...</source> <source>Statistics...</source>
<translation type="unfinished">Statistikk</translation> <translation>Statistikk</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="256"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation type="unfinished">Last inn POI-fil</translation> <translation>Last inn POI-fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="260"/> <location filename="../src/GUI/gui.cpp" line="260"/>
@ -433,7 +433,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="292"/> <location filename="../src/GUI/gui.cpp" line="292"/>
<source>Load map...</source> <source>Load map...</source>
<translation type="unfinished">Last inn kart</translation> <translation>Last inn kart</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="296"/> <location filename="../src/GUI/gui.cpp" line="296"/>
@ -485,7 +485,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="352"/> <location filename="../src/GUI/gui.cpp" line="352"/>
<source>km/mi markers</source> <source>km/mi markers</source>
<translation type="unfinished">km/mi-markører</translation> <translation>km/mi-markører</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="359"/> <location filename="../src/GUI/gui.cpp" line="359"/>
@ -520,7 +520,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="393"/>
<source>Show path markers</source> <source>Show path markers</source>
<translation type="unfinished">Vis veimarkører</translation> <translation>Vis veimarkører</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="400"/> <location filename="../src/GUI/gui.cpp" line="400"/>
@ -557,17 +557,17 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="441"/> <location filename="../src/GUI/gui.cpp" line="441"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation type="unfinished">Desimalgrader (DD)</translation> <translation>Desimalgrader (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="447"/> <location filename="../src/GUI/gui.cpp" line="447"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation type="unfinished">Desimalgrader og desimalminutter (DMM)</translation> <translation>Desimalgrader og desimalminutter (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="454"/> <location filename="../src/GUI/gui.cpp" line="454"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation type="unfinished">Grader, minutter, sekunder (DMS)</translation> <translation>Grader, minutter, sekunder (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="460"/> <location filename="../src/GUI/gui.cpp" line="460"/>
@ -577,7 +577,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="467"/> <location filename="../src/GUI/gui.cpp" line="467"/>
<source>Options...</source> <source>Options...</source>
<translation type="unfinished">Valg</translation> <translation>Valg</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="473"/> <location filename="../src/GUI/gui.cpp" line="473"/>
@ -647,7 +647,7 @@
<message> <message>
<location filename="../src/GUI/gui.cpp" line="559"/> <location filename="../src/GUI/gui.cpp" line="559"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation type="unfinished">Koordinatformat</translation> <translation>Koordinatformat</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="569"/> <location filename="../src/GUI/gui.cpp" line="569"/>
@ -861,7 +861,7 @@
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1351"/> <location filename="../src/GUI/gui.cpp" line="1351"/>
<source>%n files</source> <source>%n files</source>
<translation type="unfinished"> <translation>
<numerusform>%n fil</numerusform> <numerusform>%n fil</numerusform>
<numerusform>%n filer</numerusform> <numerusform>%n filer</numerusform>
</translation> </translation>
@ -974,7 +974,7 @@
<message> <message>
<location filename="../src/GUI/heartrategraph.cpp" line="11"/> <location filename="../src/GUI/heartrategraph.cpp" line="11"/>
<source>bpm</source> <source>bpm</source>
<translation type="unfinished">s/m</translation> <translation>bpm</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/heartrategraph.cpp" line="12"/> <location filename="../src/GUI/heartrategraph.cpp" line="12"/>
@ -1095,12 +1095,12 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="176"/> <location filename="../src/GUI/optionsdialog.cpp" line="176"/>
<source>Palette shift:</source> <source>Palette shift:</source>
<translation type="unfinished">Palettforskyvning:</translation> <translation>Palettforskyvning:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="120"/> <location filename="../src/GUI/optionsdialog.cpp" line="120"/>
<source>Track width:</source> <source>Track width:</source>
<translation type="unfinished">Sporbredde:</translation> <translation>Sporbredde:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="80"/> <location filename="../src/GUI/optionsdialog.cpp" line="80"/>
@ -1115,7 +1115,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="121"/> <location filename="../src/GUI/optionsdialog.cpp" line="121"/>
<source>Track style:</source> <source>Track style:</source>
<translation type="unfinished">Sporstil:</translation> <translation>Sporstil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="123"/> <location filename="../src/GUI/optionsdialog.cpp" line="123"/>
@ -1159,12 +1159,12 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="156"/> <location filename="../src/GUI/optionsdialog.cpp" line="156"/>
<source>Area border style:</source> <source>Area border style:</source>
<translation type="unfinished">Kantstil for område:</translation> <translation>Kantstil for område:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="157"/> <location filename="../src/GUI/optionsdialog.cpp" line="157"/>
<source>Area fill opacity:</source> <source>Area fill opacity:</source>
<translation type="unfinished">Fylldekkevne for område:</translation> <translation>Ugjennomsiktighet for område:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="161"/> <location filename="../src/GUI/optionsdialog.cpp" line="161"/>
@ -1232,7 +1232,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="259"/> <location filename="../src/GUI/optionsdialog.cpp" line="259"/>
<source>Slider color:</source> <source>Slider color:</source>
<translation type="unfinished">Linjalfarge:</translation> <translation>Farge skyveregulering:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="282"/> <location filename="../src/GUI/optionsdialog.cpp" line="282"/>
@ -1374,7 +1374,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="448"/> <location filename="../src/GUI/optionsdialog.cpp" line="448"/>
<source>Elevation</source> <source>Elevation</source>
<translation type="unfinished">Høyde</translation> <translation>Høyde</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="459"/> <location filename="../src/GUI/optionsdialog.cpp" line="459"/>
@ -1668,17 +1668,17 @@
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="31"/> <location filename="../src/GUI/speedgraph.cpp" line="31"/>
<source>min/km</source> <source>min/km</source>
<translation type="unfinished">min/km</translation> <translation>min/km</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="32"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>min/mi</source> <source>min/mi</source>
<translation type="unfinished">min/mi</translation> <translation>min/mi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="32"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>min/nmi</source> <source>min/nmi</source>
<translation type="unfinished">min/nmi</translation> <translation>min/nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="34"/> <location filename="../src/GUI/speedgraph.cpp" line="34"/>
@ -1741,7 +1741,7 @@
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="28"/> <location filename="../src/GUI/speedgraphitem.cpp" line="28"/>
<source>min/nmi</source> <source>min/nmi</source>
<translation type="unfinished">min/nmi</translation> <translation>min/nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="31"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>

View File

@ -59,7 +59,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="181"/> <location filename="../src/data/data.cpp" line="181"/>
<source>CUP files</source> <source>CUP files</source>
<translation type="unfinished"></translation> <translation>Pliki CUP</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="182"/> <location filename="../src/data/data.cpp" line="182"/>
@ -74,7 +74,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="186"/> <location filename="../src/data/data.cpp" line="186"/>
<source>GPI files</source> <source>GPI files</source>
<translation type="unfinished"></translation> <translation>Pliki GPI</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="187"/> <location filename="../src/data/data.cpp" line="187"/>
@ -114,7 +114,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="195"/> <location filename="../src/data/data.cpp" line="195"/>
<source>SML files</source> <source>SML files</source>
<translation type="unfinished"></translation> <translation>Pliki SML</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="196"/> <location filename="../src/data/data.cpp" line="196"/>

View File

@ -114,7 +114,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="195"/> <location filename="../src/data/data.cpp" line="195"/>
<source>SML files</source> <source>SML files</source>
<translation type="unfinished"></translation> <translation>SML файлы</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="196"/> <location filename="../src/data/data.cpp" line="196"/>

View File

@ -119,7 +119,7 @@
<message> <message>
<location filename="../src/data/data.cpp" line="195"/> <location filename="../src/data/data.cpp" line="195"/>
<source>SML files</source> <source>SML files</source>
<translation type="unfinished"></translation> <translation>SML файли</translation>
</message> </message>
<message> <message>
<location filename="../src/data/data.cpp" line="196"/> <location filename="../src/data/data.cpp" line="196"/>

View File

@ -4,6 +4,7 @@ Comment=GPS log file viewer and analyzer
Comment[cz]=Prohlížeč a analyzátor GPS logů Comment[cz]=Prohlížeč a analyzátor GPS logů
Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
Comment[fr]=Visualisation et analyse de fichier GPS Comment[fr]=Visualisation et analyse de fichier GPS
Comment[nb]=GPS-loggfilleser og analysator
Comment[pl]=Przeglądarka i analizator plików dziennika GPS Comment[pl]=Przeglądarka i analizator plików dziennika GPS
Comment[ru]=Программа для просмотра и анализа GPS логов Comment[ru]=Программа для просмотра и анализа GPS логов
Comment[sv]=GPS-loggfilsläsare och analysator Comment[sv]=GPS-loggfilsläsare och analysator
@ -14,4 +15,4 @@ Icon=gpxsee
Terminal=false Terminal=false
Type=Application Type=Application
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt; Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt;
MimeType=application/gpx+xml;application/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/loc+xml;application/slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi; MimeType=application/gpx+xml;application/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/loc+xml;application/slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/sml+xml;

View File

@ -7,7 +7,7 @@
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "7.20" !define VERSION "7.22"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}.exe" OutFile "GPXSee-${VERSION}.exe"
@ -176,6 +176,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Finnish" "fi" !insertmacro LOCALIZATION "Finnish" "fi"
!insertmacro LOCALIZATION "French" "fr" !insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de" !insertmacro LOCALIZATION "German" "de"
!insertmacro LOCALIZATION "Hungarian" "hu"
!insertmacro LOCALIZATION "Norwegian" "nb" !insertmacro LOCALIZATION "Norwegian" "nb"
!insertmacro LOCALIZATION "Polish" "pl" !insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR" !insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"

View File

@ -7,7 +7,7 @@
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "7.20" !define VERSION "7.22"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"
@ -183,6 +183,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Finnish" "fi" !insertmacro LOCALIZATION "Finnish" "fi"
!insertmacro LOCALIZATION "French" "fr" !insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de" !insertmacro LOCALIZATION "German" "de"
!insertmacro LOCALIZATION "Hungarian" "hu"
!insertmacro LOCALIZATION "Norwegian" "nb" !insertmacro LOCALIZATION "Norwegian" "nb"
!insertmacro LOCALIZATION "Polish" "pl" !insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR" !insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"

View File

@ -112,7 +112,7 @@ void GUI::loadMaps()
QString mapDir(ProgramPaths::mapDir()); QString mapDir(ProgramPaths::mapDir());
if (!mapDir.isNull() && !_ml->loadDir(mapDir)) if (!mapDir.isNull() && !_ml->loadDir(mapDir))
qWarning("%s", qPrintable(_ml->errorString())); qWarning("%s", qPrintable(_ml->errorPath() + ": " + _ml->errorString()));
_map = new EmptyMap(this); _map = new EmptyMap(this);
} }
@ -1325,7 +1325,10 @@ bool GUI::loadMap(const QString &fileName)
if (fileName.isEmpty()) if (fileName.isEmpty())
return false; return false;
if (_ml->loadFile(fileName)) { QFileInfo fi(fileName);
bool res = fi.isDir() ? _ml->loadDir(fileName) : _ml->loadFile(fileName);
if (res) {
QAction *a = createMapAction(_ml->maps().last()); QAction *a = createMapAction(_ml->maps().last());
_mapMenu->insertAction(_mapsEnd, a); _mapMenu->insertAction(_mapsEnd, a);
_showMapAction->setEnabled(true); _showMapAction->setEnabled(true);

View File

@ -44,37 +44,37 @@ static CUPParser cup;
static GPIParser gpi; static GPIParser gpi;
static SMLParser sml; static SMLParser sml;
static QHash<QString, Parser*> parsers() static QMap<QString, Parser*> parsers()
{ {
QHash<QString, Parser*> hash; QMap<QString, Parser*> map;
hash.insert("gpx", &gpx); map.insert("gpx", &gpx);
hash.insert("tcx", &tcx); map.insert("tcx", &tcx);
hash.insert("kml", &kml); map.insert("kml", &kml);
hash.insert("fit", &fit); map.insert("fit", &fit);
hash.insert("csv", &csv); map.insert("csv", &csv);
hash.insert("igc", &igc); map.insert("igc", &igc);
hash.insert("nmea", &nmea); map.insert("nmea", &nmea);
hash.insert("plt", &plt); map.insert("plt", &plt);
hash.insert("wpt", &wpt); map.insert("wpt", &wpt);
hash.insert("rte", &rte); map.insert("rte", &rte);
hash.insert("loc", &loc); map.insert("loc", &loc);
hash.insert("slf", &slf); map.insert("slf", &slf);
#ifdef ENABLE_GEOJSON #ifdef ENABLE_GEOJSON
hash.insert("json", &geojson); map.insert("json", &geojson);
hash.insert("geojson", &geojson); map.insert("geojson", &geojson);
#endif // ENABLE_GEOJSON #endif // ENABLE_GEOJSON
hash.insert("jpeg", &exif); map.insert("jpeg", &exif);
hash.insert("jpg", &exif); map.insert("jpg", &exif);
hash.insert("cup", &cup); map.insert("cup", &cup);
hash.insert("gpi", &gpi); map.insert("gpi", &gpi);
hash.insert("sml", &sml); map.insert("sml", &sml);
return hash; return map;
} }
QHash<QString, Parser*> Data::_parsers = parsers(); QMap<QString, Parser*> Data::_parsers = parsers();
bool Data::_useDEM = false; bool Data::_useDEM = false;
void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData) void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData)
@ -130,7 +130,7 @@ Data::Data(const QString &fileName, bool poi)
return; return;
} }
QHash<QString, Parser*>::iterator it; QMap<QString, Parser*>::iterator it;
if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) { if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) {
if (it.value()->parse(&file, trackData, routeData, _polygons, if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) { _waypoints)) {
@ -166,17 +166,8 @@ Data::Data(const QString &fileName, bool poi)
QString Data::formats() QString Data::formats()
{ {
QStringList l(filter());
qSort(l);
QString supported;
for (int i = 0; i < l.size(); i++) {
supported += l.at(i);
if (i != l.size() - 1)
supported += " ";
}
return return
qApp->translate("Data", "Supported files") + " (" + supported + ");;" qApp->translate("Data", "Supported files") + " (" + filter().join(" ") + ");;"
+ qApp->translate("Data", "CSV files") + " (*.csv);;" + qApp->translate("Data", "CSV files") + " (*.csv);;"
+ qApp->translate("Data", "CUP files") + " (*.cup);;" + qApp->translate("Data", "CUP files") + " (*.cup);;"
+ qApp->translate("Data", "FIT files") + " (*.fit);;" + qApp->translate("Data", "FIT files") + " (*.fit);;"
@ -200,10 +191,10 @@ QString Data::formats()
QStringList Data::filter() QStringList Data::filter()
{ {
QStringList filter; QStringList filter;
QHash<QString, Parser*>::iterator it;
for (it = _parsers.begin(); it != _parsers.end(); it++) for (QMap<QString, Parser*>::iterator it = _parsers.begin();
filter << QString("*.%1").arg(it.key()); it != _parsers.end(); it++)
filter << "*." + it.key();
return filter; return filter;
} }

View File

@ -2,7 +2,7 @@
#define DATA_H #define DATA_H
#include <QList> #include <QList>
#include <QHash> #include <QMap>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include "waypoint.h" #include "waypoint.h"
@ -42,7 +42,7 @@ private:
QList<Area> _polygons; QList<Area> _polygons;
QVector<Waypoint> _waypoints; QVector<Waypoint> _waypoints;
static QHash<QString, Parser*> _parsers; static QMap<QString, Parser*> _parsers;
static bool _useDEM; static bool _useDEM;
}; };

View File

@ -32,7 +32,7 @@ bool BitStream1::read(int bits, quint32 &val)
bool BitStream1::flush() bool BitStream1::flush()
{ {
if (_length && !_file.seek(_hdl, _hdl.pos + _length)) if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
return false; return false;
_length = 0; _length = 0;
@ -50,18 +50,13 @@ bool BitStream4::read(int bits, quint32 &val)
return true; return true;
} }
quint32 old = 0; quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
if (_used < 32) { quint32 bytes = qMin(_length, 4U);
old = (_data << _used) >> (32 - bits);
bits = (bits - 32) + _used;
}
_used = bits;
quint32 bytes = qMin(_length, (quint32)4);
if (!_file.readVUInt32SW(_hdl, bytes, _data)) if (!_file.readVUInt32SW(_hdl, bytes, _data))
return false; return false;
_used -= 32 - bits;
_length -= bytes; _length -= bytes;
_unused = (4 - bytes) * 8; _unused = (4 - bytes) * 8;
_data <<= _unused; _data <<= _unused;
@ -73,11 +68,12 @@ bool BitStream4::read(int bits, quint32 &val)
bool BitStream4::flush() bool BitStream4::flush()
{ {
if (_length && !_file.seek(_hdl, _hdl.pos + _length)) if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
return false; return false;
_length = 0; _length = 0;
_unused = 32; _used = 32;
_unused = 0;
return true; return true;
} }

151
src/map/IMG/gmap.cpp Normal file
View File

@ -0,0 +1,151 @@
#include <QXmlStreamReader>
#include <QDir>
#include "vectortile.h"
#include "gmap.h"
static SubFile::Type tileType(const QString &suffix)
{
if (!suffix.compare("TRE"))
return SubFile::TRE;
else if (!suffix.compare("RGN"))
return SubFile::RGN;
else if (!suffix.compare("LBL"))
return SubFile::LBL;
else if (!suffix.compare("TYP"))
return SubFile::TYP;
else if (!suffix.compare("GMP"))
return SubFile::GMP;
else if (!suffix.compare("NET"))
return SubFile::NET;
else
return SubFile::Unknown;
}
void GMAP::subProduct(QXmlStreamReader &reader, QString &dataDir,
QString &baseMap)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Directory")
dataDir = reader.readElementText();
else if (reader.name() == "BaseMap")
baseMap = reader.readElementText();
else
reader.skipCurrentElement();
}
}
void GMAP::mapProduct(QXmlStreamReader &reader, QString &dataDir,
QString &typFile, QString &baseMap)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Name")
_name = reader.readElementText();
else if (reader.name() == "TYP")
typFile = reader.readElementText();
else if (reader.name() == "SubProduct")
subProduct(reader, dataDir, baseMap);
else
reader.skipCurrentElement();
}
}
bool GMAP::readXML(const QString &path, QString &dataDir, QString &typFile,
QString &baseMap)
{
QFile file(path);
if (!file.open(QFile::ReadOnly | QFile::Text))
return false;
QXmlStreamReader reader(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "MapProduct")
mapProduct(reader, dataDir, typFile, baseMap);
else
reader.raiseError("Not a GMAP XML file");
}
if (reader.error()) {
_errorString = QString("%1: %2").arg(reader.lineNumber())
.arg(reader.errorString());
return false;
}
return true;
}
bool GMAP::loadTile(const QDir &dir, bool baseMap)
{
VectorTile *tile = new VectorTile();
QFileInfoList ml = dir.entryInfoList(QDir::Files);
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
tile->addFile(fi.absoluteFilePath(), tileType(fi.suffix()));
}
if (!tile->init(baseMap)) {
qWarning("%s: Invalid map tile", qPrintable(dir.path()));
delete tile;
return false;
}
double min[2], max[2];
min[0] = tile->bounds().left();
min[1] = tile->bounds().bottom();
max[0] = tile->bounds().right();
max[1] = tile->bounds().top();
_tileTree.Insert(min, max, tile);
_bounds |= tile->bounds();
return true;
}
GMAP::GMAP(const QString &fileName) : _fileName(fileName)
{
QString dataDirPath, typFilePath, baseMapPath;
if (!readXML(fileName, dataDirPath, typFilePath, baseMapPath))
return;
QDir baseDir(QFileInfo(fileName).absoluteDir());
if (!baseDir.exists(dataDirPath)) {
_errorString = "Missing/invalid map data directory";
return;
}
QDir dataDir(baseDir.filePath(dataDirPath));
QFileInfoList ml = dataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfo baseMap(dataDir.filePath(baseMapPath));
_baseMap = !baseMapPath.isEmpty() && baseMap.exists();
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
if (fi.isDir())
loadTile(QDir(fi.absoluteFilePath()),
fi.absoluteFilePath() == baseMap.absoluteFilePath());
}
if (baseDir.exists(typFilePath))
_typ = new SubFile(baseDir.filePath(typFilePath));
if (!_tileTree.Count())
_errorString = "No usable map tile found";
else
_valid = true;
}
bool GMAP::isGMAP(const QString &path)
{
QFile file(path);
if (!file.open(QFile::ReadOnly | QFile::Text))
return false;
QXmlStreamReader reader(&file);
if (reader.readNextStartElement() && reader.name() == "MapProduct")
return true;
return false;
}

30
src/map/IMG/gmap.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef GMAP_H
#define GMAP_H
#include "mapdata.h"
class QXmlStreamReader;
class QDir;
class GMAP : public MapData
{
public:
GMAP(const QString &fileName);
QString fileName() const {return _fileName;}
static bool isGMAP(const QString &path);
private:
bool readXML(const QString &path, QString &dataDir, QString &typFile,
QString &baseMap);
void mapProduct(QXmlStreamReader &reader, QString &dataDir,
QString &typFile, QString &baseMap);
void subProduct(QXmlStreamReader &reader, QString &dataDir,
QString &baseMap);
bool loadTile(const QDir &dir, bool baseMap);
QString _fileName;
};
#endif // GMAP_H

View File

@ -23,29 +23,6 @@ HuffmanStream::HuffmanStream(const SubFile &file, SubFile::Handle &hdl,
} }
} }
bool HuffmanStream::readNext(qint32 &lonDelta, qint32 &latDelta)
{
if (!readDelta(_lonSign, lonDelta))
return false;
if (!readDelta(_latSign, latDelta))
return false;
if (!(lonDelta|latDelta))
return false;
return true;
}
bool HuffmanStream::readOffset(qint32 &lonDelta, qint32 &latDelta)
{
if (!readDelta(1, lonDelta))
return false;
if (!readDelta(1, latDelta))
return false;
return true;
}
bool HuffmanStream::sign(int &val) bool HuffmanStream::sign(int &val)
{ {
quint32 bit; quint32 bit;
@ -64,21 +41,17 @@ bool HuffmanStream::sign(int &val)
bool HuffmanStream::readDelta(int sign, qint32 &symbol) bool HuffmanStream::readDelta(int sign, qint32 &symbol)
{ {
uchar size; quint8 size;
if (_symbolDataSize < 32) {
quint32 next; quint32 next;
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), bitsAvailable());
bitsAvailable());
if (!read(nextSize, next)) if (!read(nextSize, next))
return false; return false;
_symbolData = (_symbolData << nextSize) | next; _symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize; _symbolDataSize += nextSize;
}
symbol = _table.symbol(_symbolData << (32U - _symbolDataSize), size); symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
if (size <= _symbolDataSize) if (size <= _symbolDataSize)
_symbolDataSize -= size; _symbolDataSize -= size;

View File

@ -9,8 +9,16 @@ public:
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length, HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
const HuffmanTable &table, bool line); const HuffmanTable &table, bool line);
bool readNext(qint32 &lonDelta, qint32 &latDelta); bool readNext(qint32 &lonDelta, qint32 &latDelta)
bool readOffset(qint32 &lonDelta, qint32 &latDelta); {
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
return false;
return (lonDelta || latDelta);
}
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
bool atEnd() const bool atEnd() const
{return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();} {return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();}

View File

@ -55,7 +55,7 @@ bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
return false; return false;
if (!file.readVUInt32(hdl, recordSize)) if (!file.readVUInt32(hdl, recordSize))
return false; return false;
recordOffset = hdl.pos + recordSize; recordOffset = hdl.pos() + recordSize;
if (recordOffset > offset + size) if (recordOffset > offset + size)
return false; return false;
}; };

View File

@ -1,27 +1,10 @@
#include <QMap> #include <QMap>
#include <QtEndian> #include <QtEndian>
#include "common/programpaths.h"
#include "vectortile.h" #include "vectortile.h"
#include "img.h" #include "img.h"
#define CACHE_SIZE 8388608 /* 8MB */ typedef QMap<QByteArray, VectorTile*> TileMap;
typedef QMap<QString, VectorTile*> TileMap;
struct CTX
{
CTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
: rect(rect), bits(bits), polygons(polygons), lines(lines),
points(points) {}
const RectC &rect;
int bits;
QList<IMG::Poly> *polygons;
QList<IMG::Poly> *lines;
QList<IMG::Point> *points;
};
static SubFile::Type tileType(const char str[3]) static SubFile::Type tileType(const char str[3])
{ {
@ -41,8 +24,7 @@ static SubFile::Type tileType(const char str[3])
return SubFile::Unknown; return SubFile::Unknown;
} }
IMG::IMG(const QString &fileName) IMG::IMG(const QString &fileName) : _file(fileName)
: _file(fileName), _typ(0), _style(0), _valid(false)
{ {
#define CHECK(condition) \ #define CHECK(condition) \
if (!(condition)) { \ if (!(condition)) { \
@ -52,7 +34,7 @@ IMG::IMG(const QString &fileName)
} }
TileMap tileMap; TileMap tileMap;
QString typFile; QByteArray typFile;
if (!_file.open(QFile::ReadOnly)) { if (!_file.open(QFile::ReadOnly)) {
_errorString = _file.errorString(); _errorString = _file.errorString();
@ -78,8 +60,6 @@ IMG::IMG(const QString &fileName)
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2))); QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed(); _name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
_blockSize = 1 << (e1 + e2); _blockSize = 1 << (e1 + e2);
_blockCache.setMaxCost(CACHE_SIZE / _blockSize);
// Read the FAT table // Read the FAT table
quint8 flag; quint8 flag;
@ -107,7 +87,7 @@ IMG::IMG(const QString &fileName)
&& read(type, sizeof(type)) && readValue(size) && readValue(part)); && read(type, sizeof(type)) && readValue(size) && readValue(part));
SubFile::Type tt = tileType(type); SubFile::Type tt = tileType(type);
QString fn(QByteArray(name, sizeof(name))); QByteArray fn(name, sizeof(name));
if (VectorTile::isTileFile(tt)) { if (VectorTile::isTileFile(tt)) {
VectorTile *tile; VectorTile *tile;
TileMap::const_iterator it = tileMap.find(fn); TileMap::const_iterator it = tileMap.find(fn);
@ -156,7 +136,7 @@ IMG::IMG(const QString &fileName)
it != tileMap.constEnd(); ++it) { it != tileMap.constEnd(); ++it) {
VectorTile *tile = it.value(); VectorTile *tile = it.value();
if (!tile->init()) { if (!tile->init(false)) {
qWarning("%s: %s: Invalid map tile", qPrintable(_file.fileName()), qWarning("%s: %s: Invalid map tile", qPrintable(_file.fileName()),
qPrintable(it.key())); qPrintable(it.key()));
delete tile; delete tile;
@ -179,65 +159,6 @@ IMG::IMG(const QString &fileName)
_valid = true; _valid = true;
} }
IMG::~IMG()
{
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
delete _tileTree.GetAt(it);
delete _typ;
delete _style;
}
void IMG::load()
{
Q_ASSERT(!_style);
if (_typ)
_style = new Style(_typ);
else {
QFile typFile(ProgramPaths::typFile());
if (typFile.open(QIODevice::ReadOnly)) {
SubFile typ(&typFile);
_style = new Style(&typ);
} else
_style = new Style();
}
}
void IMG::clear()
{
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
_tileTree.GetAt(it)->clear();
delete _style;
_style = 0;
_blockCache.clear();
}
static bool cb(VectorTile *tile, void *context)
{
CTX *ctx = (CTX*)context;
tile->objects(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->points);
return true;
}
void IMG::objects(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points)
{
CTX ctx(rect, bits, polygons, lines, points);
double min[2], max[2];
min[0] = rect.left();
min[1] = rect.bottom();
max[0] = rect.right();
max[1] = rect.top();
_tileTree.Search(min, max, cb, &ctx);
}
qint64 IMG::read(char *data, qint64 maxSize) qint64 IMG::read(char *data, qint64 maxSize)
{ {
qint64 ret = _file.read(data, maxSize); qint64 ret = _file.read(data, maxSize);
@ -259,33 +180,12 @@ template<class T> bool IMG::readValue(T &val)
return true; return true;
} }
bool IMG::readBlock(int blockNum, QByteArray &data) bool IMG::readBlock(int blockNum, char *data)
{ {
QByteArray *block = _blockCache[blockNum];
if (!block) {
if (!_file.seek((qint64)blockNum * (qint64)_blockSize)) if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
return false; return false;
data.resize(_blockSize); if (read(data, _blockSize) < _blockSize)
if (read(data.data(), _blockSize) < _blockSize)
return false; return false;
_blockCache.insert(blockNum, new QByteArray(data));
} else
data = *block;
return true; return true;
} }
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const IMG::Point &point)
{
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
<< ", " << point.poi << ")";
return dbg.space();
}
QDebug operator<<(QDebug dbg, const IMG::Poly &poly)
{
dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -2,92 +2,26 @@
#define IMG_H #define IMG_H
#include <QFile> #include <QFile>
#include <QByteArray> #include "mapdata.h"
#include <QCache>
#include <QDebug>
#include "common/rtree.h"
#include "common/rectc.h"
#include "style.h"
#include "label.h"
class VectorTile; class IMG : public MapData
class SubFile;
class IMG
{ {
public: public:
struct Poly {
/* QPointF insted of Coordinates for performance reasons (no need to
duplicate all the vectors for drawing). Note, that we do not want to
ll2xy() the points in the IMG class as this can not be done in
parallel. */
QVector<QPointF> points;
Label label;
quint32 type;
bool operator<(const Poly &other) const
{return type > other.type;}
};
struct Point {
Point() : id(0) {}
Coordinates coordinates;
Label label;
quint32 type;
bool poi;
quint64 id;
bool operator<(const Point &other) const
{return id < other.id;}
};
IMG(const QString &fileName); IMG(const QString &fileName);
~IMG();
void load();
void clear();
QString fileName() const {return _file.fileName();} QString fileName() const {return _file.fileName();}
const QString &name() const {return _name;}
const RectC &bounds() const {return _bounds;}
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points);
const Style *style() const {return _style;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
private: private:
friend class SubFile; friend class SubFile;
typedef RTree<VectorTile*, double, 2> TileTree;
int blockSize() const {return _blockSize;} int blockSize() const {return _blockSize;}
bool readBlock(int blockNum, QByteArray &data); bool readBlock(int blockNum, char *data);
qint64 read(char *data, qint64 maxSize); qint64 read(char *data, qint64 maxSize);
template<class T> bool readValue(T &val); template<class T> bool readValue(T &val);
QFile _file; QFile _file;
quint8 _key; quint8 _key;
int _blockSize; int _blockSize;
QCache<int, QByteArray> _blockCache;
QString _name;
RectC _bounds;
TileTree _tileTree;
SubFile *_typ;
Style *_style;
bool _valid;
QString _errorString;
}; };
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const IMG::Point &point);
QDebug operator<<(QDebug dbg, const IMG::Poly &poly);
#endif // QT_NO_DEBUG
#endif // IMG_H #endif // IMG_H

View File

@ -12,6 +12,9 @@ public:
LBLFile(IMG *img) LBLFile(IMG *img)
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0), : SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {} _poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
LBLFile(const QString &path)
: SubFile(path), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0), _codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {} _poiMultiplier(0), _multiplier(0), _encoding(0) {}

123
src/map/IMG/mapdata.cpp Normal file
View File

@ -0,0 +1,123 @@
#include "common/programpaths.h"
#include "vectortile.h"
#include "style.h"
#include "mapdata.h"
#define CACHED_SUBDIVS_COUNT 2048 // ~32MB for both caches together
struct PolyCTX
{
PolyCTX(const RectC &rect, int bits, bool baseMap,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv*, MapData::Polys> *polyCache)
: rect(rect), bits(bits), baseMap(baseMap), polygons(polygons),
lines(lines), polyCache(polyCache) {}
const RectC &rect;
int bits;
bool baseMap;
QList<MapData::Poly> *polygons;
QList<MapData::Poly> *lines;
QCache<const SubDiv*, MapData::Polys> *polyCache;
};
struct PointCTX
{
PointCTX(const RectC &rect, int bits, bool baseMap,
QList<MapData::Point> *points,
QCache<const SubDiv*, QList<MapData::Point> > *pointCache)
: rect(rect), bits(bits), baseMap(baseMap), points(points),
pointCache(pointCache) {}
const RectC &rect;
int bits;
bool baseMap;
QList<MapData::Point> *points;
QCache<const SubDiv*, QList<MapData::Point> > *pointCache;
};
inline bool polyCb(VectorTile *tile, void *context)
{
PolyCTX *ctx = (PolyCTX*)context;
tile->polys(ctx->rect, ctx->bits, ctx->baseMap, ctx->polygons, ctx->lines,
ctx->polyCache);
return true;
}
inline bool pointCb(VectorTile *tile, void *context)
{
PointCTX *ctx = (PointCTX*)context;
tile->points(ctx->rect, ctx->bits, ctx->baseMap, ctx->points,
ctx->pointCache);
return true;
}
MapData::MapData() : _typ(0), _style(0), _baseMap(false), _valid(false)
{
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
_pointCache.setMaxCost(CACHED_SUBDIVS_COUNT);
}
MapData::~MapData()
{
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
delete _tileTree.GetAt(it);
delete _typ;
delete _style;
}
void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines)
{
PolyCTX ctx(rect, bits, _baseMap, polygons, lines, &_polyCache);
double min[2], max[2];
min[0] = rect.left();
min[1] = rect.bottom();
max[0] = rect.right();
max[1] = rect.top();
_tileTree.Search(min, max, polyCb, &ctx);
}
void MapData::points(const RectC &rect, int bits, QList<Point> *points)
{
PointCTX ctx(rect, bits, _baseMap, points, &_pointCache);
double min[2], max[2];
min[0] = rect.left();
min[1] = rect.bottom();
max[0] = rect.right();
max[1] = rect.top();
_tileTree.Search(min, max, pointCb, &ctx);
}
void MapData::load()
{
Q_ASSERT(!_style);
if (_typ)
_style = new Style(_typ);
else {
SubFile typ(ProgramPaths::typFile());
_style = new Style(&typ);
}
}
void MapData::clear()
{
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
_tileTree.GetAt(it)->clear();
delete _style;
_style = 0;
_polyCache.clear();
_pointCache.clear();
}

107
src/map/IMG/mapdata.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef MAPDATA_H
#define MAPDATA_H
#include <QList>
#include <QPointF>
#include <QCache>
#include <QDebug>
#include "common/rectc.h"
#include "common/rtree.h"
#include "label.h"
class Style;
class SubDiv;
class SubFile;
class VectorTile;
class MapData
{
public:
struct Poly {
/* QPointF insted of Coordinates for performance reasons (no need to
duplicate all the vectors for drawing). Note, that we do not want to
ll2xy() the points in the IMG class as this can not be done in
parallel. */
QVector<QPointF> points;
Label label;
quint32 type;
RectC boundingRect;
bool operator<(const Poly &other) const
{return type > other.type;}
};
struct Point {
Point() : id(0) {}
Coordinates coordinates;
Label label;
quint32 type;
bool poi;
quint64 id;
bool operator<(const Point &other) const
{return id < other.id;}
};
struct Polys {
Polys() {}
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> lines;
};
MapData();
virtual ~MapData();
const QString &name() const {return _name;}
const RectC &bounds() const {return _bounds;}
const Style *style() const {return _style;}
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines);
void points(const RectC &rect, int bits, QList<Point> *points);
void load();
void clear();
virtual QString fileName() const = 0;
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
protected:
typedef RTree<VectorTile*, double, 2> TileTree;
QString _name;
RectC _bounds;
SubFile *_typ;
Style *_style;
TileTree _tileTree;
bool _baseMap;
bool _valid;
QString _errorString;
private:
QCache<const SubDiv*, Polys> _polyCache;
QCache<const SubDiv*, QList<Point> > _pointCache;
};
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const MapData::Point &point)
{
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
<< ", " << point.poi << ")";
return dbg.space();
}
inline QDebug operator<<(QDebug dbg, const MapData::Poly &poly)
{
dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG
#endif // MAPDATA_H

View File

@ -6,9 +6,12 @@
class NETFile : public SubFile class NETFile : public SubFile
{ {
public: public:
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _multiplier(0) {} NETFile(IMG *img)
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), : SubFile(img), _offset(0), _size(0), _multiplier(0) {}
_offset(0), _size(0), _multiplier(0) {} NETFile(const QString &path)
: SubFile(path), _offset(0), _size(0), _multiplier(0) {}
NETFile(SubFile *gmp, quint32 offset)
: SubFile(gmp, offset), _offset(0), _size(0), _multiplier(0) {}
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset); bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);

View File

@ -35,11 +35,11 @@ bool RGNFile::skipClassFields(Handle &hdl) const
break; break;
} }
return seek(hdl, hdl.pos + rs); return seek(hdl, hdl.pos() + rs);
} }
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3], bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
Segment::Type type) const SegmentType type) const
{ {
quint32 bitfield = 0xFFFFFFFF; quint32 bitfield = 0xFFFFFFFF;
@ -53,7 +53,7 @@ bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3; quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3;
switch (i) { switch (i) {
case 5: case 5:
if (m == 1 && type == Segment::Point) { if (m == 1 && type == Point) {
quint16 u16; quint16 u16;
if (!readUInt16(hdl, u16)) if (!readUInt16(hdl, u16))
return false; return false;
@ -116,11 +116,16 @@ bool RGNFile::init(Handle &hdl)
return true; return true;
} }
bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, NETFile *net,
Handle &netHdl, QList<IMG::Poly> *polys) const Handle &netHdl, QList<IMG::Poly> *polys) const
{ {
if (!seek(hdl, segment.start())) const SubDiv::Segment &segment = (segmentType == Line)
? subdiv->lines() : subdiv->polygons();
if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false; return false;
quint32 labelPtr; quint32 labelPtr;
@ -128,7 +133,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
qint16 lon, lat; qint16 lon, lat;
quint16 len; quint16 len;
while (hdl.pos < (int)segment.end()) { while (hdl.pos() < (int)segment.end()) {
IMG::Poly poly; IMG::Poly poly;
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr) if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
@ -145,14 +150,14 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
if (!readUInt8(hdl, bitstreamInfo)) if (!readUInt8(hdl, bitstreamInfo))
return false; return false;
poly.type = (segment.type() == Segment::Polygon) poly.type = (segmentType == Polygon)
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8; ? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
RectC br(c, c); poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
qint32 lonDelta, latDelta; qint32 lonDelta, latDelta;
@ -164,14 +169,11 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c); poly.boundingRect = poly.boundingRect.united(c);
} }
if (!(stream.atEnd() && stream.flush())) if (!(stream.atEnd() && stream.flush()))
return false; return false;
if (!rect.intersects(br))
continue;
if (lbl && (labelPtr & 0x3FFFFF)) { if (lbl && (labelPtr & 0x3FFFFF)) {
if (labelPtr & 0x800000) { if (labelPtr & 0x800000) {
quint32 lblOff; quint32 lblOff;
@ -188,22 +190,25 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
return true; return true;
} }
bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const SubDiv *subdiv, quint32 shift, const Segment &segment, LBLFile *lbl, SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
Handle &lblHdl, QList<IMG::Poly> *polys, bool line) const QList<IMG::Poly> *polys) const
{ {
quint32 labelPtr, len; quint32 labelPtr, len;
quint8 type, subtype; quint8 type, subtype;
qint16 lon, lat; qint16 lon, lat;
const SubDiv::Segment &segment = (segmentType == Line)
? subdiv->extLines() : subdiv->extPolygons();
if (!seek(hdl, segment.start())) if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false; return false;
while (hdl.pos < (int)segment.end()) { while (hdl.pos() < (int)segment.end()) {
IMG::Poly poly; IMG::Poly poly;
QPoint pos; QPoint pos;
RectC br;
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype) if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
&& readInt16(hdl, lon) && readInt16(hdl, lat) && readInt16(hdl, lon) && readInt16(hdl, lat)
@ -218,7 +223,8 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
(subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits()))); (subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits())));
qint32 lonDelta, latDelta; qint32 lonDelta, latDelta;
HuffmanStream stream(*this, hdl, len, _huffmanTable, line); HuffmanStream stream(*this, hdl, len, _huffmanTable,
segmentType == Line);
if (shift) { if (shift) {
if (!stream.readOffset(lonDelta, latDelta)) if (!stream.readOffset(lonDelta, latDelta))
@ -227,7 +233,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
pos.y() | latDelta<<(32-subdiv->bits()-shift)); pos.y() | latDelta<<(32-subdiv->bits()-shift));
} }
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
br = RectC(c, c); poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
while (stream.readNext(lonDelta, latDelta)) { while (stream.readNext(lonDelta, latDelta)) {
@ -236,7 +242,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c); poly.boundingRect = poly.boundingRect.united(c);
} }
if (!(stream.atEnd() && stream.flush())) if (!(stream.atEnd() && stream.flush()))
@ -245,7 +251,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
br = RectC(c, c); poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
quint8 bitstreamInfo; quint8 bitstreamInfo;
@ -261,7 +267,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat())); poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c); poly.boundingRect = poly.boundingRect.united(c);
} }
if (!(stream.atEnd() && stream.flush())) if (!(stream.atEnd() && stream.flush()))
return false; return false;
@ -271,13 +277,10 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
return false; return false;
if (subtype & 0x80 && !skipClassFields(hdl)) if (subtype & 0x80 && !skipClassFields(hdl))
return false; return false;
if (subtype & 0x40 && !skipLclFields(hdl, line ? _linesFlags if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
: _polygonsFlags, segment.type())) ? _linesFlags : _polygonsFlags, segmentType))
return false; return false;
if (!rect.intersects(br))
continue;
if (lbl && (labelPtr & 0x3FFFFF)) if (lbl && (labelPtr & 0x3FFFFF))
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF); poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
@ -287,18 +290,22 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
return true; return true;
} }
bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl, SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const QList<IMG::Point> *points) const
{ {
quint8 type, subtype; quint8 type, subtype;
qint16 lon, lat; qint16 lon, lat;
quint32 labelPtr; quint32 labelPtr;
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
? subdiv->idxPoints() : subdiv->points();
if (!seek(hdl, segment.start())) if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false; return false;
while (hdl.pos < (int)segment.end()) { while (hdl.pos() < (int)segment.end()) {
IMG::Point point; IMG::Point point;
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr) if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
@ -312,20 +319,18 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
point.type = (quint16)type<<8 | subtype; point.type = (quint16)type<<8 | subtype;
qint16 lonOffset = lon<<(24-subdiv->bits()); qint32 lonOffset = lon<<(24-subdiv->bits());
qint16 latOffset = lat<<(24-subdiv->bits()); qint32 latOffset = lat<<(24-subdiv->bits());
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset), point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
toWGS24(subdiv->lat() + latOffset)); toWGS24(subdiv->lat() + latOffset));
if (!rect.contains(point.coordinates)) uint hash = qHash(QPair<uint,uint>(qHash(QPair<qint32, qint32>
continue; (subdiv->lon() + lonOffset, subdiv->lat() + latOffset)),
labelPtr & 0x3FFFFF));
point.id = ((quint64)point.type)<<32 | hash;
point.poi = labelPtr & 0x400000; point.poi = labelPtr & 0x400000;
if (lbl && (labelPtr & 0x3FFFFF)) { if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi); point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
point.id = ((quint64)point.type)<<40 | ((quint64)lbl->offset())<<24
| (labelPtr & 0x3FFFFF);
}
points->append(point); points->append(point);
} }
@ -333,18 +338,21 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
return true; return true;
} }
bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl, bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Point> *points) const Handle &lblHdl, QList<IMG::Point> *points) const
{ {
quint8 type, subtype; quint8 type, subtype;
qint16 lon, lat; qint16 lon, lat;
quint32 labelPtr; quint32 labelPtr;
const SubDiv::Segment &segment = subdiv->extPoints();
if (!seek(hdl, segment.start()))
if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false; return false;
while (hdl.pos < (int)segment.end()) { while (hdl.pos() < (int)segment.end()) {
IMG::Point point; IMG::Point point;
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype) if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
@ -353,8 +361,8 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F); point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
qint16 lonOffset = lon<<(24-subdiv->bits()); qint32 lonOffset = lon<<(24-subdiv->bits());
qint16 latOffset = lat<<(24-subdiv->bits()); qint32 latOffset = lat<<(24-subdiv->bits());
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset), point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
toWGS24(subdiv->lat() + latOffset)); toWGS24(subdiv->lat() + latOffset));
labelPtr = 0; labelPtr = 0;
@ -363,18 +371,21 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
return false; return false;
if (subtype & 0x80 && !skipClassFields(hdl)) if (subtype & 0x80 && !skipClassFields(hdl))
return false; return false;
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, segment.type())) if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
return false; return false;
if (!rect.contains(point.coordinates)) // Discard NT points breaking style draw order logic (and causing huge
// performance drawback)
if (point.type == 0x11400)
continue; continue;
uint hash = qHash(QPair<uint,uint>(qHash(QPair<qint32, qint32>
(subdiv->lon() + lonOffset, subdiv->lat() + latOffset)),
labelPtr & 0x3FFFFF));
point.id = ((quint64)point.type)<<32 | hash;
point.poi = labelPtr & 0x400000; point.poi = labelPtr & 0x400000;
if (lbl && (labelPtr & 0x3FFFFF)) { if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi); point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
point.id = ((quint64)point.type)<<40
| ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
}
points->append(point); points->append(point);
} }
@ -382,85 +393,13 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
return true; return true;
} }
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons, SubDiv *subdiv) const
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
{ {
Handle rgnHdl, lblHdl, netHdl; QMap<SegmentType, SubDiv::Segment> ret;
if (!_init && !init(rgnHdl))
return;
QVector<Segment> seg(segments(rgnHdl, subdiv));
for (int i = 0; i < seg.size(); i++) {
const Segment &segment = seg.at(i);
if (segment.start() == segment.end())
continue;
switch (segment.type()) {
case Segment::Point:
case Segment::IndexedPoint:
if (points)
pointObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl,
points);
break;
case Segment::Line:
if (lines)
polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net,
netHdl, lines);
break;
case Segment::Polygon:
if (polygons)
polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net,
netHdl, polygons);
break;
case Segment::RoadReference:
break;
}
}
}
void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift,
LBLFile *lbl, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *points)
{
Handle rgnHdl, lblHdl;
if (!_init && !init(rgnHdl))
return;
if (polygons && subdiv->polygonsOffset() != subdiv->polygonsEnd()) {
quint32 start = _polygonsOffset + subdiv->polygonsOffset();
quint32 end = subdiv->polygonsEnd()
? _polygonsOffset + subdiv->polygonsEnd()
: _polygonsOffset + _polygonsSize;
extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end,
Segment::Polygon), lbl, lblHdl, polygons, false);
}
if (lines && subdiv->linesOffset() != subdiv->linesEnd()) {
quint32 start = _linesOffset + subdiv->linesOffset();
quint32 end = subdiv->linesEnd()
? _linesOffset + subdiv->linesEnd()
: _linesOffset + _linesSize;
extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end,
Segment::Line), lbl, lblHdl, lines, true);
}
if (points && subdiv->pointsOffset() != subdiv->pointsEnd()) {
quint32 start = _pointsOffset + subdiv->pointsOffset();
quint32 end = subdiv->pointsEnd()
? _pointsOffset + subdiv->pointsEnd()
: _pointsOffset + _pointsSize;
extPointObjects(rect, rgnHdl, subdiv, Segment(start, end,
Segment::Point), lbl, lblHdl, points);
}
}
QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
const
{
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F)) if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F))
return QVector<Segment>(); return ret;
quint32 offset = _offset + subdiv->offset(); quint32 offset = _offset + subdiv->offset();
@ -470,57 +409,63 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
no++; no++;
if (!seek(hdl, offset)) if (!seek(hdl, offset))
return QVector<Segment>(); return ret;
QVector<Segment> ret;
quint32 start = offset + 2 * (no - 1); quint32 start = offset + 2 * (no - 1);
quint16 po; quint32 ls = 0;
int cnt = 0; SegmentType lt = (SegmentType)0;
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) { for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
if (subdiv->objects() & mask) { if (subdiv->objects() & mask) {
if (cnt) { if (ls) {
if (!readUInt16(hdl, po)) quint16 po;
return QVector<Segment>(); if (!readUInt16(hdl, po) || !po)
return QMap<RGNFile::SegmentType, SubDiv::Segment>();
start = offset + po; start = offset + po;
ret.insert(lt, SubDiv::Segment(ls, start));
} }
if (!ret.isEmpty())
ret.last().setEnd(start); lt = (SegmentType)mask;
ret.append(Segment(start, (Segment::Type)mask)); ls = start;
cnt++;
} }
} }
ret.last().setEnd(subdiv->end() ? _offset + subdiv->end() : _offset + _size); ret.insert(lt, SubDiv::Segment(ls, subdiv->end()
? _offset + subdiv->end() : _offset + _size));
return ret; return ret;
} }
#ifndef QT_NO_DEBUG bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment)
{ {
QString type; QMap<RGNFile::SegmentType, SubDiv::Segment> seg(segments(hdl, subdiv));
switch (segment.type()) { SubDiv::Segment extPoints, extLines, extPolygons;
case RGNFile::Segment::Point:
type = "Point"; if (subdiv->extPointsOffset() != subdiv->extPointsEnd()) {
break; quint32 start = _pointsOffset + subdiv->extPointsOffset();
case RGNFile::Segment::IndexedPoint: quint32 end = subdiv->extPointsEnd()
type = "IndexedPoint"; ? _pointsOffset + subdiv->extPointsEnd()
break; : _pointsOffset + _pointsSize;
case RGNFile::Segment::Line: extPoints = SubDiv::Segment(start, end);
type = "Line"; }
break; if (subdiv->extPolygonsOffset() != subdiv->extPolygonsEnd()) {
case RGNFile::Segment::Polygon: quint32 start = _polygonsOffset + subdiv->extPolygonsOffset();
type = "Polygon"; quint32 end = subdiv->extPolygonsEnd()
break; ? _polygonsOffset + subdiv->extPolygonsEnd()
case RGNFile::Segment::RoadReference: : _polygonsOffset + _polygonsSize;
type = "RoadReference"; extPolygons = SubDiv::Segment(start, end);
break; }
if (subdiv->extLinesOffset() != subdiv->extLinesEnd()) {
quint32 start = _linesOffset + subdiv->extLinesOffset();
quint32 end = subdiv->extLinesEnd()
? _linesOffset + subdiv->extLinesEnd()
: _linesOffset + _linesSize;
extLines = SubDiv::Segment(start, end);
} }
dbg.nospace() << "Segment(" << segment.start() << ", " << segment.end() subdiv->init(seg.value(Point), seg.value(IndexedPoint), seg.value(Line),
- segment.start() << ", " << type << ")"; seg.value(Polygon), seg.value(RoadReference), extPoints, extLines,
extPolygons);
return dbg.space(); return true;
} }
#endif // QT_NO_DEBUG

View File

@ -12,26 +12,7 @@ class NETFile;
class RGNFile : public SubFile class RGNFile : public SubFile
{ {
public: public:
RGNFile(IMG *img) enum SegmentType {
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0), _init(false) {clearFlags();}
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
{clearFlags();}
void objects(const RectC &rect, const SubDiv *subdiv,
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points);
void extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift,
LBLFile *lbl, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *points);
private:
class Segment {
public:
enum Type {
Point = 0x1, Point = 0x1,
IndexedPoint = 0x2, IndexedPoint = 0x2,
Line = 0x4, Line = 0x4,
@ -39,47 +20,42 @@ private:
RoadReference = 0x10 RoadReference = 0x10
}; };
Segment() : _start(0), _end(0), _type(Point) {} RGNFile(IMG *img)
Segment(quint32 start, Type type) : SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
: _start(start), _end(0), _type(type) {} _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
Segment(quint32 start, quint32 end, Type type) _pointsSize(0), _init(false) {clearFlags();}
: _start(start), _end(end), _type(type) {} RGNFile(const QString &path)
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
void setEnd(quint32 end) {_end = end;} _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0), _init(false) {clearFlags();}
quint32 start() const {return _start;} RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
quint32 end() const {return _end;} _size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
Type type() const {return _type;} _linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
{clearFlags();}
private:
quint32 _start;
quint32 _end;
Type _type;
};
bool initialized() const {return _init;}
bool init(Handle &hdl); bool init(Handle &hdl);
QVector<Segment> segments(Handle &hdl, const SubDiv *subdiv) const; bool polyObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl,
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, QList<IMG::Poly> *polys) const;
Handle &netHdl, QList<IMG::Poly> *polys) const; bool pointObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const;
const Segment &segment, LBLFile *lbl, Handle &lblHdl, bool extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
QList<IMG::Point> *points) const; SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, QList<IMG::Poly> *polys) const;
quint32 shift, const Segment &segment, LBLFile *lbl, Handle &lblHdl, bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
QList<IMG::Poly> *polys, bool line) const; Handle &lblHdl, QList<IMG::Point> *points) const;
bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const;
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;
private:
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
const;
void clearFlags(); void clearFlags();
bool skipClassFields(Handle &hdl) const; bool skipClassFields(Handle &hdl) const;
bool skipLclFields(Handle &hdl, const quint32 flags[3], bool skipLclFields(Handle &hdl, const quint32 flags[3], SegmentType type)
Segment::Type type) const; const;
friend QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
quint32 _offset; quint32 _offset;
quint32 _size; quint32 _size;
@ -99,8 +75,4 @@ private:
bool _init; bool _init;
}; };
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
#endif // QT_NO_DEBUG
#endif // RGNFILE_H #endif // RGNFILE_H

View File

@ -341,7 +341,7 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl)
len = len >> 2; len = len >> 2;
} }
if (!file->seek(hdl, hdl.pos + len)) if (!file->seek(hdl, hdl.pos() + len))
return false; return false;
return true; return true;
@ -890,7 +890,7 @@ bool Style::parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
bool Style::parseTYPFile(SubFile *file) bool Style::parseTYPFile(SubFile *file)
{ {
SubFile::Handle hdl; SubFile::Handle hdl(file);
Section points, lines, polygons, order; Section points, lines, polygons, order;
quint16 tmp16, codepage; quint16 tmp16, codepage;
@ -939,9 +939,6 @@ Style::Style(SubFile *typ)
if (typ) if (typ)
parseTYPFile(typ); parseTYPFile(typ);
// Override stuff breaking the style display logic
_points[0x11400] = Point(None);
} }
const Style::Line &Style::line(quint32 type) const const Style::Line &Style::line(quint32 type) const

View File

@ -7,55 +7,147 @@
class SubDiv { class SubDiv {
public: public:
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects) class Segment {
: _offset(offset), _end(0), _lon(lon), _lat(lat), _bits(bits), public:
_objects(objects), _polygonsOffset(0), _polygonsEnd(0), _linesOffset(0), Segment() : _offset(0), _end(0) {}
_linesEnd(0), _pointsOffset(0), _pointsEnd(0) {} Segment(quint32 ofset, quint32 end) : _offset(ofset), _end(end) {}
void setEnd(quint32 end) {_end = end;}
bool isValid() const {return (_end > _offset);}
quint32 offset() const {return _offset;} quint32 offset() const {return _offset;}
quint32 end() const {return _end;} quint32 end() const {return _end;}
private:
quint32 _offset, _end;
};
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
: _lon(lon), _lat(lat), _bits(bits), _init(false)
{
_tre.objects = objects;
_tre.offset = offset;
_tre.end = 0;
_tre.extPolygonsOffset = 0;
_tre.extPolygonsEnd = 0;
_tre.extLinesOffset = 0;
_tre.extLinesEnd = 0;
_tre.extPointsOffset = 0;
_tre.extPointsEnd = 0;
}
void setEnd(quint32 end) {_tre.end = end;}
void setExtOffsets(quint32 polygon, quint32 line, quint32 point)
{
_tre.extPolygonsOffset = polygon;
_tre.extLinesOffset = line;
_tre.extPointsOffset = point;
}
void setExtEnds(quint32 polygon, quint32 line, quint32 point)
{
_tre.extPolygonsEnd = polygon;
_tre.extLinesEnd = line;
_tre.extPointsEnd = point;
}
void init(const Segment &points, const Segment &idxPoints,
const Segment &lines, const Segment &polygons,
const Segment &roadReferences, const Segment &extPoints,
const Segment &extLines, const Segment &extPolygons)
{
_rgn.pointsOffset = points.offset();
_rgn.pointsEnd = points.end();
_rgn.idxPointsOffset = idxPoints.offset();
_rgn.idxPointsEnd = idxPoints.end();
_rgn.linesOffset = lines.offset();
_rgn.linesEnd = lines.end();
_rgn.polygonsOffset = polygons.offset();
_rgn.polygonsEnd = polygons.end();
_rgn.roadReferencesOffset = roadReferences.offset();
_rgn.roadReferencesEnd = roadReferences.end();
_rgn.extPointsOffset = extPoints.offset();
_rgn.extPointsEnd = extPoints.end();
_rgn.extLinesOffset = extLines.offset();
_rgn.extLinesEnd = extLines.end();
_rgn.extPolygonsOffset = extPolygons.offset();
_rgn.extPolygonsEnd = extPolygons.end();
_init = true;
}
bool initialized() const {return _init;}
qint32 lon() const {return _lon;} qint32 lon() const {return _lon;}
qint32 lat() const {return _lat;} qint32 lat() const {return _lat;}
quint8 bits() const {return _bits;} quint8 bits() const {return _bits;}
quint8 objects() const {return _objects;}
// Extended types objects (TRE7) // Valid only after initialization
void setExtOffsets(quint32 polygon, quint32 line, quint32 point) Segment points() const
{_polygonsOffset = polygon; _linesOffset = line; _pointsOffset = point;} {return Segment(_rgn.pointsOffset, _rgn.pointsEnd);}
void setExtEnds(quint32 polygon, quint32 line, quint32 point) Segment idxPoints() const
{_polygonsEnd = polygon; _linesEnd = line; _pointsEnd = point;} {return Segment(_rgn.idxPointsOffset, _rgn.idxPointsEnd);}
Segment lines() const
{return Segment(_rgn.linesOffset, _rgn.linesEnd);}
Segment polygons() const
{return Segment(_rgn.polygonsOffset, _rgn.polygonsEnd);}
Segment extPoints() const
{return Segment(_rgn.extPointsOffset, _rgn.extPointsEnd);}
Segment extLines() const
{return Segment(_rgn.extLinesOffset, _rgn.extLinesEnd);}
Segment extPolygons() const
{return Segment(_rgn.extPolygonsOffset, _rgn.extPolygonsEnd);}
quint32 polygonsOffset() const {return _polygonsOffset;} // Valid only until initialization
quint32 polygonsEnd() const {return _polygonsEnd;} quint8 objects() const {return _tre.objects;}
quint32 linesOffset() const {return _linesOffset;} quint32 offset() const {return _tre.offset;}
quint32 linesEnd() const {return _linesEnd;} quint32 end() const {return _tre.end;}
quint32 pointsOffset() const {return _pointsOffset;} quint32 extPolygonsOffset() const {return _tre.extPolygonsOffset;}
quint32 pointsEnd() const {return _pointsEnd;} quint32 extPolygonsEnd() const {return _tre.extPolygonsEnd;}
quint32 extLinesOffset() const {return _tre.extLinesOffset;}
quint32 extLinesEnd() const {return _tre.extLinesEnd;}
quint32 extPointsOffset() const {return _tre.extPointsOffset;}
quint32 extPointsEnd() const {return _tre.extPointsEnd;}
private: private:
quint32 _offset; struct TRE
quint32 _end; {
quint8 objects;
quint32 offset;
quint32 end;
quint32 extPolygonsOffset;
quint32 extPolygonsEnd;
quint32 extLinesOffset;
quint32 extLinesEnd;
quint32 extPointsOffset;
quint32 extPointsEnd;
};
struct RGN
{
quint32 pointsOffset;
quint32 pointsEnd;
quint32 idxPointsOffset;
quint32 idxPointsEnd;
quint32 linesOffset;
quint32 linesEnd;
quint32 polygonsOffset;
quint32 polygonsEnd;
quint32 roadReferencesOffset;
quint32 roadReferencesEnd;
quint32 extPointsOffset;
quint32 extPointsEnd;
quint32 extLinesOffset;
quint32 extLinesEnd;
quint32 extPolygonsOffset;
quint32 extPolygonsEnd;
};
qint32 _lon, _lat; qint32 _lon, _lat;
quint8 _bits; quint8 _bits;
quint8 _objects; bool _init;
union {
quint32 _polygonsOffset; TRE _tre;
quint32 _polygonsEnd; RGN _rgn;
quint32 _linesOffset; };
quint32 _linesEnd;
quint32 _pointsOffset;
quint32 _pointsEnd;
}; };
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv)
{
Coordinates c(toWGS24(subdiv.lon()), toWGS24(subdiv.lat()));
dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset()
<< ", " << subdiv.end() << ", " << subdiv.objects() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG
#endif // SUBDIV_H #endif // SUBDIV_H

View File

@ -5,39 +5,40 @@
bool SubFile::seek(Handle &handle, quint32 pos) const bool SubFile::seek(Handle &handle, quint32 pos) const
{ {
if (_file) if (handle._file) {
return _file->seek(pos); int blockNum = pos / BLOCK_SIZE;
else {
if (handle._blockNum != blockNum) {
if (!handle._file->seek((qint64)blockNum * BLOCK_SIZE))
return false;
if (handle._file->read(handle._data.data(), BLOCK_SIZE) < 0)
return false;
handle._blockNum = blockNum;
}
handle._blockPos = pos % BLOCK_SIZE;
handle._pos = pos;
return true;
} else {
quint32 blockSize = _img->blockSize(); quint32 blockSize = _img->blockSize();
int blockNum = pos / blockSize; int blockNum = pos / blockSize;
if (handle.blockNum != blockNum) { if (handle._blockNum != blockNum) {
if (blockNum >= _blocks->size()) if (blockNum >= _blocks->size())
return false; return false;
if (!_img->readBlock(_blocks->at(blockNum), handle.data)) if (!_img->readBlock(_blocks->at(blockNum), handle._data.data()))
return false; return false;
handle.blockNum = blockNum; handle._blockNum = blockNum;
} }
handle.blockPos = pos % blockSize; handle._blockPos = pos % blockSize;
handle.pos = pos; handle._pos = pos;
return true; return true;
} }
} }
bool SubFile::readByte(Handle &handle, quint8 &val) const
{
if (_file)
return _file->getChar((char*)&val);
else {
val = handle.data.at(handle.blockPos++);
handle.pos++;
return (handle.blockPos >= _img->blockSize())
? seek(handle, handle.pos) : true;
}
}
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
{ {
quint8 bytes, shift, b; quint8 bytes, shift, b;
@ -69,20 +70,6 @@ bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
return true; return true;
} }
bool SubFile::readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const
{
quint8 b;
val = 0;
for (quint32 i = bytes; i; i--) {
if (!readByte(hdl, b))
return false;
val |= ((quint32)b) << ((i-1) * 8);
}
return true;
}
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
{ {
quint8 bits; quint8 bits;
@ -91,7 +78,7 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
return false; return false;
if (!(bits & 1)) { if (!(bits & 1)) {
seek(hdl, hdl.pos - 1); seek(hdl, hdl._pos - 1);
if (!((bits>>1) & 1)) { if (!((bits>>1) & 1)) {
if (!((bits>>2) & 1)) { if (!((bits>>2) & 1)) {
if (!readUInt32(hdl, bitfield)) if (!readUInt32(hdl, bitfield))
@ -111,8 +98,3 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
return true; return true;
} }
QString SubFile::fileName() const
{
return _file ? _file->fileName() : _img->fileName();
}

View File

@ -3,35 +3,56 @@
#include <QVector> #include <QVector>
#include <QDebug> #include <QDebug>
#include <QFile>
#include "img.h"
class QFile;
class IMG; #define BLOCK_SIZE 4096
class SubFile class SubFile
{ {
public: public:
enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP}; enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP};
struct Handle class Handle
{ {
Handle() : blockNum(-1), blockPos(-1), pos(-1) {} public:
Handle(const SubFile *subFile)
: _file(0), _blockNum(-1), _blockPos(-1), _pos(-1)
{
if (subFile && subFile->_path) {
_file = new QFile(*(subFile->_path));
_file->open(QIODevice::ReadOnly);
_data.resize(BLOCK_SIZE);
} else if (subFile)
_data.resize(subFile->_img->blockSize());
}
~Handle() {delete _file;}
QByteArray data; int pos() const {return _pos;}
int blockNum;
int blockPos; private:
int pos; friend class SubFile;
QFile *_file;
QByteArray _data;
int _blockNum;
int _blockPos;
int _pos;
}; };
SubFile(IMG *img) SubFile(IMG *img)
: _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _file(0) {} : _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _path(0) {}
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img), SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
_blocks(gmp->_blocks), _file(gmp->_file) {} _blocks(gmp->_blocks), _path(gmp->_path) {}
SubFile(QFile *file) SubFile(const QString &path)
: _gmpOffset(0), _img(0), _blocks(0), _file(file) {} : _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)) {}
~SubFile() ~SubFile()
{ {
if (!_gmpOffset) if (!_gmpOffset) {
delete _blocks; delete _blocks;
delete _path;
}
} }
void addBlock(quint16 block) {_blocks->append(block);} void addBlock(quint16 block) {_blocks->append(block);}
@ -97,22 +118,41 @@ public:
return true; return true;
} }
bool readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const
{
quint8 b;
val = 0;
for (quint32 i = bytes; i; i--) {
if (!readByte(hdl, b))
return false;
val |= ((quint32)b) << ((i-1) * 8);
}
return true;
}
bool readVUInt32(Handle &hdl, quint32 &val) const; bool readVUInt32(Handle &hdl, quint32 &val) const;
bool readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const;
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const; bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
quint16 offset() const {return _blocks->first();} QString fileName() const {return _path ? *_path : _img->fileName();}
QString fileName() const;
protected: protected:
quint32 _gmpOffset; quint32 _gmpOffset;
private: private:
bool readByte(Handle &handle, quint8 &val) const; bool readByte(Handle &handle, quint8 &val) const
{
int blockSize = _img ? _img->blockSize() : BLOCK_SIZE;
val = handle._data.at(handle._blockPos++);
handle._pos++;
return (handle._blockPos >= blockSize)
? seek(handle, handle._pos) : true;
}
IMG *_img; IMG *_img;
QVector<quint16> *_blocks; QVector<quint16> *_blocks;
QFile *_file; QString *_path;
}; };
#endif // SUBFILE_H #endif // SUBFILE_H

View File

@ -37,9 +37,9 @@ TREFile::~TREFile()
clear(); clear();
} }
bool TREFile::init() bool TREFile::init(bool baseMap)
{ {
Handle hdl; Handle hdl(this);
quint8 locked; quint8 locked;
quint16 hdrLen; quint16 hdrLen;
@ -108,12 +108,14 @@ bool TREFile::init()
} }
} }
_isBaseMap = baseMap;
return (_firstLevel >= 0); return (_firstLevel >= 0);
} }
bool TREFile::load(int idx) bool TREFile::load(int idx)
{ {
Handle hdl; Handle hdl(this);
QList<SubDiv*> sl; QList<SubDiv*> sl;
SubDiv *s = 0; SubDiv *s = 0;
SubDivTree *tree = new SubDivTree(); SubDivTree *tree = new SubDivTree();
@ -199,7 +201,7 @@ bool TREFile::load(int idx)
if (i) if (i)
sl.at(i-1)->setExtEnds(polygons, lines, points); sl.at(i-1)->setExtEnds(polygons, lines, points);
if (!seek(hdl, hdl.pos + _extended.itemSize - 12)) if (!seek(hdl, hdl.pos() + _extended.itemSize - 12))
goto error; goto error;
} }
@ -236,10 +238,17 @@ void TREFile::clear()
_subdivs.clear(); _subdivs.clear();
} }
int TREFile::level(int bits) int TREFile::level(int bits, bool baseMap)
{ {
int idx = _firstLevel; int idx = _firstLevel;
if (baseMap) {
if (!_isBaseMap && _levels.at(idx).bits > bits)
return -1;
if (_isBaseMap && bits > _levels.last().bits)
return -1;
}
for (int i = idx + 1; i < _levels.size(); i++) { for (int i = idx + 1; i < _levels.size(); i++) {
if (_levels.at(i).bits > bits) if (_levels.at(i).bits > bits)
break; break;
@ -259,10 +268,10 @@ static bool cb(SubDiv *subdiv, void *context)
return true; return true;
} }
QList<SubDiv*> TREFile::subdivs(const RectC &rect, int bits) QList<SubDiv*> TREFile::subdivs(const RectC &rect, int bits, bool baseMap)
{ {
QList<SubDiv*> list; QList<SubDiv*> list;
SubDivTree *tree = _subdivs.value(level(bits)); SubDivTree *tree = _subdivs.value(level(bits, baseMap));
double min[2], max[2]; double min[2], max[2];
min[0] = rect.left(); min[0] = rect.left();

View File

@ -14,14 +14,15 @@ class TREFile : public SubFile
{ {
public: public:
TREFile(IMG *img) : SubFile(img) {} TREFile(IMG *img) : SubFile(img) {}
TREFile(const QString &path) : SubFile(path) {}
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {} TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
~TREFile(); ~TREFile();
bool init(); bool init(bool baseMap);
void clear(); void clear();
const RectC &bounds() const {return _bounds;} const RectC &bounds() const {return _bounds;}
QList<SubDiv*> subdivs(const RectC &rect, int bits); QList<SubDiv*> subdivs(const RectC &rect, int bits, bool baseMap);
quint32 shift(quint8 bits) const quint32 shift(quint8 bits) const
{return (bits == _levels.last().bits) ? (_flags >> 0xb) & 7 : 0;} {return (bits == _levels.last().bits) ? (_flags >> 0xb) & 7 : 0;}
@ -41,7 +42,7 @@ private:
typedef RTree<SubDiv*, double, 2> SubDivTree; typedef RTree<SubDiv*, double, 2> SubDivTree;
bool load(int idx); bool load(int idx);
int level(int bits); int level(int bits, bool baseMap);
bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits, bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits,
QMap<quint32, int> &map); QMap<quint32, int> &map);
bool parsePoints(Handle hdl, quint32 pos, const QMap<int, int> &level2bits); bool parsePoints(Handle hdl, quint32 pos, const QMap<int, int> &level2bits);
@ -54,6 +55,7 @@ private:
Extended _extended; Extended _extended;
int _firstLevel; int _firstLevel;
quint32 _flags; quint32 _flags;
bool _isBaseMap;
QMap<int, SubDivTree*> _subdivs; QMap<int, SubDivTree*> _subdivs;
}; };

View File

@ -1,5 +1,23 @@
#include "vectortile.h" #include "vectortile.h"
static void copyPolys(const RectC &rect, QList<IMG::Poly> *src,
QList<IMG::Poly> *dst)
{
for (int i = 0; i < src->size(); i++)
if (rect.intersects(src->at(i).boundingRect))
dst->append(src->at(i));
}
static void copyPoints(const RectC &rect, QList<IMG::Point> *src,
QList<IMG::Point> *dst)
{
for (int j = 0; j < src->size(); j++)
if (rect.contains(src->at(j).coordinates))
dst->append(src->at(j));
}
SubFile *VectorTile::file(SubFile::Type type) SubFile *VectorTile::file(SubFile::Type type)
{ {
switch (type) { switch (type) {
@ -41,12 +59,35 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
} }
} }
bool VectorTile::init() SubFile *VectorTile::addFile(const QString &path, SubFile::Type type)
{
switch (type) {
case SubFile::TRE:
_tre = new TREFile(path);
return _tre;
case SubFile::RGN:
_rgn = new RGNFile(path);
return _rgn;
case SubFile::LBL:
_lbl = new LBLFile(path);
return _lbl;
case SubFile::NET:
_net = new NETFile(path);
return _net;
case SubFile::GMP:
_gmp = new SubFile(path);
return _gmp;
default:
return 0;
}
}
bool VectorTile::init(bool baseMap)
{ {
if (_gmp && !initGMP()) if (_gmp && !initGMP())
return false; return false;
if (!(_tre && _tre->init() && _rgn)) if (!(_tre && _tre->init(baseMap) && _rgn))
return false; return false;
return true; return true;
@ -54,7 +95,7 @@ bool VectorTile::init()
bool VectorTile::initGMP() bool VectorTile::initGMP()
{ {
SubFile::Handle hdl; SubFile::Handle hdl(_gmp);
quint32 tre, rgn, lbl, net; quint32 tre, rgn, lbl, net;
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre) if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
@ -62,25 +103,84 @@ bool VectorTile::initGMP()
&& _gmp->readUInt32(hdl, net))) && _gmp->readUInt32(hdl, net)))
return false; return false;
_tre = new TREFile(_gmp, tre); _tre = tre ? new TREFile(_gmp, tre) : 0;
_rgn = new RGNFile(_gmp, rgn); _rgn = rgn ? new RGNFile(_gmp, rgn) : 0;
_lbl = new LBLFile(_gmp, lbl); _lbl = lbl ? new LBLFile(_gmp, lbl) : 0;
_net = new NETFile(_gmp, net); _net = net ? new NETFile(_gmp, net) : 0;
return true; return true;
} }
void VectorTile::objects(const RectC &rect, int bits, void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *points) const QCache<const SubDiv *, IMG::Polys> *polyCache) const
{ {
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits); SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net);
for (int i = 0; i < subdivs.size(); i++) {
const SubDiv *subdiv = subdivs.at(i);
quint32 shift = _tre->shift(subdiv->bits());
_rgn->objects(rect, subdiv, _lbl, _net, polygons, lines, points); if (!_rgn->initialized() && !_rgn->init(rgnHdl))
_rgn->extObjects(rect, subdiv, shift, _lbl, polygons, lines, points); return;
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits, baseMap);
for (int i = 0; i < subdivs.size(); i++) {
SubDiv *subdiv = subdivs.at(i);
IMG::Polys *polys = polyCache->object(subdiv);
if (!polys) {
quint32 shift = _tre->shift(subdiv->bits());
QList<IMG::Poly> p, l;
if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv))
continue;
_rgn->polyObjects(rgnHdl, subdiv, RGNFile::Polygon, _lbl, lblHdl,
_net, netHdl, &p);
_rgn->polyObjects(rgnHdl, subdiv, RGNFile::Line, _lbl, lblHdl,
_net, netHdl, &l);
_rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Polygon, _lbl,
lblHdl, &p);
_rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Line, _lbl,
lblHdl, &l);
copyPolys(rect, &p, polygons);
copyPolys(rect, &l, lines);
polyCache->insert(subdiv, new IMG::Polys(p, l));
} else {
copyPolys(rect, &(polys->polygons), polygons);
copyPolys(rect, &(polys->lines), lines);
}
}
}
void VectorTile::points(const RectC &rect, int bits, bool baseMap,
QList<IMG::Point> *points, QCache<const SubDiv *,
QList<IMG::Point> > *pointCache) const
{
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl);
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
return;
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits, baseMap);
for (int i = 0; i < subdivs.size(); i++) {
SubDiv *subdiv = subdivs.at(i);
QList<IMG::Point> *pl = pointCache->object(subdiv);
if (!pl) {
QList<IMG::Point> p;
if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv))
continue;
_rgn->pointObjects(rgnHdl, subdiv, RGNFile::Point, _lbl, lblHdl,
&p);
_rgn->pointObjects(rgnHdl, subdiv, RGNFile::IndexedPoint, _lbl,
lblHdl, &p);
_rgn->extPointObjects(rgnHdl, subdiv, _lbl, lblHdl, &p);
copyPoints(rect, &p, points);
pointCache->insert(subdiv, new QList<IMG::Point>(p));
} else
copyPoints(rect, pl, points);
} }
} }

View File

@ -1,7 +1,6 @@
#ifndef VECTORTILE_H #ifndef VECTORTILE_H
#define VECTORTILE_H #define VECTORTILE_H
#include "img.h"
#include "trefile.h" #include "trefile.h"
#include "trefile.h" #include "trefile.h"
#include "rgnfile.h" #include "rgnfile.h"
@ -16,16 +15,21 @@ public:
delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp; delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;
} }
bool init(); bool init(bool baseMap);
void clear() {_tre->clear();} void clear() {_tre->clear();}
const RectC &bounds() const {return _tre->bounds();} const RectC &bounds() const {return _tre->bounds();}
SubFile *file(SubFile::Type type); SubFile *file(SubFile::Type type);
SubFile *addFile(IMG *img, SubFile::Type type); SubFile *addFile(IMG *img, SubFile::Type type);
SubFile *addFile(const QString &path, SubFile::Type type);
void objects(const RectC &rect, int bits, QList<IMG::Poly> *polygons, void polys(const RectC &rect, int bits, bool baseMap,
QList<IMG::Poly> *lines, QList<IMG::Point> *points) const; QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QCache<const SubDiv *, IMG::Polys> *polyCache) const;
void points(const RectC &rect, int bits, bool baseMap,
QList<IMG::Point> *points, QCache<const SubDiv*,
QList<IMG::Point> > *pointCache) const;
static bool isTileFile(SubFile::Type type) static bool isTileFile(SubFile::Type type)
{ {
@ -34,8 +38,6 @@ public:
|| type == SubFile::GMP); || type == SubFile::GMP);
} }
friend QDebug operator<<(QDebug dbg, const VectorTile &tile);
private: private:
bool initGMP(); bool initGMP();

View File

@ -13,6 +13,9 @@
#include "IMG/textpathitem.h" #include "IMG/textpathitem.h"
#include "IMG/textpointitem.h" #include "IMG/textpointitem.h"
#include "IMG/bitmapline.h" #include "IMG/bitmapline.h"
#include "IMG/style.h"
#include "IMG/img.h"
#include "IMG/gmap.h"
#include "pcs.h" #include "pcs.h"
#include "rectd.h" #include "rectd.h"
#include "imgmap.h" #include "imgmap.h"
@ -35,9 +38,9 @@ public:
const QString &key() const {return _key;} const QString &key() const {return _key;}
const QPoint &xy() const {return _xy;} const QPoint &xy() const {return _xy;}
QImage &img() {return _img;} QImage &img() {return _img;}
QList<IMG::Poly> &polygons() {return _polygons;} QList<MapData::Poly> &polygons() {return _polygons;}
QList<IMG::Poly> &lines() {return _lines;} QList<MapData::Poly> &lines() {return _lines;}
QList<IMG::Point> &points() {return _points;} QList<MapData::Point> &points() {return _points;}
void render() void render()
{ {
@ -70,9 +73,9 @@ private:
QPoint _xy; QPoint _xy;
QString _key; QString _key;
QImage _img; QImage _img;
QList<IMG::Poly> _polygons; QList<MapData::Poly> _polygons;
QList<IMG::Poly> _lines; QList<MapData::Poly> _lines;
QList<IMG::Point> _points; QList<MapData::Point> _points;
}; };
@ -201,25 +204,20 @@ static qreal area(const QVector<QPointF> &polygon)
return area; return area;
} }
static QPointF centroid(const QVector<QPointF> polygon) static QPointF centroid(const QVector<QPointF> &polygon)
{ {
qreal cx = 0, cy = 0, factor = 0; qreal cx = 0, cy = 0;
qreal A = area(polygon); qreal factor = 1.0 / (6.0 * area(polygon));
for (int i = 0; i < polygon.size(); i++) { for (int i = 0; i < polygon.size(); i++) {
int j = (i + 1) % polygon.size(); int j = (i + 1) % polygon.size();
factor=(polygon.at(i).x() * polygon.at(j).y() - polygon[j].x() qreal f = (polygon.at(i).x() * polygon.at(j).y() - polygon.at(j).x()
* polygon[i].y()); * polygon.at(i).y());
cx+=(polygon[i].x() + polygon[j].x()) * factor; cx += (polygon.at(i).x() + polygon.at(j).x()) * f;
cy+=(polygon[i].y() + polygon[j].y()) * factor; cy += (polygon.at(i).y() + polygon.at(j).y()) * f;
} }
A *= 6.0f; return QPointF(cx * factor, cy * factor);
factor = 1/A;
cx *= factor;
cy *= factor;
return QPointF(cx, cy);
} }
static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect) static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
@ -231,11 +229,17 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill))); || polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
} }
IMGMap::IMGMap(const QString &fileName, QObject *parent) IMGMap::IMGMap(const QString &fileName, QObject *parent)
: Map(parent), _img(fileName), _projection(PCS::pcs(3857)), _valid(false) : Map(parent), _projection(PCS::pcs(3857)), _valid(false)
{ {
if (!_img.isValid()) { if (GMAP::isGMAP(fileName))
_errorString = _img.errorString(); _data = new GMAP(fileName);
else
_data = new IMG(fileName);
if (!_data->isValid()) {
_errorString = _data->errorString();
return; return;
} }
@ -247,17 +251,17 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
void IMGMap::load() void IMGMap::load()
{ {
_img.load(); _data->load();
} }
void IMGMap::unload() void IMGMap::unload()
{ {
_img.clear(); _data->clear();
} }
QRectF IMGMap::bounds() QRectF IMGMap::bounds()
{ {
RectD prect(_img.bounds(), _projection); RectD prect(_data->bounds(), _projection);
return QRectF(_transform.proj2img(prect.topLeft()), return QRectF(_transform.proj2img(prect.topLeft()),
_transform.proj2img(prect.bottomRight())); _transform.proj2img(prect.bottomRight()));
} }
@ -307,7 +311,7 @@ Transform IMGMap::transform(int zoom) const
{ {
double scale = _projection.isGeographic() double scale = _projection.isGeographic()
? 360.0 / (1<<zoom) : (2.0 * M_PI * WGS84_RADIUS) / (1<<zoom); ? 360.0 / (1<<zoom) : (2.0 * M_PI * WGS84_RADIUS) / (1<<zoom);
PointD topLeft(_projection.ll2xy(_img.bounds().topLeft())); PointD topLeft(_projection.ll2xy(_data->bounds().topLeft()));
return Transform(ReferencePoint(PointD(0, 0), topLeft), return Transform(ReferencePoint(PointD(0, 0), topLeft),
PointD(scale, scale)); PointD(scale, scale));
} }
@ -327,15 +331,14 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
return _projection.xy2ll(_transform.img2proj(p)); return _projection.xy2ll(_transform.img2proj(p));
} }
void IMGMap::drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons)
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
{ {
for (int n = 0; n < _img.style()->drawOrder().size(); n++) { for (int n = 0; n < _data->style()->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) { for (int i = 0; i < polygons.size(); i++) {
const IMG::Poly &poly = polygons.at(i); const MapData::Poly &poly = polygons.at(i);
if (poly.type != _img.style()->drawOrder().at(n)) if (poly.type != _data->style()->drawOrder().at(n))
continue; continue;
const Style::Polygon &style = _img.style()->polygon(poly.type); const Style::Polygon &style = _data->style()->polygon(poly.type);
painter->setPen(style.pen()); painter->setPen(style.pen());
painter->setBrush(style.brush()); painter->setBrush(style.brush());
@ -344,13 +347,13 @@ void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
} }
} }
void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines) void IMGMap::drawLines(QPainter *painter, const QList<MapData::Poly> &lines)
{ {
painter->setBrush(Qt::NoBrush); painter->setBrush(Qt::NoBrush);
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const MapData::Poly &poly = lines.at(i);
const Style::Line &style = _img.style()->line(poly.type); const Style::Line &style = _data->style()->line(poly.type);
if (style.background() == Qt::NoPen) if (style.background() == Qt::NoPen)
continue; continue;
@ -360,8 +363,8 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
} }
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const MapData::Poly &poly = lines.at(i);
const Style::Line &style = _img.style()->line(poly.type); const Style::Line &style = _data->style()->line(poly.type);
if (!style.img().isNull()) if (!style.img().isNull())
BitmapLine::draw(painter, poly.points, style.img()); BitmapLine::draw(painter, poly.points, style.img());
@ -378,12 +381,11 @@ void IMGMap::drawTextItems(QPainter *painter, const QList<TextItem*> &textItems)
textItems.at(i)->paint(painter); textItems.at(i)->paint(painter);
} }
void IMGMap::processPolygons(QList<MapData::Poly> &polygons,
void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
QList<TextItem*> &textItems) QList<TextItem*> &textItems)
{ {
for (int i = 0; i < polygons.size(); i++) { for (int i = 0; i < polygons.size(); i++) {
IMG::Poly &poly = polygons[i]; MapData::Poly &poly = polygons[i];
for (int j = 0; j < poly.points.size(); j++) { for (int j = 0; j < poly.points.size(); j++) {
QPointF &p = poly.points[j]; QPointF &p = poly.points[j];
p = ll2xy(Coordinates(p.x(), p.y())); p = ll2xy(Coordinates(p.x(), p.y()));
@ -395,7 +397,7 @@ void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
if (_zoom <= 23 && (Style::isWaterArea(poly.type) if (_zoom <= 23 && (Style::isWaterArea(poly.type)
|| Style::isMilitaryArea(poly.type) || Style::isMilitaryArea(poly.type)
|| Style::isNatureReserve(poly.type))) { || Style::isNatureReserve(poly.type))) {
const Style::Polygon &style = _img.style()->polygon(poly.type); const Style::Polygon &style = _data->style()->polygon(poly.type);
TextPointItem *item = new TextPointItem( TextPointItem *item = new TextPointItem(
centroid(poly.points).toPoint(), &poly.label.text(), centroid(poly.points).toPoint(), &poly.label.text(),
poiFont(), 0, &style.brush().color()); poiFont(), 0, &style.brush().color());
@ -408,13 +410,13 @@ void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
} }
} }
void IMGMap::processLines(QList<IMG::Poly> &lines, const QRect &tileRect, void IMGMap::processLines(QList<MapData::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems) QList<TextItem*> &textItems)
{ {
qStableSort(lines); qStableSort(lines);
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
IMG::Poly &poly = lines[i]; MapData::Poly &poly = lines[i];
for (int j = 0; j < poly.points.size(); j++) { for (int j = 0; j < poly.points.size(); j++) {
QPointF &p = poly.points[j]; QPointF &p = poly.points[j];
p = ll2xy(Coordinates(p.x(), p.y())); p = ll2xy(Coordinates(p.x(), p.y()));
@ -426,12 +428,12 @@ void IMGMap::processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
processShields(lines, tileRect, textItems); processShields(lines, tileRect, textItems);
} }
void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect, void IMGMap::processStreetNames(QList<MapData::Poly> &lines,
QList<TextItem*> &textItems) const QRect &tileRect, QList<TextItem*> &textItems)
{ {
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
IMG::Poly &poly = lines[i]; MapData::Poly &poly = lines[i];
const Style::Line &style = _img.style()->line(poly.type); const Style::Line &style = _data->style()->line(poly.type);
if (style.img().isNull() && style.foreground() == Qt::NoPen) if (style.img().isNull() && style.foreground() == Qt::NoPen)
continue; continue;
@ -455,7 +457,7 @@ void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
} }
} }
void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect, void IMGMap::processShields(QList<MapData::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems) QList<TextItem*> &textItems)
{ {
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) { for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
@ -466,7 +468,7 @@ void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
QHash<Label::Shield, const Label::Shield*> sp; QHash<Label::Shield, const Label::Shield*> sp;
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const MapData::Poly &poly = lines.at(i);
const Label::Shield &shield = poly.label.shield(); const Label::Shield &shield = poly.label.shield();
if (!shield.isValid() || shield.type() != type if (!shield.isValid() || shield.type() != type
|| !Style::isMajorRoad(poly.type)) || !Style::isMajorRoad(poly.type))
@ -519,14 +521,14 @@ void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
} }
} }
void IMGMap::processPoints(QList<IMG::Point> &points, void IMGMap::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems) QList<TextItem*> &textItems)
{ {
qSort(points); qSort(points);
for (int i = 0; i < points.size(); i++) { for (int i = 0; i < points.size(); i++) {
IMG::Point &point = points[i]; MapData::Point &point = points[i];
const Style::Point &style = _img.style()->point(point.type); const Style::Point &style = _data->style()->point(point.type);
if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type))) if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
continue; continue;
@ -580,7 +582,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
QPixmap pm; QPixmap pm;
QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE); QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE);
QString key = _img.fileName() + "-" + QString::number(_zoom) + "_" QString key = _data->fileName() + "-" + QString::number(_zoom) + "_"
+ QString::number(ttl.x()) + "_" + QString::number(ttl.y()); + QString::number(ttl.x()) + "_" + QString::number(ttl.y());
if (QPixmapCache::find(key, pm)) if (QPixmapCache::find(key, pm))
painter->drawPixmap(ttl, pm); painter->drawPixmap(ttl, pm);
@ -590,13 +592,14 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
RectD polyRect(_transform.img2proj(ttl), _transform.img2proj( RectD polyRect(_transform.img2proj(ttl), _transform.img2proj(
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE))); QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
_img.objects(polyRect.toRectC(_projection, 4), _zoom, _data->polys(polyRect.toRectC(_projection, 4), _zoom,
&(tile.polygons()), &(tile.lines()), 0); &(tile.polygons()), &(tile.lines()));
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT, RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x() ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT))); + TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
_img.objects(pointRect.toRectC(_projection, 4), _zoom, _data->points(pointRect.toRectC(_projection, 4), _zoom,
0, 0, &(tile.points())); &(tile.points()));
} }
} }
} }

View File

@ -4,7 +4,7 @@
#include "map.h" #include "map.h"
#include "projection.h" #include "projection.h"
#include "transform.h" #include "transform.h"
#include "IMG/img.h" #include "IMG/mapdata.h"
class TextItem; class TextItem;
@ -14,8 +14,9 @@ class IMGMap : public Map
public: public:
IMGMap(const QString &fileName, QObject *parent = 0); IMGMap(const QString &fileName, QObject *parent = 0);
~IMGMap() {delete _data;}
QString name() const {return _img.name();} QString name() const {return _data->name();}
QRectF bounds(); QRectF bounds();
@ -43,21 +44,21 @@ private:
Transform transform(int zoom) const; Transform transform(int zoom) const;
void updateTransform(); void updateTransform();
void drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons); void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
void drawLines(QPainter *painter, const QList<IMG::Poly> &lines); void drawLines(QPainter *painter, const QList<MapData::Poly> &lines);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems); void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void processPolygons(QList<IMG::Poly> &polygons, void processPolygons(QList<MapData::Poly> &polygons,
QList<TextItem *> &textItems); QList<TextItem *> &textItems);
void processLines(QList<IMG::Poly> &lines, const QRect &tileRect, void processLines(QList<MapData::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
void processPoints(QList<IMG::Point> &points, QList<TextItem*> &textItems); void processPoints(QList<MapData::Point> &points, QList<TextItem*> &textItems);
void processShields(QList<IMG::Poly> &lines, const QRect &tileRect, void processShields(QList<MapData::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
void processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect, void processStreetNames(QList<MapData::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
IMG _img; MapData *_data;
int _zoom; int _zoom;
Projection _projection; Projection _projection;
Transform _transform; Transform _transform;

View File

@ -8,51 +8,56 @@
#include "mbtilesmap.h" #include "mbtilesmap.h"
#include "rmap.h" #include "rmap.h"
#include "imgmap.h" #include "imgmap.h"
#include "IMG/gmap.h"
#include "maplist.h" #include "maplist.h"
bool MapList::loadMap(Map* map, const QString &path, bool dir) bool MapList::loadMap(Map *map, const QString &path)
{ {
if (map->isValid()) { if (map && map->isValid()) {
_maps.append(map); _maps.append(map);
return true; return true;
} else { } else if (map) {
if (dir) _errorPath = path;
_errorString += path + ": " + map->errorString() + "\n";
else
_errorString = map->errorString(); _errorString = map->errorString();
return false; return false;
} else {
_errorString = path;
_errorString = "Unknown file format";
return false;
} }
} }
Map *MapList::loadSource(const QString &path, bool dir) Map *MapList::loadSource(const QString &path)
{ {
QString err; Map *map = MapSource::loadMap(path, _errorString);
Map *map = MapSource::loadMap(path, err);
if (!map) { if (!map)
if (dir) _errorPath = path;
_errorString += path + ": " + err + "\n";
else else
_errorString = err;
} else
map->setParent(this); map->setParent(this);
return map; return map;
} }
bool MapList::loadFile(const QString &path, bool *atlas, bool dir) bool MapList::loadFile(const QString &path, bool *terminate)
{ {
QFileInfo fi(path); QFileInfo fi(path);
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
Map *map; Map *map = 0;
if (Atlas::isAtlas(path)) { if (Atlas::isAtlas(path)) {
*atlas = true; if (terminate)
*terminate = true;
map = new Atlas(path, this); map = new Atlas(path, this);
} else if (suffix == "xml") { } else if (suffix == "xml") {
if (!(map = loadSource(path, dir))) if (MapSource::isMap(path) && !(map = loadSource(path)))
return false; return false;
else if (GMAP::isGMAP(path)) {
if (terminate)
*terminate = true;
map = new IMGMap(path);
}
} else if (suffix == "jnx") } else if (suffix == "jnx")
map = new JNXMap(path, this); map = new JNXMap(path, this);
else if (suffix == "tif" || suffix == "tiff") else if (suffix == "tif" || suffix == "tiff")
@ -63,10 +68,10 @@ bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
map = new RMap(path, this); map = new RMap(path, this);
else if (suffix == "img") else if (suffix == "img")
map = new IMGMap(path, this); map = new IMGMap(path, this);
else else if (suffix == "map" || suffix == "tar")
map = new OziMap(path, this); map = new OziMap(path, this);
if (!loadMap(map, path, dir)) { if (!loadMap(map, path)) {
delete map; delete map;
return false; return false;
} }
@ -74,7 +79,7 @@ bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
return true; return true;
} }
bool MapList::loadDirR(const QString &path) bool MapList::loadDir(const QString &path)
{ {
QDir md(path); QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
@ -85,15 +90,15 @@ bool MapList::loadDirR(const QString &path)
for (int i = 0; i < ml.size(); i++) { for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i); const QFileInfo &fi = ml.at(i);
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
bool atlas = false; bool terminate = false;
if (fi.isDir() && fi.fileName() != "set") { if (fi.isDir() && fi.fileName() != "set") {
if (!loadDirR(fi.absoluteFilePath())) if (!loadDir(fi.absoluteFilePath()))
ret = false; ret = false;
} else if (filter().contains("*." + suffix)) { } else if (filter().contains("*." + suffix)) {
if (!loadFile(fi.absoluteFilePath(), &atlas, true)) if (!loadFile(fi.absoluteFilePath(), &terminate))
ret = false; ret = false;
if (atlas) if (terminate)
break; break;
} }
} }
@ -101,26 +106,11 @@ bool MapList::loadDirR(const QString &path)
return ret; return ret;
} }
bool MapList::loadFile(const QString &path)
{
bool atlas;
_errorString.clear();
return loadFile(path, &atlas, false);
}
bool MapList::loadDir(const QString &path)
{
_errorString.clear();
return loadDirR(path);
}
QString MapList::formats() QString MapList::formats()
{ {
return return
tr("Supported files") tr("Supported files") + " (" + filter().join(" ") + ");;"
+ " (*.img *.jnx *.map *.mbtiles *.rmap *.rtmap *.tar *.tba *.tif *.tiff *.xml);;" + tr("Garmin IMG maps") + " (*.gmap *.gmapi *.img *.xml);;"
+ tr("Garmin IMG maps") + " (*.img);;"
+ tr("Garmin JNX maps") + " (*.jnx);;" + tr("Garmin JNX maps") + " (*.jnx);;"
+ tr("OziExplorer maps") + " (*.map);;" + tr("OziExplorer maps") + " (*.map);;"
+ tr("MBTiles maps") + " (*.mbtiles);;" + tr("MBTiles maps") + " (*.mbtiles);;"
@ -133,7 +123,8 @@ QString MapList::formats()
QStringList MapList::filter() QStringList MapList::filter()
{ {
QStringList filter; QStringList filter;
filter << "*.img" << "*.jnx" << "*.map" << "*.tba" << "*.tar" << "*.xml" filter << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.map"
<< "*.tif" << "*.tiff" << "*.mbtiles" << "*.rmap" << "*.rtmap" << "*.img"; << "*.mbtiles" << "*.rmap" << "*.rtmap" << "*.tar" << "*.tba" << "*.tif"
<< "*.tiff" << "*.xml";
return filter; return filter;
} }

View File

@ -13,23 +13,24 @@ class MapList : public QObject
public: public:
MapList(QObject *parent = 0) : QObject(parent) {} MapList(QObject *parent = 0) : QObject(parent) {}
bool loadFile(const QString &path); bool loadFile(const QString &path, bool *terminate = 0);
bool loadDir(const QString &path); bool loadDir(const QString &path);
const QList<Map*> &maps() const {return _maps;} const QList<Map*> &maps() const {return _maps;}
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
const QString &errorPath() const {return _errorPath;}
static QString formats(); static QString formats();
static QStringList filter(); static QStringList filter();
private: private:
bool loadFile(const QString &path, bool *atlas, bool dir); Map *loadSource(const QString &path);
bool loadDirR(const QString &path); bool loadMap(Map *map, const QString &path);
Map *loadSource(const QString &path, bool dir);
bool loadMap(Map *map, const QString &path, bool dir);
QList<Map*> _maps; QList<Map*> _maps;
QString _errorString; QString _errorString;
QString _errorPath;
}; };
#endif // MAPLIST_H #endif // MAPLIST_H

View File

@ -222,6 +222,20 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
} }
} }
bool MapSource::isMap(const QString &path)
{
QFile file(path);
if (!file.open(QFile::ReadOnly | QFile::Text))
return false;
QXmlStreamReader reader(&file);
if (reader.readNextStartElement() && reader.name() == "map")
return true;
return false;
}
Map *MapSource::loadMap(const QString &path, QString &errorString) Map *MapSource::loadMap(const QString &path, QString &errorString)
{ {
Config config; Config config;

View File

@ -15,6 +15,7 @@ class MapSource
{ {
public: public:
static Map *loadMap(const QString &path, QString &errorString); static Map *loadMap(const QString &path, QString &errorString);
static bool isMap(const QString &path);
private: private:
enum Type { enum Type {