1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-04 14:49:30 +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:
- Release
@ -17,7 +17,7 @@ environment:
LIBSSL: libcrypto-1_1.dll
- QTDIR: C:\Qt\5.13\msvc2017_64
NSI: gpxsee64.nsi
VCVARS: vcvars64.bat"
VCVARS: vcvars64.bat
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
LIBCRYPTO: libssl-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.
## 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).
* 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.
* Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view.

View File

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

View File

@ -49,7 +49,7 @@
<message>
<location filename="../src/data/data.cpp" line="179"/>
<source>Supported files</source>
<translation>Formatos soportados</translation>
<translation>Formatos admitidos</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="180"/>
@ -89,7 +89,7 @@
<message>
<location filename="../src/data/data.cpp" line="189"/>
<source>JPEG images</source>
<translation>Imagen JPEG</translation>
<translation>Imágenes JPEG</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="190"/>
@ -168,7 +168,7 @@
<message>
<location filename="../src/GUI/elevationgraph.cpp" line="144"/>
<source>ft</source>
<translation>pies</translation>
<translation>ft</translation>
</message>
</context>
<context>
@ -181,7 +181,7 @@
<message>
<location filename="../src/GUI/elevationgraphitem.cpp" line="33"/>
<source>ft</source>
<translation></translation>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/elevationgraphitem.cpp" line="36"/>
@ -234,7 +234,7 @@
<message>
<location filename="../src/GUI/exportdialog.cpp" line="66"/>
<source>in</source>
<translation></translation>
<translation>in</translation>
</message>
<message>
<location filename="../src/GUI/exportdialog.cpp" line="94"/>
@ -301,7 +301,7 @@
<message>
<location filename="../src/GUI/exportdialog.cpp" line="157"/>
<source>%1 is not writable.</source>
<translation>%1 es de sólo lectura.</translation>
<translation>%1 es de solo lectura.</translation>
</message>
</context>
<context>
@ -319,7 +319,7 @@
<location filename="../src/GUI/format.cpp" line="61"/>
<location filename="../src/GUI/format.cpp" line="84"/>
<source>ft</source>
<translation></translation>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/format.cpp" line="57"/>
@ -403,17 +403,17 @@
<message>
<location filename="../src/GUI/gui.cpp" line="256"/>
<source>Load POI file...</source>
<translation>Cargar archivo de POI&apos;s...</translation>
<translation>Cargar archivo de POI...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="260"/>
<source>Close POI files</source>
<translation>Cerrar archivo de POI&apos;s</translation>
<translation>Cerrar archivos de POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="264"/>
<source>Overlap POIs</source>
<translation>Sobrescribir POI&apos;s</translation>
<translation>Sobreponer POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="269"/>
@ -423,7 +423,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="274"/>
<source>Show POIs</source>
<translation>Ver POI&apos;s</translation>
<translation>Ver POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="284"/>
@ -438,7 +438,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="296"/>
<source>Clear tile cache</source>
<translation>Limpiar cache de teselas</translation>
<translation>Limpiar antememoria de teselas</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="301"/>
@ -455,7 +455,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="322"/>
<source>Show tracks</source>
<translation>Ver tracks</translation>
<translation>Ver pistas</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="327"/>
@ -465,7 +465,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="332"/>
<source>Show waypoints</source>
<translation>Ver waypoints</translation>
<translation>Ver puntos de referencia</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="337"/>
@ -480,7 +480,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="347"/>
<source>Route waypoints</source>
<translation>Waypoints de ruta</translation>
<translation>Puntos de referencia de ruta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="352"/>
@ -622,7 +622,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="529"/>
<source>POI files</source>
<translation>Archivos de POI&apos;s</translation>
<translation>Archivos de POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="540"/>
@ -727,22 +727,22 @@
<message>
<location filename="../src/GUI/gui.cpp" line="707"/>
<source>Zoom in</source>
<translation>Zoom +</translation>
<translation>Acercar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="709"/>
<source>Zoom out</source>
<translation>Zoom -</translation>
<translation>Alejar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="711"/>
<source>Digital zoom</source>
<translation>Zoom digital</translation>
<translation>Escala digital</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="712"/>
<source>Zoom</source>
<translation>Zoom</translation>
<translation>Escala</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="725"/>
@ -752,7 +752,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="727"/>
<source>POI directory:</source>
<translation>Carpeta de POIs:</translation>
<translation>Carpeta de POI:</translation>
</message>
<message>
<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="877"/>
<source>Line: %1</source>
<translation>Linea: %1</translation>
<translation>Renglón: %1</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="850"/>
<source>Open POI file</source>
<translation>Cargar archivo de POI&apos;s</translation>
<translation>Cargar archivo de POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="874"/>
<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>
<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="1103"/>
<source>Waypoints</source>
<translation>Waypoints</translation>
<translation>Puntos de referencia</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1037"/>
@ -851,7 +851,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="1336"/>
<source>Error loading map:</source>
<translation>Error cargando archivo de mapa:</translation>
<translation>Error al cargar el archivo de mapa:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1347"/>
@ -878,7 +878,7 @@
<message>
<location filename="../src/GUI/gearratiograph.cpp" line="27"/>
<source>Most used</source>
<translation>Mas usada</translation>
<translation>Más usada</translation>
</message>
<message>
<location filename="../src/GUI/gearratiograph.cpp" line="29"/>
@ -914,7 +914,7 @@
<message>
<location filename="../src/GUI/graphview.cpp" line="46"/>
<source>Data not available</source>
<translation>Sin datos</translation>
<translation>Sin datos disponibles</translation>
</message>
<message>
<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="118"/>
<source>ft</source>
<translation></translation>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/graphview.cpp" line="113"/>
@ -1017,7 +1017,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="121"/>
<source>Supported files</source>
<translation>Formatos soportados</translation>
<translation>Formatos admitidos</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="126"/>
@ -1047,7 +1047,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="128"/>
<source>GeoTIFF images</source>
<translation>Imagenes GeoTIFF</translation>
<translation>Imágenes GeoTIFF</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="129"/>
@ -1057,7 +1057,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<source>Online map sources</source>
<translation>Mapas Online</translation>
<translation>Fuentes de mapas en nea</translation>
</message>
</context>
<context>
@ -1065,12 +1065,12 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="61"/>
<source>High-resolution</source>
<translation>Alta resolución</translation>
<translation>Resolución alta</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="62"/>
<source>Standard</source>
<translation>Estandar</translation>
<translation>Estándar</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="67"/>
@ -1185,12 +1185,12 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="211"/>
<source>Waypoint color:</source>
<translation>Color de waypoints:</translation>
<translation>Color de puntos de referencia:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="212"/>
<source>Waypoint size:</source>
<translation>Tamaño de wapoints:</translation>
<translation>Tamaño de puntos de referencia:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="214"/>
@ -1207,27 +1207,27 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="216"/>
<source>Waypoints</source>
<translation>Waypoints</translation>
<translation>Puntos de referencia</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="227"/>
<source>POI color:</source>
<translation>Color de POI&apos;s:</translation>
<translation>Color de POI:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="228"/>
<source>POI size:</source>
<translation>Tamaño de POI&apos;s:</translation>
<translation>Tamaño de POI:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="232"/>
<source>POIs</source>
<translation>POI&apos;s</translation>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="258"/>
<source>Line width:</source>
<translation>Anchura de linea:</translation>
<translation>Anchura de línea:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="259"/>
@ -1435,17 +1435,17 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="509"/>
<source>High-Resolution</source>
<translation>Alta resolución</translation>
<translation>Resolución alta</translation>
</message>
<message>
<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>
<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>
<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>
<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>
<location filename="../src/GUI/optionsdialog.cpp" line="538"/>
@ -1500,17 +1500,17 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="585"/>
<source>Enable HTTP/2</source>
<translation>Habilitar HTTP/2</translation>
<translation>Activar HTTP/2</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="592"/>
<source>MB</source>
<translation>Mo</translation>
<translation>MB</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="602"/>
<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>
<location filename="../src/GUI/optionsdialog.cpp" line="603"/>
@ -1591,7 +1591,7 @@
<message>
<location filename="../src/GUI/powergraphitem.cpp" line="17"/>
<source>Maximum</source>
<translation>Maxima</translation>
<translation>Máxima</translation>
</message>
<message>
<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="112"/>
<source>ft</source>
<translation></translation>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>

