mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-03 06:19:15 +02:00
Compare commits
115 Commits
Author | SHA1 | Date | |
---|---|---|---|
bf0dd1b24a | |||
9859608115 | |||
9f62b7114e | |||
c85f404d28 | |||
bb6d6a4044 | |||
521369a6ec | |||
45a6cdeda0 | |||
12827edcb2 | |||
ee24bd54f1 | |||
cc22df3bf2 | |||
d7f0cda4b2 | |||
a898ff2807 | |||
9dd4e117f6 | |||
92deaaaf2b | |||
015a9187a0 | |||
1de9c6ef5d | |||
54b6225c6c | |||
48c7299ba6 | |||
c284b9fa7c | |||
2c503a2406 | |||
27edc4d6b5 | |||
f333a76ef7 | |||
2c114f43c5 | |||
29e29591f8 | |||
e4ac9fda0e | |||
26229e5871 | |||
64bee2f2f4 | |||
e4288ee95c | |||
c9b3c2eedd | |||
42e4b0769f | |||
ce043ef8fa | |||
8c7050e273 | |||
d670107a11 | |||
7b03c4d852 | |||
2002b828dd | |||
71f0e1d0ac | |||
eb9767f2dd | |||
8d06ab6208 | |||
187cb77858 | |||
8167a995f6 | |||
b5aed7314e | |||
464d4c5327 | |||
11f4dc4b41 | |||
2d3ad41d69 | |||
a7dcc57dd1 | |||
2d5e11f001 | |||
e86f89308b | |||
378fa8dc0e | |||
dde8903013 | |||
37c4fe1eba | |||
f9db0acb03 | |||
1aa07a6a34 | |||
c302a67299 | |||
8b6d7acec5 | |||
ba70fd159d | |||
1773a1ae0d | |||
136f08aa76 | |||
f70d92805b | |||
69e66f1856 | |||
911c63df0c | |||
d16899530a | |||
e2339c67cd | |||
c809d2f17e | |||
fac0bae006 | |||
9bd03c1225 | |||
d63c666997 | |||
0cd20a1e57 | |||
2f70d46be8 | |||
325e83569c | |||
56b374ed30 | |||
df1be4aeb9 | |||
d79bdaef78 | |||
fa0c09b30c | |||
95c82c501a | |||
3b16f37e66 | |||
661e26fbdb | |||
25939cfa62 | |||
c59ea4e5cd | |||
5de1bc7e7d | |||
7c3399575b | |||
7bedd17071 | |||
06a84dcea2 | |||
ca204626a1 | |||
d16ef7b081 | |||
ef013dc036 | |||
633d52daca | |||
adbb5e5684 | |||
bd9b09df3d | |||
ede2b6004f | |||
a516055dc2 | |||
1ba3ada96e | |||
1667e0ca70 | |||
b50d5227a5 | |||
f38db3227f | |||
c3aeb95660 | |||
6bdd97611d | |||
15e09539c7 | |||
a225c6d308 | |||
a94056ac7e | |||
aea7bbdf09 | |||
1c9b31d7c9 | |||
7a9b26756a | |||
eaae965719 | |||
ca6e8638d8 | |||
66a22fbfee | |||
2d3ca7c5f8 | |||
8c71d11fa6 | |||
857c5050f4 | |||
44d1d27c93 | |||
68e20cff5b | |||
1c67f1cac9 | |||
a09d13594d | |||
6916d0e6b4 | |||
757ec98108 | |||
2ddb5dc28b |
@ -1,4 +1,4 @@
|
||||
version: 7.20.{build}
|
||||
version: 7.25.{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
|
||||
|
@ -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.
|
||||
|
12
gpxsee.pro
12
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 7.20
|
||||
VERSION = 7.25
|
||||
|
||||
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
|
||||
|
@ -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'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'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'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'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'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'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'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 lí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'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's:</translation>
|
||||
<translation>Tamaño de POI:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="232"/>
|
||||
<source>POIs</source>
|
||||
<translation>POI'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"/>
|
||||
|
@ -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
1900
lang/gpxsee_hu.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 på 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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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;
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.20"
|
||||
!define VERSION "7.25"
|
||||
|
||||
; 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.20"
|
||||
!define VERSION "7.25"
|
||||
|
||||
; 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4">
|
||||
<name>4UMaps</name>
|
||||
<url>https://tileserver.4umaps.com/$z/$x/$y.png</url>
|
||||
<zoom min="2" max="15"/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3" type="WMTS">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4" type="WMTS">
|
||||
<name>Antarctica</name>
|
||||
<url type="REST">https://gis.ngdc.noaa.gov/arcgis/rest/services/antarctic/antarctic_basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
|
||||
<copyright>NOAA National Centers for Environmental Information (NCEI); International Bathymetric Chart of the Southern Ocean (IBCSO); General Bathymetric Chart of the Oceans (GEBCO); Natural Earth</copyright>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4">
|
||||
<name>Open Street Map</name>
|
||||
<url>https://tile.openstreetmap.org/$z/$x/$y.png</url>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4">
|
||||
<name>Open Topo Map</name>
|
||||
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
|
||||
<zoom max="17"/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4">
|
||||
<name>USGS Imagery</name>
|
||||
<url>https://basemap.nationalmap.gov/ArcGIS/rest/services/USGSImageryOnly/MapServer/tile/$z/$y/$x</url>
|
||||
<zoom min="2" max="15"/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4">
|
||||
<name>USGS Topo</name>
|
||||
<url>https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/$z/$y/$x</url>
|
||||
<zoom min="2" max="15"/>
|
||||
|
@ -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);
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <QGraphicsScene>
|
||||
#include <QWheelEvent>
|
||||
#include <QApplication>
|
||||
#include <QPixmapCache>
|
||||
#include <QScrollBar>
|
||||
#include "data/poi.h"
|
||||
#include "data/data.h"
|
||||
@ -351,7 +350,6 @@ void MapView::setMap(Map *map)
|
||||
centerOn(nc);
|
||||
|
||||
reloadMap();
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void MapView::setPOI(POI *poi)
|
||||
@ -982,7 +980,6 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
|
||||
_deviceRatio = deviceRatio;
|
||||
_mapRatio = mapRatio;
|
||||
QPixmapCache::clear();
|
||||
|
||||
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
|
||||
.intersected(_map->bounds()));
|
||||
|
@ -14,8 +14,8 @@ double Coordinates::distanceTo(const Coordinates &c) const
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c)
|
||||
{
|
||||
dbg.nospace() << qSetRealNumberPrecision(10) << "Coordinates(" << c.lat()
|
||||
<< ", " << c.lon() << ")";
|
||||
dbg.nospace() << qSetRealNumberPrecision(10) << "Coordinates(" << c.lon()
|
||||
<< ", " << c.lat() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -3,14 +3,16 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#define LS(val, bits) ((qint32)(((quint32)(val))<<(bits)))
|
||||
|
||||
inline double toWGS32(qint32 v)
|
||||
{
|
||||
return (double)(((double)v / (double)(1U<<31)) * (double)180);
|
||||
return ((double)v / (double)(1U<<31)) * 180.0;
|
||||
}
|
||||
|
||||
inline double toWGS24(qint32 v)
|
||||
{
|
||||
return toWGS32(v<<8);
|
||||
return toWGS32(LS(v, 8));
|
||||
}
|
||||
|
||||
#endif // GARMIN_H
|
||||
|
@ -28,6 +28,9 @@ public:
|
||||
double left() const {return _tl.lon();}
|
||||
double right() const {return _br.lon();}
|
||||
|
||||
double width() const {return (right() - left());}
|
||||
double height() const {return (top() - bottom());}
|
||||
|
||||
void setLeft(double val) {_tl.rlon() = val;}
|
||||
void setRight(double val) {_br.rlon() = val;}
|
||||
void setTop(double val) {_tl.rlat() = val;}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
#include <QtCore/qmath.h>
|
||||
#else // QT5
|
||||
#include <QtMath>
|
||||
#endif // QT5
|
||||
#include "bitmapline.h"
|
||||
|
||||
|
||||
static QImage img2line(const QImage &img, int width)
|
||||
{
|
||||
Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied);
|
||||
@ -32,8 +38,8 @@ void BitmapLine::draw(QPainter *painter, const QPolygonF &line,
|
||||
painter->save();
|
||||
painter->translate(segment.p1());
|
||||
painter->rotate(-segment.angle());
|
||||
painter->drawImage(0, -img.height()/2, img2line(img, segment.length()));
|
||||
painter->drawImage(0.0, -img.height()/2.0, img2line(img,
|
||||
qCeil(segment.length())));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
161
src/map/IMG/gmap.cpp
Normal file
161
src/map/IMG/gmap.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDir>
|
||||
#include "map/osm.h"
|
||||
#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()) {
|
||||
qWarning("%s: Invalid map tile", qPrintable(dir.path()));
|
||||
delete tile;
|
||||
return false;
|
||||
}
|
||||
if (baseMap)
|
||||
tile->markAsBasemap();
|
||||
|
||||
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();
|
||||
if (tile->zooms().min() < _zooms.min())
|
||||
_zooms.setMin(tile->zooms().min());
|
||||
|
||||
// Limit world maps bounds so that the maps can be projected using
|
||||
// the default Web Mercator projection
|
||||
if (_bounds.height() > 120)
|
||||
_bounds &= OSM::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
30
src/map/IMG/gmap.h
Normal 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
|
@ -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;
|
||||
|
@ -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();}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -1,27 +1,11 @@
|
||||
#include <QMap>
|
||||
#include <QtEndian>
|
||||
#include "common/programpaths.h"
|
||||
#include "map/osm.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 ▭
|
||||
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 +25,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 +35,7 @@ IMG::IMG(const QString &fileName)
|
||||
}
|
||||
|
||||
TileMap tileMap;
|
||||
QString typFile;
|
||||
QByteArray typFile;
|
||||
|
||||
if (!_file.open(QFile::ReadOnly)) {
|
||||
_errorString = _file.errorString();
|
||||
@ -78,8 +61,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 +88,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);
|
||||
@ -152,6 +133,8 @@ IMG::IMG(const QString &fileName)
|
||||
}
|
||||
|
||||
// Create tile tree
|
||||
|
||||
int minMapZoom = 24;
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
@ -171,73 +154,32 @@ IMG::IMG(const QString &fileName)
|
||||
_tileTree.Insert(min, max, tile);
|
||||
|
||||
_bounds |= tile->bounds();
|
||||
if (tile->zooms().min() < _zooms.min())
|
||||
_zooms.setMin(tile->zooms().min());
|
||||
if (tile->zooms().min() < minMapZoom)
|
||||
minMapZoom = tile->zooms().min();
|
||||
}
|
||||
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
if (tile->zooms().min() > minMapZoom)
|
||||
_baseMap = true;
|
||||
if (tile->zooms().min() == minMapZoom)
|
||||
tile->markAsBasemap();
|
||||
}
|
||||
|
||||
// Limit world maps bounds so that the maps can be projected using
|
||||
// the default Web Mercator projection
|
||||
if (_bounds.height() > 120)
|
||||
_bounds &= OSM::BOUNDS;
|
||||
|
||||
if (!_tileTree.Count())
|
||||
_errorString = "No usable map tile found";
|
||||
else
|
||||
_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 +201,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
|
||||
|
@ -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
|
||||
|
@ -30,15 +30,20 @@ static quint8 SPECIAL_CHARS[] = {
|
||||
'8', '9', '~', '~', '~', '~', '~', '~'
|
||||
};
|
||||
|
||||
static QString capitalize(const QString &str)
|
||||
static bool isAllUpperCase(const QString &str)
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return str;
|
||||
return false;
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (str.at(i).isLetter() && !(str.at(i).isUpper()
|
||||
|| str.at(i) == QChar(0x00DF)))
|
||||
return str;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static QString capitalized(const QString &str)
|
||||
{
|
||||
QString ret(str);
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (i && !str.at(i-1).isSpace())
|
||||
@ -77,7 +82,7 @@ bool LBLFile::init(Handle &hdl)
|
||||
return true;
|
||||
}
|
||||
|
||||
Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
|
||||
{
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
@ -95,9 +100,12 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F};
|
||||
|
||||
for (int cpt = 0; cpt < 4; cpt++) {
|
||||
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d))
|
||||
return Label(capitalize(QString::fromLatin1(label)),
|
||||
Label::Shield(shieldType, shieldLabel));
|
||||
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d)) {
|
||||
QString text(QString::fromLatin1(label));
|
||||
return Label(capitalize && isAllUpperCase(text)
|
||||
? capitalized(text) : text, Label::Shield(shieldType,
|
||||
shieldLabel));
|
||||
}
|
||||
switch (curCharSet) {
|
||||
case Normal:
|
||||
if (c[cpt] == 0x1c)
|
||||
@ -127,7 +135,7 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
}
|
||||
}
|
||||
|
||||
Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
|
||||
{
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
@ -157,12 +165,15 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
bap->append(c);
|
||||
}
|
||||
|
||||
return Label(capitalize(_codec ? _codec->toUnicode(label)
|
||||
: QString::fromLatin1(label)), Label::Shield(shieldType, _codec
|
||||
? _codec->toUnicode(shieldLabel) : QString::fromLatin1(shieldLabel)));
|
||||
QString text(_codec ? _codec->toUnicode(label) : QString::fromLatin1(label));
|
||||
QString shieldText(_codec ? _codec->toUnicode(shieldLabel)
|
||||
: QString::fromLatin1(shieldLabel));
|
||||
|
||||
return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text,
|
||||
Label::Shield(shieldType, shieldText));
|
||||
}
|
||||
|
||||
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
|
||||
{
|
||||
if (!_multiplier && !init(hdl))
|
||||
return QString();
|
||||
@ -183,10 +194,10 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
|
||||
switch (_encoding) {
|
||||
case 6:
|
||||
return label6b(hdl, labelOffset);
|
||||
return label6b(hdl, labelOffset, capitalize);
|
||||
case 9:
|
||||
case 10:
|
||||
return label8b(hdl, labelOffset);
|
||||
return label8b(hdl, labelOffset, capitalize);
|
||||
default:
|
||||
return Label();
|
||||
}
|
||||
|
@ -12,17 +12,21 @@ 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) {}
|
||||
|
||||
Label label(Handle &hdl, quint32 offset, bool poi = false);
|
||||
Label label(Handle &hdl, quint32 offset, bool poi = false,
|
||||
bool capitalize = true);
|
||||
|
||||
private:
|
||||
bool init(Handle &hdl);
|
||||
|
||||
Label label6b(Handle &hdl, quint32 offset) const;
|
||||
Label label8b(Handle &hdl, quint32 offset) const;
|
||||
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
|
||||
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
|
||||
|
||||
QTextCodec *_codec;
|
||||
quint32 _offset;
|
||||
|
128
src/map/IMG/mapdata.cpp
Normal file
128
src/map/IMG/mapdata.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#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 ▭
|
||||
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 ▭
|
||||
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), _zooms(15, 28), _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 {
|
||||
QString typFile(ProgramPaths::typFile());
|
||||
if (!typFile.isEmpty()) {
|
||||
SubFile typ(typFile);
|
||||
_style = new Style(&typ);
|
||||
} else
|
||||
_style = new Style();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
110
src/map/IMG/mapdata.h
Normal file
110
src/map/IMG/mapdata.h
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef MAPDATA_H
|
||||
#define MAPDATA_H
|
||||
|
||||
#include <QList>
|
||||
#include <QPointF>
|
||||
#include <QCache>
|
||||
#include <QDebug>
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
#include "common/range.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 Range &zooms() const {return _zooms;}
|
||||
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;
|
||||
Range _zooms;
|
||||
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
|
@ -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);
|
||||
|
||||
|
@ -8,6 +8,20 @@
|
||||
#include "rgnfile.h"
|
||||
|
||||
|
||||
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
|
||||
{
|
||||
quint64 id;
|
||||
|
||||
uint hash = qHash(QPair<uint,uint>(qHash(QPair<int, int>(pos.x(),
|
||||
pos.y())), labelPtr & 0x3FFFFF));
|
||||
id = ((quint64)type)<<32 | hash;
|
||||
// Make country labels precedent over city labels
|
||||
if (!(type >= 0x1400 && type <= 0x153f))
|
||||
id |= 1ULL<<63;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
bool RGNFile::skipClassFields(Handle &hdl) const
|
||||
{
|
||||
quint8 flags;
|
||||
@ -35,11 +49,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 +67,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 +130,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 +147,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,33 +164,32 @@ 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())));
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(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;
|
||||
DeltaStream stream(*this, hdl, len, bitstreamInfo, labelPtr & 0x400000,
|
||||
false);
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
pos.rx() += LS(lonDelta, (24-subdiv->bits()));
|
||||
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffff;
|
||||
pos.ry() += LS(latDelta, (24-subdiv->bits()));
|
||||
|
||||
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 +206,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)
|
||||
@ -214,38 +235,41 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
labelPtr = 0;
|
||||
|
||||
if (!_huffmanTable.isNull()) {
|
||||
pos = QPoint((subdiv->lon()<<8) + ((qint32)lon<<(32-subdiv->bits())),
|
||||
(subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits())));
|
||||
pos = QPoint(LS(subdiv->lon(), 8) + LS(lon, 32-subdiv->bits()),
|
||||
LS(subdiv->lat(), 8) + LS(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))
|
||||
return false;
|
||||
pos = QPoint(pos.x() | lonDelta<<(32-subdiv->bits()-shift),
|
||||
pos.y() | latDelta<<(32-subdiv->bits()-shift));
|
||||
pos = QPoint(pos.x() | LS(lonDelta, 32-subdiv->bits()-shift),
|
||||
pos.y() | LS(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)) {
|
||||
pos.rx() += lonDelta<<(32-subdiv->bits()-shift);
|
||||
pos.ry() += latDelta<<(32-subdiv->bits()-shift);
|
||||
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
|
||||
if (pos.rx() < 0 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffffff;
|
||||
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
|
||||
|
||||
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()))
|
||||
return false;
|
||||
} else {
|
||||
pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
pos = QPoint(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(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;
|
||||
@ -256,12 +280,14 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
DeltaStream stream(*this, hdl, len - 1, bitstreamInfo, false, true);
|
||||
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
pos.rx() += LS(lonDelta, 24-subdiv->bits());
|
||||
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffff;
|
||||
pos.ry() += LS(latDelta, 24-subdiv->bits());
|
||||
|
||||
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 +297,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,19 +310,23 @@ 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;
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
|
||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
@ -310,22 +337,17 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
} else
|
||||
subtype = 0;
|
||||
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
|
||||
point.type = (quint16)type<<8 | subtype;
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
|
||||
if (!rect.contains(point.coordinates))
|
||||
continue;
|
||||
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
point.poi = labelPtr & 0x400000;
|
||||
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);
|
||||
}
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi,
|
||||
!(point.type == 0x1400 || point.type == 0x1500
|
||||
|| point.type == 0x1e00));
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
@ -333,48 +355,47 @@ 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;
|
||||
qint16 lon, lat;
|
||||
quint8 type, subtype;
|
||||
quint32 labelPtr = 0;
|
||||
|
||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
labelPtr = 0;
|
||||
|
||||
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
|
||||
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))
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
subdiv->lat() + LS(lat, 24-subdiv->bits()));
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
// Discard NT points breaking style draw order logic (and causing huge
|
||||
// performance drawback)
|
||||
if (point.type == 0x11400)
|
||||
continue;
|
||||
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
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 +403,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 +419,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) {
|
||||
for (quint8 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
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include "style.h"
|
||||
|
||||
|
||||
@ -79,13 +80,19 @@ void Style::defaultPolygonStyle()
|
||||
<< TYPE(0x13);
|
||||
}
|
||||
|
||||
static QImage railroad()
|
||||
{
|
||||
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(QColor("#717171"));
|
||||
QPainter p(&img);
|
||||
p.setPen(QPen(Qt::white, 2));
|
||||
p.drawLine(9, 2, 15, 2);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void Style::defaultLineStyle()
|
||||
{
|
||||
QVector<qreal> pattern;
|
||||
pattern << 4 << 4;
|
||||
QPen rr(QColor("#717171"), 3, Qt::CustomDashLine);
|
||||
rr.setDashPattern(pattern);
|
||||
|
||||
_lines[TYPE(0x01)] = Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#72a35a"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x02)] = Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
@ -109,13 +116,13 @@ void Style::defaultLineStyle()
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x0c)] = Line(QPen(QColor("#ffffff"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x14)] = Line(rr, QPen(Qt::white, 3, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x14)] = Line(railroad());
|
||||
_lines[TYPE(0x16)] = Line(QPen(QColor("#aba083"), 1, Qt::DotLine));
|
||||
_lines[TYPE(0x18)] = Line(QPen(QColor("#9fc4e1"), 2, Qt::SolidLine));
|
||||
_lines[TYPE(0x18)].setTextColor(QColor("#9fc4e1"));
|
||||
//_lines[TYPE(0x1a)] = Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1b)] = Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1c)] = Line(QPen(QColor("#505145"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1e)] = Line(QPen(QColor("#505145"), 2, Qt::DashDotLine));
|
||||
_lines[TYPE(0x1f)] = Line(QPen(QColor("#9fc4e1"), 3, Qt::SolidLine));
|
||||
_lines[TYPE(0x1f)].setTextColor(QColor("#9fc4e1"));
|
||||
@ -145,6 +152,17 @@ void Style::defaultLineStyle()
|
||||
|
||||
void Style::defaultPointStyle()
|
||||
{
|
||||
// Countries
|
||||
_points[TYPE(0x14)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x14)].setTextFontSize(Small);
|
||||
_points[TYPE(0x15)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x15)].setTextFontSize(Small);
|
||||
|
||||
// Regions
|
||||
_points[TYPE(0x1e)].setTextColor(QColor("#505145"));
|
||||
_points[TYPE(0x1e)].setTextFontSize(ExtraSmall);
|
||||
_points[TYPE(0x28)].setTextFontSize(Small);
|
||||
|
||||
// Cities
|
||||
_points[TYPE(0x01)].setTextFontSize(Large);
|
||||
_points[TYPE(0x02)].setTextFontSize(Large);
|
||||
@ -341,7 +359,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 +908,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 +957,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
|
||||
|
@ -16,7 +16,8 @@ public:
|
||||
None = 1,
|
||||
Small = 2,
|
||||
Normal = 3,
|
||||
Large = 4
|
||||
Large = 4,
|
||||
ExtraSmall = 5
|
||||
};
|
||||
|
||||
enum POIClass {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -2,36 +2,56 @@
|
||||
#define SUBFILE_H
|
||||
|
||||
#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 +117,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
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include "trefile.h"
|
||||
|
||||
|
||||
static inline double RB(qint32 val)
|
||||
{
|
||||
return (val == -0x800000 || val == 0x800000) ? 180.0 : toWGS24(val);
|
||||
}
|
||||
|
||||
static void demangle(quint8 *data, quint32 size, quint32 key)
|
||||
{
|
||||
static const unsigned char shuf[] = {
|
||||
@ -39,10 +44,11 @@ TREFile::~TREFile()
|
||||
|
||||
bool TREFile::init()
|
||||
{
|
||||
Handle hdl;
|
||||
Handle hdl(this);
|
||||
quint8 locked;
|
||||
quint16 hdrLen;
|
||||
|
||||
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||
&& seek(hdl, _gmpOffset + 0x0D) && readUInt8(hdl, locked)))
|
||||
return false;
|
||||
@ -53,7 +59,8 @@ bool TREFile::init()
|
||||
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
|
||||
return false;
|
||||
_bounds = RectC(Coordinates(toWGS24(west), toWGS24(north)),
|
||||
Coordinates(toWGS24(east), toWGS24(south)));
|
||||
Coordinates(RB(east), toWGS24(south)));
|
||||
Q_ASSERT(_bounds.left() <= _bounds.right());
|
||||
|
||||
// Levels & subdivs info
|
||||
quint32 levelsOffset, levelsSize, subdivSize;
|
||||
@ -108,12 +115,14 @@ bool TREFile::init()
|
||||
}
|
||||
}
|
||||
|
||||
_isBaseMap = false;
|
||||
|
||||
return (_firstLevel >= 0);
|
||||
}
|
||||
|
||||
bool TREFile::load(int idx)
|
||||
{
|
||||
Handle hdl;
|
||||
Handle hdl(this);
|
||||
QList<SubDiv*> sl;
|
||||
SubDiv *s = 0;
|
||||
SubDivTree *tree = new SubDivTree();
|
||||
@ -130,8 +139,8 @@ bool TREFile::load(int idx)
|
||||
|
||||
for (int j = 0; j < _levels.at(idx).subdivs; j++) {
|
||||
quint32 oo;
|
||||
qint32 lon, lat;
|
||||
quint16 width, height, nextLevel;
|
||||
qint32 lon, lat, width, height;
|
||||
quint16 nextLevel;
|
||||
|
||||
if (!(readUInt32(hdl, oo) && readInt24(hdl, lon) && readInt24(hdl, lat)
|
||||
&& readUInt16(hdl, width) && readUInt16(hdl, height)))
|
||||
@ -147,17 +156,16 @@ bool TREFile::load(int idx)
|
||||
s->setEnd(offset);
|
||||
|
||||
width &= 0x7FFF;
|
||||
width <<= (24 - _levels.at(idx).bits);
|
||||
height <<= (24 - _levels.at(idx).bits);
|
||||
|
||||
width = LS(width, 24 - _levels.at(idx).bits);
|
||||
height = LS(height, 24 - _levels.at(idx).bits);
|
||||
|
||||
s = new SubDiv(offset, lon, lat, _levels.at(idx).bits, objects);
|
||||
sl.append(s);
|
||||
|
||||
double min[2], max[2];
|
||||
RectC bounds(Coordinates(toWGS24(lon - width),
|
||||
toWGS24(lat + height + 1)), Coordinates(toWGS24(lon + width + 1),
|
||||
toWGS24(lat - height)));
|
||||
RectC bounds(Coordinates(toWGS24(lon - width), toWGS24(lat + height)),
|
||||
Coordinates(RB(lon + width), toWGS24(lat - height)));
|
||||
Q_ASSERT(bounds.left() <= bounds.right());
|
||||
|
||||
min[0] = bounds.left();
|
||||
min[1] = bounds.bottom();
|
||||
@ -199,7 +207,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,8 +244,15 @@ void TREFile::clear()
|
||||
_subdivs.clear();
|
||||
}
|
||||
|
||||
int TREFile::level(int bits)
|
||||
int TREFile::level(int bits, bool baseMap)
|
||||
{
|
||||
if (baseMap) {
|
||||
if (!_isBaseMap && _levels.first().bits > bits)
|
||||
return -1;
|
||||
if (_isBaseMap && bits > _levels.last().bits)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int idx = _firstLevel;
|
||||
|
||||
for (int i = idx + 1; i < _levels.size(); i++) {
|
||||
@ -259,10 +274,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();
|
||||
|
@ -14,16 +14,20 @@ 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();
|
||||
void markAsBasemap() {_isBaseMap = true;}
|
||||
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;}
|
||||
Range zooms() const
|
||||
{return Range(_levels.at(_firstLevel).bits, _levels.last().bits);}
|
||||
|
||||
private:
|
||||
struct MapLevel {
|
||||
@ -41,7 +45,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 +58,7 @@ private:
|
||||
Extended _extended;
|
||||
int _firstLevel;
|
||||
quint32 _flags;
|
||||
bool _isBaseMap;
|
||||
|
||||
QMap<int, SubDivTree*> _subdivs;
|
||||
};
|
||||
|
@ -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,6 +59,29 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (_gmp && !initGMP())
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef VECTORTILE_H
|
||||
#define VECTORTILE_H
|
||||
|
||||
#include "img.h"
|
||||
#include "trefile.h"
|
||||
#include "trefile.h"
|
||||
#include "rgnfile.h"
|
||||
@ -17,15 +16,22 @@ public:
|
||||
}
|
||||
|
||||
bool init();
|
||||
void markAsBasemap() {_tre->markAsBasemap();}
|
||||
void clear() {_tre->clear();}
|
||||
|
||||
const RectC &bounds() const {return _tre->bounds();}
|
||||
Range zooms() const {return _tre->zooms();}
|
||||
|
||||
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 +40,6 @@ public:
|
||||
|| type == SubFile::GMP);
|
||||
}
|
||||
|
||||
friend QDebug operator<<(QDebug dbg, const VectorTile &tile);
|
||||
|
||||
private:
|
||||
bool initGMP();
|
||||
|
||||
|
@ -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,14 +73,12 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
static const Range zooms(12, 28);
|
||||
|
||||
static const QColor shieldColor(Qt::white);
|
||||
static const QColor shieldBgColor1("#dd3e3e");
|
||||
static const QColor shieldBgColor2("#379947");
|
||||
@ -126,6 +127,7 @@ static QFont *font(Style::FontSize size, Style::FontSize defaultSize
|
||||
static QFont large = pixelSizeFont(16);
|
||||
static QFont normal = pixelSizeFont(14);
|
||||
static QFont small = pixelSizeFont(12);
|
||||
static QFont extraSmall = pixelSizeFont(10);
|
||||
|
||||
switch (size) {
|
||||
case Style::None:
|
||||
@ -136,6 +138,8 @@ static QFont *font(Style::FontSize size, Style::FontSize defaultSize
|
||||
return &normal;
|
||||
case Style::Small:
|
||||
return &small;
|
||||
case Style::ExtraSmall:
|
||||
return &extraSmall;
|
||||
default:
|
||||
return font(defaultSize);
|
||||
}
|
||||
@ -201,25 +205,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,15 +230,21 @@ 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;
|
||||
}
|
||||
|
||||
_zoom = zooms.min();
|
||||
_zoom = _data->zooms().min();
|
||||
updateTransform();
|
||||
|
||||
_valid = true;
|
||||
@ -247,17 +252,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()));
|
||||
}
|
||||
@ -267,8 +272,8 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
if (rect.isValid()) {
|
||||
RectD pr(rect, _projection, 10);
|
||||
|
||||
_zoom = zooms.min();
|
||||
for (int i = zooms.min() + 1; i <= zooms.max(); i++) {
|
||||
_zoom = _data->zooms().min();
|
||||
for (int i = _data->zooms().min() + 1; i <= _data->zooms().max(); i++) {
|
||||
Transform t(transform(i));
|
||||
QRectF r(t.proj2img(pr.topLeft()), t.proj2img(pr.bottomRight()));
|
||||
if (size.width() < r.width() || size.height() < r.height())
|
||||
@ -276,7 +281,7 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
_zoom = i;
|
||||
}
|
||||
} else
|
||||
_zoom = zooms.max();
|
||||
_zoom = _data->zooms().max();
|
||||
|
||||
updateTransform();
|
||||
|
||||
@ -285,14 +290,14 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
|
||||
int IMGMap::zoomIn()
|
||||
{
|
||||
_zoom = qMin(_zoom + 1, zooms.max());
|
||||
_zoom = qMin(_zoom + 1, _data->zooms().max());
|
||||
updateTransform();
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
int IMGMap::zoomOut()
|
||||
{
|
||||
_zoom = qMax(_zoom - 1, zooms.min());
|
||||
_zoom = qMax(_zoom - 1, _data->zooms().min());
|
||||
updateTransform();
|
||||
return _zoom;
|
||||
}
|
||||
@ -307,7 +312,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 +332,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 +348,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 +364,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 +382,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 +398,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 +411,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 +429,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 +458,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 +469,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 +522,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 +583,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);
|
||||
@ -588,15 +591,22 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
tiles.append(RasterTile(this, ttl, key));
|
||||
RasterTile &tile = tiles.last();
|
||||
|
||||
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);
|
||||
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()));
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE,
|
||||
ttl.y() + TILE_SIZE));
|
||||
polyRect &= bounds().adjusted(0.5, 0.5, -0.5, -0.5);
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
_data->polys(polyRectD.toRectC(_projection, 4), _zoom,
|
||||
&(tile.polygons()), &(tile.lines()));
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE
|
||||
+ TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT));
|
||||
pointRect &= bounds().adjusted(0.5, 0.5, -0.5, -0.5);
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data->points(pointRectD.toRectC(_projection, 4), _zoom,
|
||||
&(tile.points()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -8,51 +8,52 @@
|
||||
#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 (dir)
|
||||
_errorString += path + ": " + map->errorString() + "\n";
|
||||
else
|
||||
_errorString = map->errorString();
|
||||
_errorPath = path;
|
||||
_errorString = (map) ? map->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, this);
|
||||
}
|
||||
} else if (suffix == "jnx")
|
||||
map = new JNXMap(path, this);
|
||||
else if (suffix == "tif" || suffix == "tiff")
|
||||
@ -63,10 +64,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 +75,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 +86,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 +102,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 +119,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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -286,7 +300,7 @@ Map *MapSource::loadMap(const QString &path, QString &errorString)
|
||||
case WMS:
|
||||
return new WMSMap(config.name, WMS::Setup(config.url, config.layer,
|
||||
config.style, config.format, config.crs, config.coordinateSystem,
|
||||
config.dimensions, config.authorization));
|
||||
config.dimensions, config.authorization), config.tileSize);
|
||||
case TMS:
|
||||
return new OnlineMap(config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
|
@ -15,6 +15,7 @@ class MapSource
|
||||
{
|
||||
public:
|
||||
static Map *loadMap(const QString &path, QString &errorString);
|
||||
static bool isMap(const QString &path);
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
|
@ -169,6 +169,17 @@ void TileLoader::clearCache()
|
||||
dir.remove(list.at(i));
|
||||
|
||||
_downloader->clearErrors();
|
||||
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void TileLoader::setScaledSize(int size)
|
||||
{
|
||||
if (_scaledSize == size)
|
||||
return;
|
||||
|
||||
_scaledSize = size;
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
QUrl TileLoader::tileUrl(const Tile &tile) const
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
void setUrl(const QString &url) {_url = url;}
|
||||
void setAuthorization(const Authorization &authorization)
|
||||
{_authorization = authorization;}
|
||||
void setScaledSize(int size) {_scaledSize = size;}
|
||||
void setScaledSize(int size);
|
||||
void setQuadTiles(bool quadTiles) {_quadTiles = quadTiles;}
|
||||
|
||||
void loadTilesAsync(QVector<Tile> &list);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <cmath>
|
||||
#include <QFileInfo>
|
||||
#include <QEventLoop>
|
||||
#include <QXmlStreamReader>
|
||||
@ -7,6 +8,19 @@
|
||||
#include "wms.h"
|
||||
|
||||
|
||||
static QString bareFormat(const QString &format)
|
||||
{
|
||||
return format.left(format.indexOf(';')).trimmed();
|
||||
}
|
||||
|
||||
static inline double hint2denominator(double h)
|
||||
{
|
||||
/* Some WMS 1.1.1 servers use a 72dpi resolution by default. Using the usual
|
||||
90dpi (0.28mm) resolution known from later standards (WMS 1.3, WMTS) does
|
||||
make them return emty images in the "max" scale level. */
|
||||
return h / (M_SQRT2 * 0.36e-3);
|
||||
}
|
||||
|
||||
WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
|
||||
{
|
||||
QStringList ll = setup.layer().split(',');
|
||||
@ -24,13 +38,48 @@ WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
|
||||
}
|
||||
}
|
||||
|
||||
void WMS::get(QXmlStreamReader &reader, CTX &ctx)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "OnlineResource") {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
ctx.url = attr.value("xlink:href").toString();
|
||||
reader.skipCurrentElement();
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void WMS::http(QXmlStreamReader &reader, CTX &ctx)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Get")
|
||||
get(reader, ctx);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void WMS::dcpType(QXmlStreamReader &reader, CTX &ctx)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "HTTP")
|
||||
http(reader, ctx);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void WMS::getMap(QXmlStreamReader &reader, CTX &ctx)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Format") {
|
||||
if (reader.readElementText() == ctx.setup.format())
|
||||
QString format(reader.readElementText());
|
||||
if (bareFormat(format) == bareFormat(ctx.setup.format()))
|
||||
ctx.formatSupported = true;
|
||||
} else
|
||||
} else if (reader.name() == "DCPType")
|
||||
dcpType(reader, ctx);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -97,7 +146,16 @@ void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
|
||||
CRSs.append(reader.readElementText());
|
||||
else if (reader.name() == "Style")
|
||||
styles.append(style(reader));
|
||||
else if (reader.name() == "MinScaleDenominator") {
|
||||
else if (reader.name() == "ScaleHint") {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
double minHint = attr.value("min").toString().toDouble();
|
||||
double maxHint = attr.value("max").toString().toDouble();
|
||||
if (minHint > 0)
|
||||
scaleDenominator.setMin(hint2denominator(minHint));
|
||||
if (maxHint > 0)
|
||||
scaleDenominator.setMax(hint2denominator(maxHint));
|
||||
reader.skipCurrentElement();
|
||||
} else if (reader.name() == "MinScaleDenominator") {
|
||||
double sd = reader.readElementText().toDouble();
|
||||
if (sd > 0)
|
||||
scaleDenominator.setMin(sd);
|
||||
@ -248,6 +306,8 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
|
||||
return false;
|
||||
}
|
||||
|
||||
_tileUrl = ctx.url.isEmpty() ? setup.url() : ctx.url;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
const RangeF &scaleDenominator() const {return _scaleDenominator;}
|
||||
const RectC &boundingBox() const {return _boundingBox;}
|
||||
const QString &version() const {return _version;}
|
||||
const QString &tileUrl() const {return _tileUrl;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
@ -79,12 +80,16 @@ private:
|
||||
const Setup &setup;
|
||||
QList<Layer> layers;
|
||||
bool formatSupported;
|
||||
QString url;
|
||||
|
||||
CTX(const Setup &setup);
|
||||
};
|
||||
|
||||
RectC geographicBoundingBox(QXmlStreamReader &reader);
|
||||
QString style(QXmlStreamReader &reader);
|
||||
void get(QXmlStreamReader &reader, CTX &ctx);
|
||||
void http(QXmlStreamReader &reader, CTX &ctx);
|
||||
void dcpType(QXmlStreamReader &reader, CTX &ctx);
|
||||
void getMap(QXmlStreamReader &reader, CTX &ctx);
|
||||
void request(QXmlStreamReader &reader, CTX &ctx);
|
||||
void layer(QXmlStreamReader &reader, CTX &ctx, const QList<QString> &pCRSs,
|
||||
@ -100,6 +105,7 @@ private:
|
||||
RangeF _scaleDenominator;
|
||||
RectC _boundingBox;
|
||||
QString _version;
|
||||
QString _tileUrl;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
|
||||
#define CAPABILITIES_FILE "capabilities.xml"
|
||||
#define TILE_SIZE 256
|
||||
#define EPSILON 1e-6
|
||||
|
||||
double WMSMap::sd2res(double scaleDenominator) const
|
||||
@ -18,14 +17,14 @@ double WMSMap::sd2res(double scaleDenominator) const
|
||||
return scaleDenominator * 0.28e-3 * _projection.units().fromMeters(1.0);
|
||||
}
|
||||
|
||||
QString WMSMap::tileUrl(const QString &version) const
|
||||
QString WMSMap::tileUrl(const QString &baseUrl, const QString &version) const
|
||||
{
|
||||
QString url;
|
||||
|
||||
url = QString("%1%2version=%3&request=GetMap&bbox=$bbox"
|
||||
url = QString("%1%2service=WMS&version=%3&request=GetMap&bbox=$bbox"
|
||||
"&width=%4&height=%5&layers=%6&styles=%7&format=%8&transparent=true")
|
||||
.arg(_setup.url(), _setup.url().contains('?') ? "&" : "?", version,
|
||||
QString::number(TILE_SIZE), QString::number(TILE_SIZE), _setup.layer(),
|
||||
.arg(baseUrl, baseUrl.contains('?') ? "&" : "?", version,
|
||||
QString::number(_tileSize), QString::number(_tileSize), _setup.layer(),
|
||||
_setup.style(), _setup.format());
|
||||
|
||||
if (version >= "1.3.0")
|
||||
@ -84,7 +83,7 @@ bool WMSMap::loadWMS()
|
||||
_projection = wms.projection();
|
||||
_bbox = wms.boundingBox();
|
||||
_bounds = RectD(_bbox, _projection);
|
||||
_tileLoader->setUrl(tileUrl(wms.version()));
|
||||
_tileLoader->setUrl(tileUrl(wms.tileUrl(), wms.version()));
|
||||
|
||||
if (wms.version() >= "1.3.0") {
|
||||
if (_setup.coordinateSystem().axisOrder() == CoordinateSystem::Unknown)
|
||||
@ -100,9 +99,9 @@ bool WMSMap::loadWMS()
|
||||
return true;
|
||||
}
|
||||
|
||||
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent)
|
||||
: Map(parent), _name(name), _setup(setup), _tileLoader(0), _zoom(0),
|
||||
_mapRatio(1.0), _valid(false)
|
||||
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
|
||||
QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0),
|
||||
_zoom(0), _tileSize(tileSize), _mapRatio(1.0), _valid(false)
|
||||
{
|
||||
_tileLoader = new TileLoader(tilesDir(), this);
|
||||
_tileLoader->setAuthorization(_setup.authorization());
|
||||
@ -180,7 +179,7 @@ Coordinates WMSMap::xy2ll(const QPointF &p)
|
||||
|
||||
qreal WMSMap::tileSize() const
|
||||
{
|
||||
return (TILE_SIZE / _mapRatio);
|
||||
return (_tileSize / _mapRatio);
|
||||
}
|
||||
|
||||
void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
@ -194,10 +193,10 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
tiles.reserve((br.x() - tl.x()) * (br.y() - tl.y()));
|
||||
for (int i = tl.x(); i < br.x(); i++) {
|
||||
for (int j = tl.y(); j < br.y(); j++) {
|
||||
PointD ttl(_transform.img2proj(QPointF(i * TILE_SIZE,
|
||||
j * TILE_SIZE)));
|
||||
PointD tbr(_transform.img2proj(QPointF(i * TILE_SIZE + TILE_SIZE,
|
||||
j * TILE_SIZE + TILE_SIZE)));
|
||||
PointD ttl(_transform.img2proj(QPointF(i * _tileSize,
|
||||
j * _tileSize)));
|
||||
PointD tbr(_transform.img2proj(QPointF(i * _tileSize + _tileSize,
|
||||
j * _tileSize + _tileSize)));
|
||||
RectD bbox = (_cs.axisOrder() == CoordinateSystem::YX)
|
||||
? RectD(PointD(tbr.y(), tbr.x()), PointD(ttl.y(), ttl.x()))
|
||||
: RectD(ttl, tbr);
|
||||
|
@ -14,7 +14,8 @@ class WMSMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent = 0);
|
||||
WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
|
||||
QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
@ -39,7 +40,7 @@ public:
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
QString tileUrl(const QString &version) const;
|
||||
QString tileUrl(const QString &baseUrl, const QString &version) const;
|
||||
double sd2res(double scaleDenominator) const;
|
||||
QString tilesDir() const;
|
||||
void computeZooms(const RangeF &scaleDenominator);
|
||||
@ -58,6 +59,7 @@ private:
|
||||
RectC _bbox;
|
||||
RectD _bounds;
|
||||
int _zoom;
|
||||
int _tileSize;
|
||||
qreal _mapRatio;
|
||||
|
||||
bool _valid;
|
||||
|
@ -12,6 +12,11 @@
|
||||
#include "wmts.h"
|
||||
|
||||
|
||||
static QString bareFormat(const QString &format)
|
||||
{
|
||||
return format.left(format.indexOf(';')).trimmed();
|
||||
}
|
||||
|
||||
static void skipParentElement(QXmlStreamReader &reader)
|
||||
{
|
||||
while (reader.readNextStartElement())
|
||||
@ -182,7 +187,8 @@ void WMTS::layer(QXmlStreamReader &reader, CTX &ctx)
|
||||
if (s == ctx.setup.style())
|
||||
ctx.hasStyle = true;
|
||||
} else if (reader.name() == "Format") {
|
||||
if (reader.readElementText() == ctx.setup.format())
|
||||
QString format(reader.readElementText());
|
||||
if (bareFormat(format) == bareFormat(ctx.setup.format()))
|
||||
ctx.hasFormat = true;
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
|
Reference in New Issue
Block a user