View File

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

View File

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

View File

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

View File

@ -119,7 +119,7 @@
<message>
<location filename="../src/data/data.cpp" line="195"/>
<source>SML files</source>
<translation type="unfinished"></translation>
<translation>SML файли</translation>
</message>
<message>
<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[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
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[ru]=Программа для просмотра и анализа GPS логов
Comment[sv]=GPS-loggfilsläsare och analysator
@ -14,4 +15,4 @@ Icon=gpxsee
Terminal=false
Type=Application
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
Name "GPXSee"
; Program version
!define VERSION "7.20"
!define VERSION "7.22"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -176,6 +176,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Finnish" "fi"
!insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de"
!insertmacro LOCALIZATION "Hungarian" "hu"
!insertmacro LOCALIZATION "Norwegian" "nb"
!insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
@ -251,4 +252,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

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

View File

@ -112,7 +112,7 @@ void GUI::loadMaps()
QString mapDir(ProgramPaths::mapDir());
if (!mapDir.isNull() && !_ml->loadDir(mapDir))
qWarning("%s", qPrintable(_ml->errorString()));
qWarning("%s", qPrintable(_ml->errorPath() + ": " + _ml->errorString()));
_map = new EmptyMap(this);
}
@ -1325,7 +1325,10 @@ bool GUI::loadMap(const QString &fileName)
if (fileName.isEmpty())
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());
_mapMenu->insertAction(_mapsEnd, a);
_showMapAction->setEnabled(true);

View File

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

View File

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

View File

@ -32,7 +32,7 @@ bool BitStream1::read(int bits, quint32 &val)
bool BitStream1::flush()
{
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
return false;
_length = 0;
@ -50,18 +50,13 @@ bool BitStream4::read(int bits, quint32 &val)
return true;
}
quint32 old = 0;
if (_used < 32) {
old = (_data << _used) >> (32 - bits);
bits = (bits - 32) + _used;
}
_used = bits;
quint32 bytes = qMin(_length, (quint32)4);
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
quint32 bytes = qMin(_length, 4U);
if (!_file.readVUInt32SW(_hdl, bytes, _data))
return false;
_used -= 32 - bits;
_length -= bytes;
_unused = (4 - bytes) * 8;
_data <<= _unused;
@ -73,11 +68,12 @@ bool BitStream4::read(int bits, quint32 &val)
bool BitStream4::flush()
{
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
return false;
_length = 0;
_unused = 32;
_used = 32;
_unused = 0;
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)
{
quint32 bit;
@ -64,21 +41,17 @@ bool HuffmanStream::sign(int &val)
bool HuffmanStream::readDelta(int sign, qint32 &symbol)
{
uchar size;
quint8 size;
quint32 next;
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), bitsAvailable());
if (_symbolDataSize < 32) {
quint32 next;
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize),
bitsAvailable());
if (!read(nextSize, next))
return false;
if (!read(nextSize, next))
return false;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
}
symbol = _table.symbol(_symbolData << (32U - _symbolDataSize), size);
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
if (size <= _symbolDataSize)
_symbolDataSize -= size;

View File

@ -9,8 +9,16 @@ public:
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
const HuffmanTable &table, bool line);
bool readNext(qint32 &lonDelta, qint32 &latDelta);
bool readOffset(qint32 &lonDelta, qint32 &latDelta);
bool readNext(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
{return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();}

View File

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

View File

@ -1,27 +1,10 @@
#include <QMap>
#include <QtEndian>
#include "common/programpaths.h"
#include "vectortile.h"
#include "img.h"
#define CACHE_SIZE 8388608 /* 8MB */
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;
};
typedef QMap<QByteArray, VectorTile*> TileMap;
static SubFile::Type tileType(const char str[3])
{
@ -41,8 +24,7 @@ static SubFile::Type tileType(const char str[3])
return SubFile::Unknown;
}
IMG::IMG(const QString &fileName)
: _file(fileName), _typ(0), _style(0), _valid(false)
IMG::IMG(const QString &fileName) : _file(fileName)
{
#define CHECK(condition) \
if (!(condition)) { \
@ -52,7 +34,7 @@ IMG::IMG(const QString &fileName)
}
TileMap tileMap;
QString typFile;
QByteArray typFile;
if (!_file.open(QFile::ReadOnly)) {
_errorString = _file.errorString();
@ -78,8 +60,6 @@ IMG::IMG(const QString &fileName)
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
_blockSize = 1 << (e1 + e2);
_blockCache.setMaxCost(CACHE_SIZE / _blockSize);
// Read the FAT table
quint8 flag;
@ -107,7 +87,7 @@ IMG::IMG(const QString &fileName)
&& read(type, sizeof(type)) && readValue(size) && readValue(part));
SubFile::Type tt = tileType(type);
QString fn(QByteArray(name, sizeof(name)));
QByteArray fn(name, sizeof(name));
if (VectorTile::isTileFile(tt)) {
VectorTile *tile;
TileMap::const_iterator it = tileMap.find(fn);
@ -156,7 +136,7 @@ IMG::IMG(const QString &fileName)
it != tileMap.constEnd(); ++it) {
VectorTile *tile = it.value();
if (!tile->init()) {
if (!tile->init(false)) {
qWarning("%s: %s: Invalid map tile", qPrintable(_file.fileName()),
qPrintable(it.key()));
delete tile;
@ -179,65 +159,6 @@ IMG::IMG(const QString &fileName)
_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 ret = _file.read(data, maxSize);
@ -259,33 +180,12 @@ template<class T> bool IMG::readValue(T &val)
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))
return false;
data.resize(_blockSize);
if (read(data.data(), _blockSize) < _blockSize)
return false;
_blockCache.insert(blockNum, new QByteArray(data));
} else
data = *block;
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
return false;
if (read(data, _blockSize) < _blockSize)
return false;
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
#include <QFile>
#include <QByteArray>
#include <QCache>
#include <QDebug>
#include "common/rtree.h"
#include "common/rectc.h"
#include "style.h"
#include "label.h"
#include "mapdata.h"
class VectorTile;
class SubFile;
class IMG
class IMG : public 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;
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();
void load();
void clear();
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:
friend class SubFile;
typedef RTree<VectorTile*, double, 2> TileTree;
int blockSize() const {return _blockSize;}
bool readBlock(int blockNum, QByteArray &data);
bool readBlock(int blockNum, char *data);
qint64 read(char *data, qint64 maxSize);
template<class T> bool readValue(T &val);
QFile _file;
quint8 _key;
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

View File

@ -12,6 +12,9 @@ public:
LBLFile(IMG *img)
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(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),
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(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
{
public:
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _multiplier(0) {}
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_offset(0), _size(0), _multiplier(0) {}
NETFile(IMG *img)
: SubFile(img), _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);

View File

@ -35,11 +35,11 @@ bool RGNFile::skipClassFields(Handle &hdl) const
break;
}
return seek(hdl, hdl.pos + rs);
return seek(hdl, hdl.pos() + rs);
}
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
Segment::Type type) const
SegmentType type) const
{
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;
switch (i) {
case 5:
if (m == 1 && type == Segment::Point) {
if (m == 1 && type == Point) {
quint16 u16;
if (!readUInt16(hdl, u16))
return false;
@ -116,11 +116,16 @@ bool RGNFile::init(Handle &hdl)
return true;
}
bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, NETFile *net,
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;
quint32 labelPtr;
@ -128,7 +133,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
qint16 lon, lat;
quint16 len;
while (hdl.pos < (int)segment.end()) {
while (hdl.pos() < (int)segment.end()) {
IMG::Poly poly;
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))
return false;
poly.type = (segment.type() == Segment::Polygon)
poly.type = (segmentType == Polygon)
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
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()));
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()));
poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c);
poly.boundingRect = poly.boundingRect.united(c);
}
if (!(stream.atEnd() && stream.flush()))
return false;
if (!rect.intersects(br))
continue;
if (lbl && (labelPtr & 0x3FFFFF)) {
if (labelPtr & 0x800000) {
quint32 lblOff;
@ -188,22 +190,25 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
return true;
}
bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
const SubDiv *subdiv, quint32 shift, const Segment &segment, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Poly> *polys, bool line) const
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys) const
{
quint32 labelPtr, len;
quint8 type, subtype;
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;
while (hdl.pos < (int)segment.end()) {
while (hdl.pos() < (int)segment.end()) {
IMG::Poly poly;
QPoint pos;
RectC br;
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
&& 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())));
qint32 lonDelta, latDelta;
HuffmanStream stream(*this, hdl, len, _huffmanTable, line);
HuffmanStream stream(*this, hdl, len, _huffmanTable,
segmentType == Line);
if (shift) {
if (!stream.readOffset(lonDelta, latDelta))
@ -227,7 +233,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
pos.y() | latDelta<<(32-subdiv->bits()-shift));
}
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()));
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()));
poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c);
poly.boundingRect = poly.boundingRect.united(c);
}
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())),
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
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()));
quint8 bitstreamInfo;
@ -261,7 +267,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
br = br.united(c);
poly.boundingRect = poly.boundingRect.united(c);
}
if (!(stream.atEnd() && stream.flush()))
return false;
@ -271,13 +277,10 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
return false;
if (subtype & 0x80 && !skipClassFields(hdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, line ? _linesFlags
: _polygonsFlags, segment.type()))
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
? _linesFlags : _polygonsFlags, segmentType))
return false;
if (!rect.intersects(br))
continue;
if (lbl && (labelPtr & 0x3FFFFF))
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
@ -287,18 +290,22 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
return true;
}
bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const
{
quint8 type, subtype;
qint16 lon, lat;
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;
while (hdl.pos < (int)segment.end()) {
while (hdl.pos() < (int)segment.end()) {
IMG::Point point;
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;
qint16 lonOffset = lon<<(24-subdiv->bits());
qint16 latOffset = lat<<(24-subdiv->bits());
qint32 lonOffset = lon<<(24-subdiv->bits());
qint32 latOffset = lat<<(24-subdiv->bits());
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
toWGS24(subdiv->lat() + latOffset));
if (!rect.contains(point.coordinates))
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;
if (lbl && (labelPtr & 0x3FFFFF)) {
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
point.id = ((quint64)point.type)<<40 | ((quint64)lbl->offset())<<24
| (labelPtr & 0x3FFFFF);
}
points->append(point);
}
@ -333,18 +338,21 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
return true;
}
bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl,
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Point> *points) const
{
quint8 type, subtype;
qint16 lon, lat;
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;
while (hdl.pos < (int)segment.end()) {
while (hdl.pos() < (int)segment.end()) {
IMG::Point point;
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);
qint16 lonOffset = lon<<(24-subdiv->bits());
qint16 latOffset = lat<<(24-subdiv->bits());
qint32 lonOffset = lon<<(24-subdiv->bits());
qint32 latOffset = lat<<(24-subdiv->bits());
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
toWGS24(subdiv->lat() + latOffset));
labelPtr = 0;
@ -363,18 +371,21 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
return false;
if (subtype & 0x80 && !skipClassFields(hdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, segment.type()))
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
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;
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;
if (lbl && (labelPtr & 0x3FFFFF)) {
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
point.id = ((quint64)point.type)<<40
| ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
}
points->append(point);
}
@ -382,85 +393,13 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
return true;
}
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv,
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
SubDiv *subdiv) const
{
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))
return QVector<Segment>();
return ret;
quint32 offset = _offset + subdiv->offset();
@ -470,57 +409,63 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
no++;
if (!seek(hdl, offset))
return QVector<Segment>();
return ret;
QVector<Segment> ret;
quint32 start = offset + 2 * (no - 1);
quint16 po;
int cnt = 0;
quint32 ls = 0;
SegmentType lt = (SegmentType)0;
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
if (subdiv->objects() & mask) {
if (cnt) {
if (!readUInt16(hdl, po))
return QVector<Segment>();
if (ls) {
quint16 po;
if (!readUInt16(hdl, po) || !po)
return QMap<RGNFile::SegmentType, SubDiv::Segment>();
start = offset + po;
ret.insert(lt, SubDiv::Segment(ls, start));
}
if (!ret.isEmpty())
ret.last().setEnd(start);
ret.append(Segment(start, (Segment::Type)mask));
cnt++;
lt = (SegmentType)mask;
ls = start;
}
}
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;
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment)
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
{
QString type;
switch (segment.type()) {
case RGNFile::Segment::Point:
type = "Point";
break;
case RGNFile::Segment::IndexedPoint:
type = "IndexedPoint";
break;
case RGNFile::Segment::Line:
type = "Line";
break;
case RGNFile::Segment::Polygon:
type = "Polygon";
break;
case RGNFile::Segment::RoadReference:
type = "RoadReference";
break;
QMap<RGNFile::SegmentType, SubDiv::Segment> seg(segments(hdl, subdiv));
SubDiv::Segment extPoints, extLines, extPolygons;
if (subdiv->extPointsOffset() != subdiv->extPointsEnd()) {
quint32 start = _pointsOffset + subdiv->extPointsOffset();
quint32 end = subdiv->extPointsEnd()
? _pointsOffset + subdiv->extPointsEnd()
: _pointsOffset + _pointsSize;
extPoints = SubDiv::Segment(start, end);
}
if (subdiv->extPolygonsOffset() != subdiv->extPolygonsEnd()) {
quint32 start = _polygonsOffset + subdiv->extPolygonsOffset();
quint32 end = subdiv->extPolygonsEnd()
? _polygonsOffset + subdiv->extPolygonsEnd()
: _polygonsOffset + _polygonsSize;
extPolygons = SubDiv::Segment(start, end);
}
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()
- segment.start() << ", " << type << ")";
subdiv->init(seg.value(Point), seg.value(IndexedPoint), seg.value(Line),
seg.value(Polygon), seg.value(RoadReference), extPoints, extLines,
extPolygons);
return dbg.space();
return true;
}
#endif // QT_NO_DEBUG

View File

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

View File

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

View File

@ -7,55 +7,147 @@
class SubDiv {
public:
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
: _offset(offset), _end(0), _lon(lon), _lat(lat), _bits(bits),
_objects(objects), _polygonsOffset(0), _polygonsEnd(0), _linesOffset(0),
_linesEnd(0), _pointsOffset(0), _pointsEnd(0) {}
void setEnd(quint32 end) {_end = end;}
class Segment {
public:
Segment() : _offset(0), _end(0) {}
Segment(quint32 ofset, quint32 end) : _offset(ofset), _end(end) {}
bool isValid() const {return (_end > _offset);}
quint32 offset() const {return _offset;}
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;}
quint32 offset() const {return _offset;}
quint32 end() const {return _end;}
qint32 lon() const {return _lon;}
qint32 lat() const {return _lat;}
quint8 bits() const {return _bits;}
quint8 objects() const {return _objects;}
// Extended types objects (TRE7)
void setExtOffsets(quint32 polygon, quint32 line, quint32 point)
{_polygonsOffset = polygon; _linesOffset = line; _pointsOffset = point;}
void setExtEnds(quint32 polygon, quint32 line, quint32 point)
{_polygonsEnd = polygon; _linesEnd = line; _pointsEnd = point;}
// Valid only after initialization
Segment points() const
{return Segment(_rgn.pointsOffset, _rgn.pointsEnd);}
Segment idxPoints() const
{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;}
quint32 polygonsEnd() const {return _polygonsEnd;}
quint32 linesOffset() const {return _linesOffset;}
quint32 linesEnd() const {return _linesEnd;}
quint32 pointsOffset() const {return _pointsOffset;}
quint32 pointsEnd() const {return _pointsEnd;}
// Valid only until initialization
quint8 objects() const {return _tre.objects;}
quint32 offset() const {return _tre.offset;}
quint32 end() const {return _tre.end;}
quint32 extPolygonsOffset() const {return _tre.extPolygonsOffset;}
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:
quint32 _offset;
quint32 _end;
struct TRE
{
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;
quint8 _bits;
quint8 _objects;
quint32 _polygonsOffset;
quint32 _polygonsEnd;
quint32 _linesOffset;
quint32 _linesEnd;
quint32 _pointsOffset;
quint32 _pointsEnd;
bool _init;
union {
TRE _tre;
RGN _rgn;
};
};
#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

View File

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

View File

@ -3,35 +3,56 @@
#include <QVector>
#include <QDebug>
#include <QFile>
#include "img.h"
class QFile;
class IMG;
#define BLOCK_SIZE 4096
class SubFile
{
public:
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 blockNum;
int blockPos;
int pos;
int pos() const {return _pos;}
private:
friend class SubFile;
QFile *_file;
QByteArray _data;
int _blockNum;
int _blockPos;
int _pos;
};
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),
_blocks(gmp->_blocks), _file(gmp->_file) {}
SubFile(QFile *file)
: _gmpOffset(0), _img(0), _blocks(0), _file(file) {}
_blocks(gmp->_blocks), _path(gmp->_path) {}
SubFile(const QString &path)
: _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)) {}
~SubFile()
{
if (!_gmpOffset)
if (!_gmpOffset) {
delete _blocks;
delete _path;
}
}
void addBlock(quint16 block) {_blocks->append(block);}
@ -97,22 +118,41 @@ public:
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 readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const;
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
quint16 offset() const {return _blocks->first();}
QString fileName() const;
QString fileName() const {return _path ? *_path : _img->fileName();}
protected:
quint32 _gmpOffset;
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;
QVector<quint16> *_blocks;
QFile *_file;
QString *_path;
};
#endif // SUBFILE_H

View File

@ -37,9 +37,9 @@ TREFile::~TREFile()
clear();
}
bool TREFile::init()
bool TREFile::init(bool baseMap)
{
Handle hdl;
Handle hdl(this);
quint8 locked;
quint16 hdrLen;
@ -108,12 +108,14 @@ bool TREFile::init()
}
}
_isBaseMap = baseMap;
return (_firstLevel >= 0);
}
bool TREFile::load(int idx)
{
Handle hdl;
Handle hdl(this);
QList<SubDiv*> sl;
SubDiv *s = 0;
SubDivTree *tree = new SubDivTree();
@ -199,7 +201,7 @@ bool TREFile::load(int idx)
if (i)
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;
}
@ -236,10 +238,17 @@ void TREFile::clear()
_subdivs.clear();
}
int TREFile::level(int bits)
int TREFile::level(int bits, bool baseMap)
{
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++) {
if (_levels.at(i).bits > bits)
break;
@ -259,10 +268,10 @@ static bool cb(SubDiv *subdiv, void *context)
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;
SubDivTree *tree = _subdivs.value(level(bits));
SubDivTree *tree = _subdivs.value(level(bits, baseMap));
double min[2], max[2];
min[0] = rect.left();

View File

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

View File

@ -1,5 +1,23 @@
#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)
{
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())
return false;
if (!(_tre && _tre->init() && _rgn))
if (!(_tre && _tre->init(baseMap) && _rgn))
return false;
return true;
@ -54,7 +95,7 @@ bool VectorTile::init()
bool VectorTile::initGMP()
{
SubFile::Handle hdl;
SubFile::Handle hdl(_gmp);
quint32 tre, rgn, lbl, net;
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
@ -62,25 +103,84 @@ bool VectorTile::initGMP()
&& _gmp->readUInt32(hdl, net)))
return false;
_tre = new TREFile(_gmp, tre);
_rgn = new RGNFile(_gmp, rgn);
_lbl = new LBLFile(_gmp, lbl);
_net = new NETFile(_gmp, net);
_tre = tre ? new TREFile(_gmp, tre) : 0;
_rgn = rgn ? new RGNFile(_gmp, rgn) : 0;
_lbl = lbl ? new LBLFile(_gmp, lbl) : 0;
_net = net ? new NETFile(_gmp, net) : 0;
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::Point> *points) const
QCache<const SubDiv *, IMG::Polys> *polyCache) const
{
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits);
for (int i = 0; i < subdivs.size(); i++) {
const SubDiv *subdiv = subdivs.at(i);
quint32 shift = _tre->shift(subdiv->bits());
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net);
_rgn->objects(rect, subdiv, _lbl, _net, polygons, lines, points);
_rgn->extObjects(rect, subdiv, shift, _lbl, polygons, lines, points);
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);
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
#define VECTORTILE_H
#include "img.h"
#include "trefile.h"
#include "trefile.h"
#include "rgnfile.h"
@ -16,16 +15,21 @@ public:
delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;
}
bool init();
bool init(bool baseMap);
void clear() {_tre->clear();}
const RectC &bounds() const {return _tre->bounds();}
SubFile *file(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,
QList<IMG::Poly> *lines, QList<IMG::Point> *points) const;
void polys(const RectC &rect, int bits, bool baseMap,
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)
{
@ -34,8 +38,6 @@ public:
|| type == SubFile::GMP);
}
friend QDebug operator<<(QDebug dbg, const VectorTile &tile);
private:
bool initGMP();

View File

@ -13,6 +13,9 @@
#include "IMG/textpathitem.h"
#include "IMG/textpointitem.h"
#include "IMG/bitmapline.h"
#include "IMG/style.h"
#include "IMG/img.h"
#include "IMG/gmap.h"
#include "pcs.h"
#include "rectd.h"
#include "imgmap.h"
@ -35,9 +38,9 @@ public:
const QString &key() const {return _key;}
const QPoint &xy() const {return _xy;}
QImage &img() {return _img;}
QList<IMG::Poly> &polygons() {return _polygons;}
QList<IMG::Poly> &lines() {return _lines;}
QList<IMG::Point> &points() {return _points;}
QList<MapData::Poly> &polygons() {return _polygons;}
QList<MapData::Poly> &lines() {return _lines;}
QList<MapData::Point> &points() {return _points;}
void render()
{
@ -70,9 +73,9 @@ private:
QPoint _xy;
QString _key;
QImage _img;
QList<IMG::Poly> _polygons;
QList<IMG::Poly> _lines;
QList<IMG::Point> _points;
QList<MapData::Poly> _polygons;
QList<MapData::Poly> _lines;
QList<MapData::Point> _points;
};
@ -201,25 +204,20 @@ static qreal area(const QVector<QPointF> &polygon)
return area;
}
static QPointF centroid(const QVector<QPointF> polygon)
static QPointF centroid(const QVector<QPointF> &polygon)
{
qreal cx = 0, cy = 0, factor = 0;
qreal A = area(polygon);
qreal cx = 0, cy = 0;
qreal factor = 1.0 / (6.0 * area(polygon));
for (int i = 0; i < polygon.size(); i++) {
int j = (i + 1) % polygon.size();
factor=(polygon.at(i).x() * polygon.at(j).y() - polygon[j].x()
* polygon[i].y());
cx+=(polygon[i].x() + polygon[j].x()) * factor;
cy+=(polygon[i].y() + polygon[j].y()) * factor;
qreal f = (polygon.at(i).x() * polygon.at(j).y() - polygon.at(j).x()
* polygon.at(i).y());
cx += (polygon.at(i).x() + polygon.at(j).x()) * f;
cy += (polygon.at(i).y() + polygon.at(j).y()) * f;
}
A *= 6.0f;
factor = 1/A;
cx *= factor;
cy *= factor;
return QPointF(cx, cy);
return QPointF(cx * factor, cy * factor);
}
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)));
}
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()) {
_errorString = _img.errorString();
if (GMAP::isGMAP(fileName))
_data = new GMAP(fileName);
else
_data = new IMG(fileName);
if (!_data->isValid()) {
_errorString = _data->errorString();
return;
}
@ -247,17 +251,17 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
void IMGMap::load()
{
_img.load();
_data->load();
}
void IMGMap::unload()
{
_img.clear();
_data->clear();
}
QRectF IMGMap::bounds()
{
RectD prect(_img.bounds(), _projection);
RectD prect(_data->bounds(), _projection);
return QRectF(_transform.proj2img(prect.topLeft()),
_transform.proj2img(prect.bottomRight()));
}
@ -307,7 +311,7 @@ Transform IMGMap::transform(int zoom) const
{
double scale = _projection.isGeographic()
? 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),
PointD(scale, scale));
}
@ -327,15 +331,14 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
return _projection.xy2ll(_transform.img2proj(p));
}
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
void IMGMap::drawPolygons(QPainter *painter, const QList<MapData::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++) {
const IMG::Poly &poly = polygons.at(i);
if (poly.type != _img.style()->drawOrder().at(n))
const MapData::Poly &poly = polygons.at(i);
if (poly.type != _data->style()->drawOrder().at(n))
continue;
const Style::Polygon &style = _img.style()->polygon(poly.type);
const Style::Polygon &style = _data->style()->polygon(poly.type);
painter->setPen(style.pen());
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);
for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i);
const Style::Line &style = _img.style()->line(poly.type);
const MapData::Poly &poly = lines.at(i);
const Style::Line &style = _data->style()->line(poly.type);
if (style.background() == Qt::NoPen)
continue;
@ -360,8 +363,8 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
}
for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i);
const Style::Line &style = _img.style()->line(poly.type);
const MapData::Poly &poly = lines.at(i);
const Style::Line &style = _data->style()->line(poly.type);
if (!style.img().isNull())
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);
}
void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
void IMGMap::processPolygons(QList<MapData::Poly> &polygons,
QList<TextItem*> &textItems)
{
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++) {
QPointF &p = poly.points[j];
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)
|| Style::isMilitaryArea(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(
centroid(poly.points).toPoint(), &poly.label.text(),
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)
{
qStableSort(lines);
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++) {
QPointF &p = poly.points[j];
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);
}
void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems)
void IMGMap::processStreetNames(QList<MapData::Poly> &lines,
const QRect &tileRect, QList<TextItem*> &textItems)
{
for (int i = 0; i < lines.size(); i++) {
IMG::Poly &poly = lines[i];
const Style::Line &style = _img.style()->line(poly.type);
MapData::Poly &poly = lines[i];
const Style::Line &style = _data->style()->line(poly.type);
if (style.img().isNull() && style.foreground() == Qt::NoPen)
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)
{
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;
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();
if (!shield.isValid() || shield.type() != 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)
{
qSort(points);
for (int i = 0; i < points.size(); i++) {
IMG::Point &point = points[i];
const Style::Point &style = _img.style()->point(point.type);
MapData::Point &point = points[i];
const Style::Point &style = _data->style()->point(point.type);
if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
continue;
@ -580,7 +582,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
for (int j = 0; j < height; j++) {
QPixmap pm;
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());
if (QPixmapCache::find(key, 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(
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
_img.objects(polyRect.toRectC(_projection, 4), _zoom,
&(tile.polygons()), &(tile.lines()), 0);
_data->polys(polyRect.toRectC(_projection, 4), _zoom,
&(tile.polygons()), &(tile.lines()));
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
_img.objects(pointRect.toRectC(_projection, 4), _zoom,
0, 0, &(tile.points()));
_data->points(pointRect.toRectC(_projection, 4), _zoom,
&(tile.points()));
}
}
}

View File

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

View File

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

View File

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

View File

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