Compare commits
61 Commits
12.2
...
52ea52ff4e
Author | SHA1 | Date | |
---|---|---|---|
52ea52ff4e | |||
b6ca28e159 | |||
648627b17f | |||
2aa759a4bc | |||
84dc58da71 | |||
25838ad02d | |||
d11483cd94 | |||
6cd122f59b | |||
981bd33680 | |||
2697507c3a | |||
8b24aa17e2 | |||
6fc5a2f67d | |||
d794de5818 | |||
81f695a672 | |||
9580ddd54a | |||
20aaf68405 | |||
cdc0a64ead | |||
f2218126ef | |||
14670868bb | |||
6a73b6358d | |||
7e89f339f4 | |||
9e80319577 | |||
0596201fb2 | |||
dce078bca6 | |||
34f935462f | |||
84a592998d | |||
c114383c85 | |||
ab2f8d8350 | |||
164e59602e | |||
1b858ac4f2 | |||
0a58808017 | |||
b80cd05d4b | |||
66c951f38c | |||
46109d0ce0 | |||
cd1f80f2c1 | |||
02699b0636 | |||
bb8727755a | |||
69831f0c90 | |||
dbe407d9d9 | |||
b78d4741f6 | |||
405b1397e9 | |||
2f280c744b | |||
54d6016b1a | |||
65afd802ce | |||
e6b96d8717 | |||
f057ebdbb7 | |||
f941dce573 | |||
416bd3472f | |||
034a9d9b28 | |||
048198dfe1 | |||
a50fa28c08 | |||
152f17f15a | |||
873db27768 | |||
62f3343f75 | |||
07581f027b | |||
b3767e85e1 | |||
4fdeb3169f | |||
18836107af | |||
630fef2143 | |||
00c8d70eab | |||
426490ef4d |
@ -1,4 +1,4 @@
|
||||
version: 12.2.{build}
|
||||
version: 12.4.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
2
.github/workflows/android.yml
vendored
@ -28,12 +28,10 @@ jobs:
|
||||
- name: Install Qt (Desktop)
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
aqtversion: '==2.1.0'
|
||||
version: '6.4.0'
|
||||
- name: Install Qt (Android)
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
aqtversion: '==2.1.0'
|
||||
version: '6.4.0'
|
||||
target: 'android'
|
||||
arch: 'android_armv7'
|
||||
|
25
.github/workflows/osx.yml
vendored
@ -10,14 +10,12 @@ jobs:
|
||||
name: GPXSee Qt5 build
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Set environment variables
|
||||
run: echo "PATH=/usr/local/opt/qt@5/bin:$PATH" >> $GITHUB_ENV
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew update
|
||||
brew install qt5
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '5.15.2'
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
- name: Configure build
|
||||
@ -25,7 +23,7 @@ jobs:
|
||||
- name: Build project
|
||||
run: make -j3
|
||||
- name: Create DMG
|
||||
run: macdeployqt GPXSee.app -dmg
|
||||
run: macdeployqt GPXSee.app -dmg -appstore-compliant
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@ -36,14 +34,13 @@ jobs:
|
||||
name: GPXSee Qt6 build
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Set environment variables
|
||||
run: echo "PATH=/usr/local/opt/qt@6/bin:$PATH" >> $GITHUB_ENV
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew update
|
||||
brew install qt6
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.4.3'
|
||||
modules: qtpositioning qt5compat qtserialport
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
- name: Configure build
|
||||
@ -51,7 +48,7 @@ jobs:
|
||||
- name: Build project
|
||||
run: make -j3
|
||||
- name: Create DMG
|
||||
run: macdeployqt GPXSee.app -dmg
|
||||
run: macdeployqt GPXSee.app -dmg -appstore-compliant
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
@ -345,6 +345,7 @@ FEH2010,5593,1078,9122,7019,8901,9603,0,0,0,,,,
|
||||
CIGD11,6135,1100,9122,7019,8901,9603,0,0,0,,,,
|
||||
Nepal 1981,6207,1111,9122,7015,8901,9603,293.17,726.18,245.36,,,,
|
||||
CGRS93,6311,1112,9122,7030,8901,9607,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926
|
||||
NAD83(2011),6318,1116,9122,7019,8901,9603,0,0,0,,,,
|
||||
Mexico ITRF2008,6365,1120,9122,7019,8901,9603,0,0,0,,,,
|
||||
RDN2008,6706,1132,9122,7019,8901,9603,0,0,0,,,,
|
||||
Aden 1925,6881,1135,9122,7012,8901,9603,-24,-203,268,,,,
|
||||
|
|
@ -2071,6 +2071,28 @@ SIRGAS 2000 / UTM zone 23N,6210,4674,16023,9001,9807,4400,8801,0,9102,8802,-45,9
|
||||
SIRGAS 2000 / UTM zone 24N,6211,4674,16024,9001,9807,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
CGRS93 / Cyprus Local Transverse Mercator,6312,6311,6308,9001,9807,4400,8801,0,9102,8802,33,9102,8805,0.99995,9201,8806,200000,9001,8807,-3500000,9001,,,,,,
|
||||
Macedonia State Coordinate System zone 7,6316,3906,18277,9001,9807,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 59N,6328,6318,16059,9001,9807,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 60N,6329,6318,16060,9001,9807,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 1N,6330,6318,16001,9001,9807,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 2N,6331,6318,16002,9001,9807,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 3N,6332,6318,16003,9001,9807,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 4N,6333,6318,16004,9001,9807,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 5N,6334,6318,16005,9001,9807,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 6N,6335,6318,16006,9001,9807,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 7N,6336,6318,16007,9001,9807,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 8N,6337,6318,16008,9001,9807,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 9N,6338,6318,16009,9001,9807,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 10N,6339,6318,16010,9001,9807,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 11N,6340,6318,16011,9001,9807,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 12N,6341,6318,16012,9001,9807,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 13N,6342,6318,16013,9001,9807,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 14N,6343,6318,16014,9001,9807,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 15N,6344,6318,16015,9001,9807,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 16N,6345,6318,16016,9001,9807,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 17N,6346,6318,16017,9001,9807,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 18N,6347,6318,16018,9001,9807,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / UTM zone 19N,6348,6318,16019,9001,9807,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
NAD83(2011) / Conus Albers,6350,6318,5068,9001,9822,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
|
||||
Mexico ITRF92 / LCC,6362,4483,6361,9001,9802,4500,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,
|
||||
Mexico ITRF2008 / UTM zone 11N,6366,6365,16011,9001,9807,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
Mexico ITRF2008 / UTM zone 12N,6367,6365,16012,9001,9807,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
|
Can't render this file because it is too large.
|
@ -3,7 +3,7 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 12.2
|
||||
VERSION = 12.4
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
|
@ -194,6 +194,10 @@
|
||||
<file alias="breakers.png">icons/map/marine/breakers.png</file>
|
||||
<file alias="overfalls.png">icons/map/marine/overfalls.png</file>
|
||||
<file alias="boarding-place.png">icons/map/marine/boarding-place.png</file>
|
||||
<file alias="light.png">icons/map/marine/light.png</file>
|
||||
<file alias="building.png">icons/map/marine/building.png</file>
|
||||
<file alias="fog-signal.png">icons/map/marine/fog-signal.png</file>
|
||||
<file alias="construction.png">icons/map/marine/construction.png</file>
|
||||
</qresource>
|
||||
|
||||
<!-- Mapsforge rendertheme -->
|
||||
|
BIN
icons/map/marine/building.png
Normal file
After Width: | Height: | Size: 108 B |
BIN
icons/map/marine/construction.png
Normal file
After Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 147 B |
BIN
icons/map/marine/fog-signal.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
icons/map/marine/light.png
Normal file
After Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 288 B |
@ -1020,6 +1020,7 @@
|
||||
<translation>
|
||||
<numerusform>%n fitxer</numerusform>
|
||||
<numerusform>%n fitxers</numerusform>
|
||||
<numerusform>%n fitxers</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -30,7 +30,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/cadencegraph.cpp" line="28"/>
|
||||
<source>Avg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mez</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/cadencegraph.cpp" line="30"/>
|
||||
@ -1156,7 +1156,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/heartrategraph.cpp" line="28"/>
|
||||
<source>Avg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mez</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/heartrategraph.cpp" line="30"/>
|
||||
@ -1912,7 +1912,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>DEM-kaŝmemora grandeco:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
@ -2157,7 +2157,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/powergraph.cpp" line="28"/>
|
||||
<source>Avg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mez</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/powergraph.cpp" line="30"/>
|
||||
@ -2277,7 +2277,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/speedgraph.cpp" line="35"/>
|
||||
<source>Avg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mez</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/speedgraph.cpp" line="37"/>
|
||||
@ -2374,7 +2374,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/temperaturegraph.cpp" line="28"/>
|
||||
<source>Avg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mez</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/temperaturegraph.cpp" line="30"/>
|
||||
|
@ -791,7 +791,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="963"/>
|
||||
<source>Open directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Avaa hakemisto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="1215"/>
|
||||
@ -1790,7 +1790,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="577"/>
|
||||
<source>Use $lat and $lon for NYY/SYY and EXXX/WXXX in the URL.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Käytä $lat ja $lon kohdissa NYY/SYY ja EXXX/WXXX URL-osoitteessa.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="582"/>
|
||||
@ -1912,7 +1912,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>DEM-välimuistin koko:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
|
@ -1894,7 +1894,7 @@
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="741"/>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="748"/>
|
||||
<source>Image cache size:</source>
|
||||
<translation>Bildehurtiglagringstørrelse:</translation>
|
||||
<translation>Bildehurtiglagerstørrelse:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="742"/>
|
||||
@ -1912,7 +1912,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>DEM-hurtiglagerstørrelse:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
|
@ -1913,7 +1913,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Размер кэша DEM:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
|
@ -1913,7 +1913,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Розмір кешу DEM:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
|
@ -1911,7 +1911,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="749"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>DEM 缓存大小:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="769"/>
|
||||
|
@ -37,7 +37,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "12.2"
|
||||
!define VERSION "12.4"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QLibraryInfo>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QImageReader>
|
||||
#include <QFileInfo>
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <QCoreApplication>
|
||||
#include <QJniObject>
|
||||
@ -154,10 +155,13 @@ void App::loadDatums()
|
||||
QString ellipsoidsFile(ProgramPaths::ellipsoidsFile());
|
||||
QString gcsFile(ProgramPaths::gcsFile());
|
||||
|
||||
if (ellipsoidsFile.isNull())
|
||||
if (!QFileInfo::exists(ellipsoidsFile)) {
|
||||
qWarning("No ellipsoids file found.");
|
||||
if (gcsFile.isNull())
|
||||
ellipsoidsFile = QString();
|
||||
} if (!QFileInfo::exists(gcsFile)) {
|
||||
qWarning("No GCS file found.");
|
||||
gcsFile = QString();
|
||||
}
|
||||
|
||||
if (!ellipsoidsFile.isNull() && !gcsFile.isNull()) {
|
||||
Ellipsoid::loadList(ellipsoidsFile);
|
||||
@ -170,8 +174,9 @@ void App::loadPCSs()
|
||||
{
|
||||
QString pcsFile(ProgramPaths::pcsFile());
|
||||
|
||||
if (pcsFile.isNull())
|
||||
if (!QFileInfo::exists(pcsFile)) {
|
||||
qWarning("No PCS file found.");
|
||||
else
|
||||
qWarning("Maps based on a projection different from EPSG:3857 won't work.");
|
||||
} else
|
||||
PCS::loadList(pcsFile);
|
||||
}
|
||||
|
@ -137,11 +137,8 @@ TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node)
|
||||
MapAction *a = new MapAction(map, _mapsActionGroup);
|
||||
connect(a, &MapAction::loaded, this, &GUI::mapInitialized);
|
||||
tree.addItem(a);
|
||||
} else {
|
||||
qWarning("%s: %s", qPrintable(map->path()),
|
||||
qPrintable(map->errorString()));
|
||||
} else
|
||||
delete map;
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "pluginparameters.h"
|
||||
|
||||
static const QMap<QString, QStringList> pluginParams = {
|
||||
{"nmea", {"nmea.source"}},
|
||||
{"nmea", {"nmea.source", "nmea.baudrate"}},
|
||||
{"serialnmea", {"serialnmea.serial_port"}},
|
||||
{"geoclue2", {"desktopId"}}
|
||||
};
|
||||
|
@ -38,6 +38,15 @@ inline bool operator==(const Coordinates &c1, const Coordinates &c2)
|
||||
{return (c1.lat() == c2.lat() && c1.lon() == c2.lon());}
|
||||
inline bool operator!=(const Coordinates &c1, const Coordinates &c2)
|
||||
{return !(c1 == c2);}
|
||||
inline bool operator<(const Coordinates &c1, const Coordinates &c2)
|
||||
{
|
||||
if (c1.lon() < c2.lon())
|
||||
return true;
|
||||
else if (c1.lon() > c2.lon())
|
||||
return false;
|
||||
else
|
||||
return (c1.lat() < c2.lat());
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c);
|
||||
|
@ -15,9 +15,10 @@ public:
|
||||
bool operator!=(const Range &other) const
|
||||
{return _min != other._min || _max != other._max;}
|
||||
|
||||
int size() const {return (_max - _min);}
|
||||
int min() const {return _min;}
|
||||
int max() const {return _max;}
|
||||
int size() const {return (_max - _min);}
|
||||
int mid() const {return _min + size()/2;}
|
||||
|
||||
bool isValid() const {return size() >= 0;}
|
||||
bool isNull() const {return _min == 0 && _max == 0;}
|
||||
|
@ -88,6 +88,24 @@ static GraphSegment filter(const GraphSegment &g, int window)
|
||||
}
|
||||
|
||||
|
||||
qreal Track::lastDistance(int seg)
|
||||
{
|
||||
for (int i = seg - 1; i >= 0; i--)
|
||||
if (!_segments.at(i).distance.isEmpty())
|
||||
return _segments.at(i).distance.last();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qreal Track::lastTime(int seg)
|
||||
{
|
||||
for (int i = seg - 1; i >= 0; i--)
|
||||
if (!_segments.at(i).time.isEmpty())
|
||||
return _segments.at(i).time.last();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Track::Track(const TrackData &data) : _pause(0)
|
||||
{
|
||||
qreal ds, dt;
|
||||
@ -113,11 +131,8 @@ Track::Track(const TrackData &data) : _pause(0)
|
||||
|
||||
Segment &seg = _segments.last();
|
||||
|
||||
seg.distance.append(i && !_segments.at(i-1).distance.isEmpty()
|
||||
? _segments.at(i-1).distance.last() : 0);
|
||||
seg.time.append(i && !_segments.at(i-1).time.isEmpty()
|
||||
? _segments.at(i-1).time.last() :
|
||||
sd.first().hasTimestamp() ? 0 : NAN);
|
||||
seg.distance.append(lastDistance(i));
|
||||
seg.time.append(sd.first().hasTimestamp() ? lastTime(i) : NAN);
|
||||
seg.speed.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||
acceleration.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||
bool hasTime = !std::isnan(seg.time.first());
|
||||
|
@ -63,6 +63,8 @@ private:
|
||||
QSet<int> stop;
|
||||
};
|
||||
|
||||
qreal lastDistance(int seg);
|
||||
qreal lastTime(int seg);
|
||||
bool discardStopPoint(const Segment &seg, int i) const;
|
||||
|
||||
Graph demElevation() const;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define CATWAT 69
|
||||
#define CATWRK 71
|
||||
#define COMCHA 77
|
||||
#define CURVEL 84
|
||||
#define DRVAL1 87
|
||||
#define ELEVAT 90
|
||||
#define FUNCTN 94
|
||||
|
@ -19,55 +19,60 @@ static QMap<uint,uint> orderMapInit()
|
||||
{
|
||||
QMap<uint,uint> map;
|
||||
|
||||
map.insert(TYPE(CGUSTA), 0);
|
||||
map.insert(SUBTYPE(BUAARE, 1), 1);
|
||||
map.insert(SUBTYPE(BUAARE, 5), 2);
|
||||
map.insert(SUBTYPE(BUAARE, 4), 3);
|
||||
map.insert(SUBTYPE(BUAARE, 3), 4);
|
||||
map.insert(SUBTYPE(BUAARE, 2), 5);
|
||||
map.insert(SUBTYPE(BUAARE, 6), 6);
|
||||
map.insert(SUBTYPE(BUAARE, 0), 7);
|
||||
map.insert(TYPE(RDOSTA), 8);
|
||||
map.insert(TYPE(RADSTA), 9);
|
||||
map.insert(TYPE(RTPBCN), 10);
|
||||
map.insert(TYPE(BCNISD), 11);
|
||||
map.insert(TYPE(BCNLAT), 12);
|
||||
map.insert(TYPE(I_BCNLAT), 12);
|
||||
map.insert(TYPE(BCNSAW), 13);
|
||||
map.insert(TYPE(BCNSPP), 14);
|
||||
map.insert(TYPE(BOYCAR), 15);
|
||||
map.insert(TYPE(BOYINB), 16);
|
||||
map.insert(TYPE(BOYISD), 17);
|
||||
map.insert(TYPE(BOYLAT), 18);
|
||||
map.insert(TYPE(I_BOYLAT), 18);
|
||||
map.insert(TYPE(BOYSAW), 19);
|
||||
map.insert(TYPE(BOYSPP), 20);
|
||||
map.insert(TYPE(MORFAC), 21);
|
||||
map.insert(TYPE(OFSPLF), 22);
|
||||
map.insert(TYPE(LIGHTS), 23);
|
||||
map.insert(TYPE(LIGHTS), 0);
|
||||
map.insert(TYPE(FOGSIG), 0);
|
||||
|
||||
map.insert(TYPE(CGUSTA), 1);
|
||||
map.insert(SUBTYPE(BUAARE, 1), 2);
|
||||
map.insert(SUBTYPE(BUAARE, 5), 3);
|
||||
map.insert(SUBTYPE(BUAARE, 4), 4);
|
||||
map.insert(SUBTYPE(BUAARE, 3), 5);
|
||||
map.insert(SUBTYPE(BUAARE, 2), 6);
|
||||
map.insert(SUBTYPE(BUAARE, 6), 7);
|
||||
map.insert(SUBTYPE(BUAARE, 0), 8);
|
||||
map.insert(TYPE(RDOSTA), 9);
|
||||
map.insert(TYPE(RADSTA), 10);
|
||||
map.insert(TYPE(RTPBCN), 11);
|
||||
map.insert(TYPE(BCNISD), 12);
|
||||
map.insert(TYPE(BCNLAT), 13);
|
||||
map.insert(TYPE(I_BCNLAT), 13);
|
||||
map.insert(TYPE(BCNSAW), 14);
|
||||
map.insert(TYPE(BCNSPP), 15);
|
||||
map.insert(TYPE(BOYCAR), 16);
|
||||
map.insert(TYPE(BOYINB), 17);
|
||||
map.insert(TYPE(BOYISD), 18);
|
||||
map.insert(TYPE(BOYLAT), 19);
|
||||
map.insert(TYPE(I_BOYLAT), 19);
|
||||
map.insert(TYPE(BOYSAW), 20);
|
||||
map.insert(TYPE(BOYSPP), 21);
|
||||
map.insert(TYPE(MORFAC), 22);
|
||||
map.insert(TYPE(OFSPLF), 23);
|
||||
map.insert(TYPE(OBSTRN), 24);
|
||||
map.insert(TYPE(WRECKS), 25);
|
||||
map.insert(TYPE(UWTROC), 26);
|
||||
map.insert(TYPE(WATTUR), 27);
|
||||
map.insert(TYPE(PILBOP), 28);
|
||||
map.insert(TYPE(SISTAT), 29);
|
||||
map.insert(TYPE(I_SISTAT), 29);
|
||||
map.insert(TYPE(I_RDOCAL), 30);
|
||||
map.insert(TYPE(I_TRNBSN), 31);
|
||||
map.insert(TYPE(HRBFAC), 32);
|
||||
map.insert(TYPE(I_HRBFAC), 32);
|
||||
map.insert(TYPE(PILPNT), 33);
|
||||
map.insert(TYPE(ACHBRT), 34);
|
||||
map.insert(TYPE(I_ACHBRT), 34);
|
||||
map.insert(TYPE(CRANES), 35);
|
||||
map.insert(TYPE(I_CRANES), 35);
|
||||
map.insert(TYPE(I_WTWGAG), 36);
|
||||
map.insert(TYPE(PYLONS), 37);
|
||||
map.insert(TYPE(LNDMRK), 38);
|
||||
map.insert(TYPE(SILTNK), 39);
|
||||
map.insert(TYPE(LNDELV), 40);
|
||||
map.insert(TYPE(SMCFAC), 41);
|
||||
map.insert(TYPE(BUISGL), 42);
|
||||
map.insert(TYPE(CURENT), 28);
|
||||
map.insert(TYPE(PILBOP), 29);
|
||||
map.insert(TYPE(SISTAT), 30);
|
||||
map.insert(TYPE(I_SISTAT), 30);
|
||||
map.insert(TYPE(RDOCAL), 31);
|
||||
map.insert(TYPE(I_RDOCAL), 31);
|
||||
map.insert(TYPE(I_TRNBSN), 32);
|
||||
map.insert(TYPE(HRBFAC), 33);
|
||||
map.insert(TYPE(I_HRBFAC), 33);
|
||||
map.insert(TYPE(PILPNT), 34);
|
||||
map.insert(TYPE(ACHBRT), 35);
|
||||
map.insert(TYPE(I_ACHBRT), 35);
|
||||
map.insert(TYPE(CRANES), 36);
|
||||
map.insert(TYPE(I_CRANES), 36);
|
||||
map.insert(TYPE(I_WTWGAG), 37);
|
||||
map.insert(TYPE(PYLONS), 38);
|
||||
map.insert(TYPE(SLCONS), 39);
|
||||
map.insert(TYPE(LNDMRK), 40);
|
||||
map.insert(TYPE(SILTNK), 41);
|
||||
map.insert(TYPE(LNDELV), 42);
|
||||
map.insert(TYPE(SMCFAC), 43);
|
||||
map.insert(TYPE(BUISGL), 44);
|
||||
|
||||
map.insert(TYPE(I_DISMAR), 0xFFFFFFFE);
|
||||
map.insert(TYPE(SOUNDG), 0xFFFFFFFF);
|
||||
@ -246,10 +251,15 @@ MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
|
||||
if (type>>16 == I_DISMAR && params.size()) {
|
||||
_label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0));
|
||||
_type = SUBTYPE(I_DISMAR, type & 0xFF);
|
||||
} else if (type == TYPE(I_RDOCAL) && params.size() > 1) {
|
||||
} else if ((type>>16 == I_RDOCAL || type>>16 == RDOCAL) && params.size() > 1) {
|
||||
if (!params.at(1).isEmpty())
|
||||
_label = QString("VHF ") + QString::fromLatin1(params.at(1));
|
||||
_param = QVariant(params.at(0).toDouble());
|
||||
} else if (type>>16 == CURENT && params.size() > 1) {
|
||||
if (!params.at(1).isEmpty())
|
||||
_label = QString::fromLatin1(params.at(1))
|
||||
+ QString::fromUtf8("\xE2\x80\x89kt");
|
||||
_param = QVariant(params.at(0).toDouble());
|
||||
} else if (type>>16 == I_SISTAT || type>>16 == SISTAT) {
|
||||
if (_label.isEmpty())
|
||||
_label = sistat(type & 0xFF);
|
||||
@ -540,9 +550,13 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
|
||||
subtype |= av.at(1).toByteArray().toUInt() << 8;
|
||||
|
||||
if ((OBJL == I_DISMAR && key == I_WTWDIS)
|
||||
|| (OBJL == I_RDOCAL && key == ORIENT))
|
||||
|| (OBJL == RDOCAL && key == ORIENT)
|
||||
|| (OBJL == I_RDOCAL && key == ORIENT)
|
||||
|| (OBJL == CURENT && key == ORIENT))
|
||||
params[0] = av.at(1).toByteArray();
|
||||
if (OBJL == I_RDOCAL && key == COMCHA)
|
||||
if ((OBJL == I_RDOCAL && key == COMCHA)
|
||||
|| (OBJL == RDOCAL && key == COMCHA)
|
||||
|| (OBJL == CURENT && key == CURVEL))
|
||||
params[1] = av.at(1).toByteArray();
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define COALNE 30
|
||||
#define CONVYR 34
|
||||
#define CRANES 35
|
||||
#define CURENT 36
|
||||
#define DAMCON 38
|
||||
#define DWRTPT 41
|
||||
#define DEPARE 42
|
||||
@ -39,6 +40,7 @@
|
||||
#define FNCLNE 52
|
||||
#define FERYRT 53
|
||||
#define FLODOC 57
|
||||
#define FOGSIG 58
|
||||
#define GATCON 61
|
||||
#define HRBFAC 64
|
||||
#define HULKES 65
|
||||
@ -63,6 +65,7 @@
|
||||
#define PYLONS 98
|
||||
#define RADSTA 102
|
||||
#define RTPBCN 103
|
||||
#define RDOCAL 104
|
||||
#define RDOSTA 105
|
||||
#define RAILWY 106
|
||||
#define RCRTCL 108
|
||||
|
@ -2,16 +2,17 @@
|
||||
#include <QPainter>
|
||||
#include "common/linec.h"
|
||||
#include "map/bitmapline.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "style.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace ENC;
|
||||
|
||||
#define ICON_PADDING 2
|
||||
#define TSSLPT_SIZE 0.005 /* ll */
|
||||
#define RDOCAL_SIZE 12 /* px */
|
||||
#define TSSLPT_SIZE 0.005 /* ll */
|
||||
#define RDOCAL_SIZE 12 /* px */
|
||||
#define CURENT_SIZE 12 /* px */
|
||||
|
||||
typedef QMap<Coordinates, const MapData::Point*> PointMap;
|
||||
|
||||
const float C1 = 0.866025f; /* sqrt(3)/2 */
|
||||
|
||||
@ -49,6 +50,18 @@ static QFont *font(Style::FontSize size)
|
||||
}
|
||||
}
|
||||
|
||||
static const QImage *light()
|
||||
{
|
||||
static QImage img(":/marine/light.png");
|
||||
return &img;
|
||||
}
|
||||
|
||||
static const QImage *signal()
|
||||
{
|
||||
static QImage img(":/marine/fog-signal.png");
|
||||
return &img;
|
||||
}
|
||||
|
||||
static const Style& style()
|
||||
{
|
||||
static Style s;
|
||||
@ -95,6 +108,7 @@ static QImage *rdocalArrow(qreal angle)
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
img->fill(Qt::transparent);
|
||||
QPainter p(img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(QPen(QColor("#eb49eb"), 1));
|
||||
|
||||
QPointF arrow[3];
|
||||
@ -114,14 +128,54 @@ static QImage *rdocalArrow(qreal angle)
|
||||
return img;
|
||||
}
|
||||
|
||||
static QImage *currentArrow(qreal angle)
|
||||
{
|
||||
QImage *img = new QImage(CURENT_SIZE*2, CURENT_SIZE*2,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
img->fill(Qt::transparent);
|
||||
QPainter p(img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(QPen(Qt::black, 1));
|
||||
|
||||
QPointF arrow[3];
|
||||
arrow[0] = QPointF(img->width()/2, img->height()/2);
|
||||
arrow[1] = arrow[0] + QPointF(qSin(angle - M_PI/3) * CURENT_SIZE,
|
||||
qCos(angle - M_PI/3) * CURENT_SIZE);
|
||||
arrow[2] = arrow[0] + QPointF(qSin(angle - M_PI + M_PI/3) * CURENT_SIZE,
|
||||
qCos(angle - M_PI + M_PI/3) * CURENT_SIZE);
|
||||
|
||||
QLineF l(arrow[1], arrow[2]);
|
||||
QPointF pt(l.pointAt(0.5));
|
||||
QLineF l2(arrow[0], pt);
|
||||
|
||||
p.translate(arrow[0] - pt);
|
||||
p.drawPolyline(QPolygonF() << arrow[1] << arrow[0] << arrow[2]);
|
||||
p.drawLine(arrow[0], l2.pointAt(2));
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
static QImage *image(uint type, const QVariant ¶m)
|
||||
{
|
||||
if (type>>16 == I_RDOCAL)
|
||||
if (type>>16 == RDOCAL || type>>16 == I_RDOCAL)
|
||||
return rdocalArrow(deg2rad(90 - param.toDouble()));
|
||||
else if (type>>16 == CURENT)
|
||||
return currentArrow(deg2rad(90 - param.toDouble()));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
|
||||
{
|
||||
if (type>>16 == I_DISMAR)
|
||||
return true;
|
||||
|
||||
if ((img || type>>16 == SOUNDG) && zoom < range.mid())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QPainterPath RasterTile::painterPath(const Polygon &polygon) const
|
||||
{
|
||||
QPainterPath path;
|
||||
@ -266,21 +320,37 @@ void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<TextItem*> &textItems,
|
||||
QList<QImage*> &images)
|
||||
QList<TextItem*> &lights)
|
||||
{
|
||||
const Style &s = style();
|
||||
PointMap lightsMap, signalsMap;
|
||||
int i;
|
||||
|
||||
std::sort(_points.begin(), _points.end(), pointLess);
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
/* Lights & Signals */
|
||||
for (i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point *point = _points.at(i);
|
||||
if (point->type()>>16 == LIGHTS)
|
||||
lightsMap.insert(point->pos(), point);
|
||||
else if (point->type()>>16 == FOGSIG)
|
||||
signalsMap.insert(point->pos(), point);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Everything else */
|
||||
for ( ; i < _points.size(); i++) {
|
||||
const MapData::Point *point = _points.at(i);
|
||||
QPoint pos(ll2xy(point->pos()).toPoint());
|
||||
const Style::Point &style = s.point(point->type());
|
||||
|
||||
const QString *label = point->label().isEmpty() ? 0 : &(point->label());
|
||||
QImage *rimg = style.img().isNull()
|
||||
? image(point->type(), point->param()) : 0;
|
||||
const QImage *img = style.img().isNull() ? rimg : &style.img();
|
||||
const QFont *fnt = font(style.textFontSize());
|
||||
const QFont *fnt = showLabel(img, _zooms, _zoom, point->type())
|
||||
? font(style.textFontSize()) : 0;
|
||||
const QColor *color = &style.textColor();
|
||||
const QColor *hColor = style.haloColor().isValid()
|
||||
? &style.haloColor() : 0;
|
||||
@ -288,16 +358,16 @@ void RasterTile::processPoints(QList<TextItem*> &textItems,
|
||||
if ((!label || !fnt) && !img)
|
||||
continue;
|
||||
|
||||
TextPointItem *item = new TextPointItem(ll2xy(point->pos()).toPoint(),
|
||||
label, fnt, img, color, hColor, 0, ICON_PADDING);
|
||||
PointItem *item = new PointItem(pos, label, fnt, img, rimg, color,
|
||||
hColor);
|
||||
if (item->isValid() && !item->collides(textItems)) {
|
||||
textItems.append(item);
|
||||
if (rimg)
|
||||
images.append(rimg);
|
||||
} else {
|
||||
if (lightsMap.contains(point->pos()))
|
||||
lights.append(new TextPointItem(pos, 0, 0, light(), 0, 0, 0, 0));
|
||||
if (signalsMap.contains(point->pos()))
|
||||
lights.append(new TextPointItem(pos, 0, 0, signal(), 0, 0, 0, 0));
|
||||
} else
|
||||
delete item;
|
||||
delete rimg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,14 +398,13 @@ void RasterTile::processLines(QList<TextItem*> &textItems)
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<TextItem*> textItems;
|
||||
QList<QImage*> images;
|
||||
QList<TextItem*> textItems, lights;
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
||||
processPolygons(textItems);
|
||||
processPoints(textItems, images);
|
||||
processPoints(textItems, lights);
|
||||
processLines(textItems);
|
||||
|
||||
QPainter painter(&_pixmap);
|
||||
@ -347,10 +416,11 @@ void RasterTile::render()
|
||||
drawLines(&painter);
|
||||
drawArrows(&painter);
|
||||
|
||||
drawTextItems(&painter, lights);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
qDeleteAll(images);
|
||||
qDeleteAll(lights);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setBrush(Qt::NoBrush);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QPixmap>
|
||||
#include "map/projection.h"
|
||||
#include "map/transform.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "mapdata.h"
|
||||
|
||||
class TextItem;
|
||||
@ -13,12 +14,14 @@ namespace ENC {
|
||||
class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform, int zoom,
|
||||
const QRect &rect, qreal ratio, const QList<MapData::Line*> &lines,
|
||||
const QList<MapData::Poly*> &polygons, const QList<MapData::Point*> &points)
|
||||
: _proj(proj), _transform(transform), _zoom(zoom), _rect(rect),
|
||||
_ratio(ratio), _pixmap(rect.width() * ratio, rect.height() * ratio),
|
||||
_lines(lines), _polygons(polygons), _points(points), _valid(false) {}
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Range &zooms, int zoom, const QRect &rect, qreal ratio,
|
||||
const QList<MapData::Line*> &lines, const QList<MapData::Poly*> &polygons,
|
||||
const QList<MapData::Point*> &points)
|
||||
: _proj(proj), _transform(transform), _zooms(zooms), _zoom(zoom),
|
||||
_rect(rect), _ratio(ratio),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _lines(lines),
|
||||
_polygons(polygons), _points(points), _valid(false) {}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
QPoint xy() const {return _rect.topLeft();}
|
||||
@ -28,12 +31,25 @@ public:
|
||||
void render();
|
||||
|
||||
private:
|
||||
class PointItem : public TextPointItem
|
||||
{
|
||||
public:
|
||||
PointItem(const QPoint &point, const QString *text, const QFont *font,
|
||||
const QImage *img, const QImage *rimg, const QColor *color,
|
||||
const QColor *haloColor) : TextPointItem(point, text, font, img, color,
|
||||
haloColor, 0, 2), _rimg(rimg) {}
|
||||
~PointItem() {delete _rimg;}
|
||||
|
||||
private:
|
||||
const QImage *_rimg;
|
||||
};
|
||||
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
QPainterPath painterPath(const Polygon &polygon) const;
|
||||
QPolygonF polyline(const QVector<Coordinates> &path) const;
|
||||
QPolygonF tsslptArrow(const Coordinates &c, qreal angle) const;
|
||||
void processPoints(QList<TextItem*> &textItems, QList<QImage*> &images);
|
||||
void processPoints(QList<TextItem*> &textItems, QList<TextItem *> &lights);
|
||||
void processLines(QList<TextItem*> &textItems);
|
||||
void processPolygons(QList<TextItem*> &textItems);
|
||||
void drawBitmapPath(QPainter *painter, const QImage &img,
|
||||
@ -45,6 +61,7 @@ private:
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
Range _zooms;
|
||||
int _zoom;
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
|
@ -178,12 +178,11 @@ void Style::pointStyle()
|
||||
{
|
||||
_points[SUBTYPE(BUAARE, 1)].setTextFontSize(Large);
|
||||
_points[SUBTYPE(BUAARE, 5)].setTextFontSize(Large);
|
||||
_points[SUBTYPE(BUAARE, 3)].setTextFontSize(Small);
|
||||
_points[SUBTYPE(BUAARE, 4)].setTextFontSize(Large);
|
||||
_points[SUBTYPE(BUAARE, 2)].setTextFontSize(Small);
|
||||
_points[SUBTYPE(BUAARE, 6)].setTextFontSize(Small);
|
||||
_points[SUBTYPE(BUAARE, 0)].setTextFontSize(Small);
|
||||
_points[TYPE(SOUNDG)].setTextFontSize(Small);
|
||||
_points[TYPE(SOUNDG)].setHaloColor(QColor());
|
||||
_points[TYPE(LIGHTS)] = Point(QImage(":/marine/light-major.png"), Small);
|
||||
_points[TYPE(BOYCAR)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
_points[TYPE(BOYINB)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
_points[TYPE(BOYISD)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
@ -191,12 +190,14 @@ void Style::pointStyle()
|
||||
_points[TYPE(I_BOYLAT)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
_points[TYPE(BOYSAW)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
_points[TYPE(BOYSPP)] = Point(QImage(":/marine/buoy.png"), Small);
|
||||
_points[TYPE(BCNCAR)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[TYPE(BCNISD)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[TYPE(BCNLAT)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[TYPE(I_BCNLAT)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[TYPE(BCNSAW)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[TYPE(BCNSPP)] = Point(QImage(":/marine/beacon.png"), Small);
|
||||
_points[SUBTYPE(LNDMRK, 3)] = Point(QImage(":/marine/chimney.png"));
|
||||
_points[SUBTYPE(LNDMRK, 7)] = Point(QImage(":/marine/pylon.png"));
|
||||
_points[SUBTYPE(LNDMRK, 9)] = Point(QImage(":/marine/monument.png"));
|
||||
_points[SUBTYPE(LNDMRK, 20)] = Point(QImage(":/marine/church.png"));
|
||||
_points[SUBTYPE(LNDMRK, 17)] = Point(QImage(":/marine/tower.png"));
|
||||
@ -235,14 +236,14 @@ void Style::pointStyle()
|
||||
_points[SUBTYPE(MORFAC, 5)] = Point(QImage(":/marine/pile.png"), Small);
|
||||
_points[SUBTYPE(MORFAC, 7)] = Point(QImage(":/marine/mooring-buoy.png"),
|
||||
Small);
|
||||
_points[TYPE(CRANES)] = Point(QImage(":/marine/crane.png"));
|
||||
_points[TYPE(I_CRANES)] = Point(QImage(":/marine/crane.png"));
|
||||
_points[SUBTYPE(I_DISMAR, 1)] = Point(QImage(":/marine/distance-mark.png"));
|
||||
_points[TYPE(CRANES)] = Point(QImage(":/marine/crane.png"), Small);
|
||||
_points[TYPE(I_CRANES)] = Point(QImage(":/marine/crane.png"), Small);
|
||||
_points[SUBTYPE(I_DISMAR, 1)] = Point(QImage(":/marine/distance-mark.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(I_DISMAR, 1)].setTextColor(QColor("#ffffff"));
|
||||
_points[SUBTYPE(I_DISMAR, 1)].setTextFontSize(Small);
|
||||
_points[SUBTYPE(I_DISMAR, 1)].setHaloColor(QColor());
|
||||
_points[SUBTYPE(I_DISMAR, 2)] = Point(QImage(":/marine/distance-mark-land.png"));
|
||||
_points[SUBTYPE(I_DISMAR, 2)].setTextFontSize(Small);
|
||||
_points[SUBTYPE(I_DISMAR, 2)] = Point(QImage(":/marine/distance-mark-land.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(I_DISMAR, 2)].setHaloColor(QColor());
|
||||
_points[SUBTYPE(I_DISMAR, 3)] = _points[SUBTYPE(I_DISMAR, 2)];
|
||||
_points[SUBTYPE(I_DISMAR, 4)] = _points[SUBTYPE(I_DISMAR, 2)];
|
||||
@ -252,7 +253,8 @@ void Style::pointStyle()
|
||||
_points[TYPE(RTPBCN)] = Point(QImage(":/marine/radar-transponder.png"));
|
||||
_points[TYPE(SILTNK)] = Point(QImage(":/marine/silo.png"));
|
||||
_points[TYPE(I_TRNBSN)] = Point(QImage(":/marine/turning-basin.png"));
|
||||
_points[TYPE(I_WTWGAG)] = Point(QImage(":/marine/gauge.png"));
|
||||
_points[TYPE(I_WTWGAG)] = Point(QImage(":/marine/gauge.png"), Small);
|
||||
_points[TYPE(RDOCAL)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(I_RDOCAL)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(PYLONS)] = Point(QImage(":/marine/pylon.png"));
|
||||
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"));
|
||||
@ -261,26 +263,33 @@ void Style::pointStyle()
|
||||
_points[SUBTYPE(WATTUR, 4)] = Point(QImage(":/marine/overfalls.png"));
|
||||
_points[TYPE(PILBOP)] = Point(QImage(":/marine/boarding-place.png"));
|
||||
_points[TYPE(SISTAT)] = Point(QImage(":/marine/pylon.png"));
|
||||
_points[TYPE(SLCONS)] = Point(QImage(":/marine/construction.png"), Small);
|
||||
|
||||
_points[SUBTYPE(SMCFAC, 7)] = Point(QImage(":/POI/restaurant-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 11)] = Point(QImage(":/POI/pharmacy-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 12)] = Point(QImage(":/POI/drinking-water-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 13)] = Point(QImage(":/POI/fuel-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 18)] = Point(QImage(":/POI/toilet-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 20)] = Point(QImage(":/POI/telephone-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 22)] = Point(QImage(":/POI/parking-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 25)] = Point(QImage(":/POI/campsite-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 2)] = Point(QImage(":/POI/harbor-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 5)] = Point(QImage(":/POI/hospital-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 6)] = Point(QImage(":/POI/post-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 7)] = Point(QImage(":/POI/lodging-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 9)] = Point(QImage(":/POI/police-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 13)] = Point(QImage(":/POI/bank-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 19)] = Point(QImage(":/POI/school-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 20)] = Point(QImage(":/POI/religious-christian-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 22)] = Point(QImage(":/POI/religious-jewish-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 26)] = Point(QImage(":/POI/religious-muslim-11.png"));
|
||||
_points[SUBTYPE(BUISGL, 42)] = Point(QImage(":/POI/bus-11.png"));
|
||||
_points[SUBTYPE(SMCFAC, 7)] = Point(QImage(":/POI/restaurant-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 11)] = Point(QImage(":/POI/pharmacy-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 12)] = Point(QImage(":/POI/drinking-water-11.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(SMCFAC, 13)] = Point(QImage(":/POI/fuel-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 18)] = Point(QImage(":/POI/toilet-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 20)] = Point(QImage(":/POI/telephone-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 22)] = Point(QImage(":/POI/parking-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 25)] = Point(QImage(":/POI/campsite-11.png"), Small);
|
||||
_points[TYPE(BUISGL)] = Point(QImage(":/marine/building.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 2)] = Point(QImage(":/POI/harbor-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 5)] = Point(QImage(":/POI/hospital-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 6)] = Point(QImage(":/POI/post-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 7)] = Point(QImage(":/POI/lodging-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 9)] = Point(QImage(":/POI/police-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 13)] = Point(QImage(":/POI/bank-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 19)] = Point(QImage(":/POI/school-11.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 20)] = Point(QImage(":/POI/religious-christian-11.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(BUISGL, 22)] = Point(QImage(":/POI/religious-jewish-11.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(BUISGL, 26)] = Point(QImage(":/POI/religious-muslim-11.png"),
|
||||
Small);
|
||||
_points[SUBTYPE(BUISGL, 33)] = Point(QImage(":/marine/pylon.png"), Small);
|
||||
_points[SUBTYPE(BUISGL, 42)] = Point(QImage(":/POI/bus-11.png"), Small);
|
||||
}
|
||||
|
||||
Style::Style()
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <QFileInfo>
|
||||
#include "common/programpaths.h"
|
||||
#include "vectortile.h"
|
||||
#include "style.h"
|
||||
@ -76,7 +77,7 @@ void MapData::load()
|
||||
_style = new Style(_typ);
|
||||
else {
|
||||
QString typFile(ProgramPaths::typFile());
|
||||
if (!typFile.isEmpty()) {
|
||||
if (QFileInfo::exists(typFile)) {
|
||||
SubFile typ(&typFile);
|
||||
_style = new Style(&typ);
|
||||
} else
|
||||
@ -108,6 +109,9 @@ void MapData::computeZooms()
|
||||
zooms.insert(z.at(i));
|
||||
}
|
||||
|
||||
if (zooms.isEmpty())
|
||||
return;
|
||||
|
||||
_zooms = zooms.values();
|
||||
std::sort(_zooms.begin(), _zooms.end());
|
||||
|
||||
|
@ -357,7 +357,8 @@ void RasterTile::processStreetNames(QList<TextItem*> &textItems)
|
||||
? &style.textColor() : 0;
|
||||
|
||||
TextPathItem *item = new TextPathItem(poly.points,
|
||||
&poly.label.text(), _rect, fnt, color, &haloColor);
|
||||
&poly.label.text(), _rect, fnt, color, Style::isContourLine(poly.type)
|
||||
? 0 : &haloColor);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
|
@ -217,7 +217,7 @@ bool RGNFile::load(Handle &hdl)
|
||||
&& readUInt32(hdl, _base.size)))
|
||||
return false;
|
||||
|
||||
if (hdrLen >= 0x68) {
|
||||
if (hdrLen >= 0x71) {
|
||||
if (!(readUInt32(hdl, _polygons.offset) && readUInt32(hdl, _polygons.size)
|
||||
&& seek(hdl, _gmpOffset + 0x29) && readUInt32(hdl, _polygonsGblFlags)
|
||||
&& readUInt32(hdl, _polygonsLclFlags[0])
|
||||
|
@ -392,6 +392,7 @@ void Style::defaultLineStyle()
|
||||
_lines[0x10505] = Line(QImage(":/marine/safety-zone-line.png"));
|
||||
_lines[0x10507] = Line(QPen(QColor("#e728e7"), 1, Qt::DashLine));
|
||||
_lines[0x10601] = Line(QPen(QColor("#000000"), 1, Qt::SolidLine));
|
||||
_lines[0x10603] = Line(QPen(QColor("#e728e7"), 2, Qt::DashDotLine));
|
||||
_lines[0x10606] = Line(QImage(":/marine/anchor-line.png"));
|
||||
_lines[0x1060c] = Line(QPen(QColor("#e728e7"), 1, Qt::SolidLine));
|
||||
_lines[0x1060d] = Line(QPen(QColor("#eb49eb"), 1, Qt::DashLine));
|
||||
|
@ -195,8 +195,8 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data.points(pointRectD.toRectC(_projection, 20), &points);
|
||||
|
||||
tiles.append(RasterTile(_projection, _transform, _zoom,
|
||||
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
||||
tiles.append(RasterTile(_projection, _transform, _data.zooms(),
|
||||
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
||||
lines, polygons, points));
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
#include "image.h"
|
||||
|
||||
#define TILE_SIZE 256
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
#define OPENGL_SIZE_LIMIT 536870912 /* 512MB */
|
||||
#else
|
||||
#define OPENGL_SIZE_LIMIT 134217728 /* 128MB */
|
||||
#endif
|
||||
|
||||
void Image::draw(QPainter *painter, const QRectF &rect, Map::Flags flags)
|
||||
{
|
||||
@ -11,7 +16,7 @@ void Image::draw(QPainter *painter, const QRectF &rect, Map::Flags flags)
|
||||
/* When OpenGL is used, big images are rendered incredibly slow or not at
|
||||
all using the QPainter::drawImage() function with a source rect set. So
|
||||
we have to tile the image ourself before it can be drawn. */
|
||||
if (flags & Map::OpenGL) {
|
||||
if (flags & Map::OpenGL && _img.sizeInBytes() > OPENGL_SIZE_LIMIT) {
|
||||
for (int i = sr.left()/TILE_SIZE; i <= sr.right()/TILE_SIZE; i++) {
|
||||
for (int j = sr.top()/TILE_SIZE; j <= sr.bottom()/TILE_SIZE; j++) {
|
||||
QPoint tl(i * TILE_SIZE, j * TILE_SIZE);
|
||||
|
@ -80,7 +80,6 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
errors.append(it.key() + ": " + map->errorString());
|
||||
++it;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (it = _parsers.begin(); it != _parsers.end(); it++) {
|
||||
map = it.value()(path, proj, isDir);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QColor>
|
||||
#include "common/hash.h"
|
||||
#include "map/osm.h"
|
||||
#include "subfile.h"
|
||||
#include "mapdata.h"
|
||||
@ -14,37 +15,6 @@ using namespace Mapsforge;
|
||||
#define MD(val) ((val) / 1e6)
|
||||
#define OFFSET_MASK 0x7FFFFFFFFFL
|
||||
|
||||
static uint pointType(const QVector<MapData::Tag> &tags)
|
||||
{
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
const MapData::Tag &tag = tags.at(i);
|
||||
if (tag.key == "place") {
|
||||
if (tag.value == "country")
|
||||
return 4;
|
||||
else if (tag.value == "city")
|
||||
return 3;
|
||||
else if (tag.value == "town")
|
||||
return 2;
|
||||
else if (tag.value == "village")
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setPointId(MapData::Point &p)
|
||||
{
|
||||
uint hash = (uint)qHash(QPair<double,double>((uint)qHash(
|
||||
QPair<double, double>(p.coordinates.lon(), p.coordinates.lat())),
|
||||
(uint)qHash(p.label)));
|
||||
uint type = pointType(p.tags);
|
||||
|
||||
p.id = ((quint64)type)<<32 | hash;
|
||||
}
|
||||
|
||||
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
||||
QList<MapData::Path> *dst)
|
||||
{
|
||||
@ -194,7 +164,7 @@ static bool readDoubleDelta(SubFile &subfile, const Coordinates &c,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readPolygon(SubFile &subfile, const Coordinates &c,
|
||||
static bool readPolygonPath(SubFile &subfile, const Coordinates &c,
|
||||
bool doubleDelta, Polygon &polygon)
|
||||
{
|
||||
quint32 blocks, nodes;
|
||||
@ -202,7 +172,7 @@ static bool readPolygon(SubFile &subfile, const Coordinates &c,
|
||||
if (!subfile.readVUInt32(blocks))
|
||||
return false;
|
||||
|
||||
polygon.reserve(blocks);
|
||||
polygon.reserve(polygon.size() + blocks);
|
||||
for (quint32 i = 0; i < blocks; i++) {
|
||||
if (!subfile.readVUInt32(nodes) || !nodes)
|
||||
return false;
|
||||
@ -604,7 +574,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
||||
Path p;
|
||||
Path p(subfile.offset() + subfile.pos());
|
||||
qint32 lon = 0, lat = 0;
|
||||
|
||||
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
||||
@ -646,15 +616,15 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
|
||||
Q_ASSERT(blocks);
|
||||
for (unsigned j = 0; j < blocks; j++) {
|
||||
if (!readPolygon(subfile, tile->pos, flags & 0x04, p.poly))
|
||||
if (!readPolygonPath(subfile, tile->pos, flags & 0x04, p.poly))
|
||||
return false;
|
||||
p.closed = isClosed(p.poly);
|
||||
if (flags & 0x10)
|
||||
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
|
||||
p.poly.first().first().lat() + MD(lat));
|
||||
|
||||
list->append(p);
|
||||
}
|
||||
p.closed = isClosed(p.poly);
|
||||
if (flags & 0x10)
|
||||
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
|
||||
p.poly.first().first().lat() + MD(lat));
|
||||
|
||||
list->append(p);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -719,7 +689,6 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
||||
p.tags.append(Tag("ele", QByteArray::number(elevation)));
|
||||
}
|
||||
|
||||
setPointId(p);
|
||||
list->append(p);
|
||||
}
|
||||
|
||||
@ -735,15 +704,14 @@ QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag)
|
||||
|
||||
QDebug operator<<(QDebug dbg, const MapData::Path &path)
|
||||
{
|
||||
dbg.nospace() << "Path(" << path.poly.boundingRect() << ", " << path.label
|
||||
<< ", " << path.tags << ")";
|
||||
dbg.nospace() << "Path(" << path.poly.boundingRect() << ", "
|
||||
<< path.tags << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const MapData::Point &point)
|
||||
{
|
||||
dbg.nospace() << "Point(" << point.coordinates << "," << point.label
|
||||
<< ", " << point.tags << ")";
|
||||
dbg.nospace() << "Point(" << point.coordinates << ", " << point.tags << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QCache>
|
||||
#include <QPainterPath>
|
||||
#include "common/hash.h"
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
@ -42,31 +41,31 @@ public:
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point(const Coordinates &c) : coordinates(c) {}
|
||||
Point(const Coordinates &c) : coordinates(c)
|
||||
{
|
||||
id = (quint64)qHash(QPair<double, double>(c.lon(), c.lat()));
|
||||
}
|
||||
|
||||
quint64 id;
|
||||
Coordinates coordinates;
|
||||
QVector<Tag> tags;
|
||||
int layer;
|
||||
quint64 id;
|
||||
|
||||
QString label;
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
{return id > other.id;}
|
||||
};
|
||||
|
||||
struct Path {
|
||||
Path(quint64 id) : id(id) {}
|
||||
|
||||
quint64 id;
|
||||
Polygon poly;
|
||||
QVector<Tag> tags;
|
||||
Coordinates labelPos;
|
||||
int layer;
|
||||
bool closed;
|
||||
|
||||
QString label;
|
||||
QPainterPath path;
|
||||
|
||||
bool operator<(const Path &other) const
|
||||
{return layer < other.layer;}
|
||||
bool operator==(const Path &other) const
|
||||
{return (id == other.id);}
|
||||
};
|
||||
|
||||
RectC bounds() const;
|
||||
@ -75,7 +74,7 @@ public:
|
||||
int tileSize() const {return _tileSize;}
|
||||
|
||||
void points(const RectC &rect, int zoom, QList<Point> *list);
|
||||
void paths(const RectC &rect, int zoom, QList<Path> *list);
|
||||
void paths(const RectC &rect, int zoom, QList<Path> *set);
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
@ -175,6 +174,11 @@ inline HASH_T qHash(const MapData::Tag &tag)
|
||||
return ::qHash(tag.key) ^ ::qHash(tag.value);
|
||||
}
|
||||
|
||||
inline HASH_T qHash(const MapData::Path &path)
|
||||
{
|
||||
return ::qHash(path.id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include <QPainter>
|
||||
#include <QCache>
|
||||
#include "common/programpaths.h"
|
||||
#include "map/mapsforgemap.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace Mapsforge;
|
||||
@ -44,36 +41,13 @@ static QPointF centroid(const QPainterPath &polygon)
|
||||
return QPointF(cx * factor, cy * factor);
|
||||
}
|
||||
|
||||
static QString *pointLabel(const Style::TextRender *ri, MapData::Point &point)
|
||||
static const QByteArray *label(const QByteArray &key,
|
||||
const QVector<MapData::Tag> &tags)
|
||||
{
|
||||
for (int i = 0; i < point.tags.size(); i++) {
|
||||
if (point.tags.at(i).key == ri->key()) {
|
||||
if (point.tags.at(i).value.isEmpty())
|
||||
return 0;
|
||||
else {
|
||||
point.label = point.tags.at(i).value;
|
||||
return &point.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QString *pathLabel(const Style::TextRender *ri, MapData::Path &path,
|
||||
bool *limit = 0)
|
||||
{
|
||||
for (int i = 0; i < path.tags.size(); i++) {
|
||||
if (path.tags.at(i).key == ri->key()) {
|
||||
if (path.tags.at(i).value.isEmpty())
|
||||
return 0;
|
||||
else {
|
||||
path.label = path.tags.at(i).value;
|
||||
if (limit)
|
||||
*limit = (path.tags.at(i).key == "ref");
|
||||
return &path.label;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
const MapData::Tag &tag = tags.at(i);
|
||||
if (tag.key == key)
|
||||
return tag.value.isEmpty() ? 0 : &tag.value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -85,23 +59,23 @@ static const QColor *haloColor(const Style::TextRender *ti)
|
||||
? &ti->strokeColor() : 0;
|
||||
}
|
||||
|
||||
|
||||
void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.pointLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.pointSymbols(_zoom));
|
||||
QList<PainterPoint> points;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
MapData::Point &point = _points[i];
|
||||
QString *label = 0;
|
||||
const MapData::Point &point = _points.at(i);
|
||||
const QByteArray *lbl = 0;
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
|
||||
for (int j = 0; j < labels.size(); j++) {
|
||||
const Style::TextRender *ri = labels.at(j);
|
||||
if (ri->rule().match(point.tags)) {
|
||||
if ((label = pointLabel(ri, point))) {
|
||||
if ((lbl = label(ri->key(), point.tags))) {
|
||||
ti = ri;
|
||||
break;
|
||||
}
|
||||
@ -116,17 +90,21 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ti && !si)
|
||||
continue;
|
||||
if (ti || si)
|
||||
points.append(PainterPoint(&point, lbl, si, ti));
|
||||
}
|
||||
|
||||
const QImage *img = si ? &si->img() : 0;
|
||||
const QFont *font = ti ? &ti->font() : 0;
|
||||
const QColor *color = ti ? &ti->fillColor() : 0;
|
||||
const QColor *hColor = ti ? haloColor(ti) : 0;
|
||||
std::sort(points.begin(), points.end());
|
||||
|
||||
TextPointItem *item = new TextPointItem(
|
||||
ll2xy(point.coordinates).toPoint(), label, font, img, color,
|
||||
hColor, 0);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const PainterPoint &p = points.at(i);
|
||||
const QImage *img = p.si ? &p.si->img() : 0;
|
||||
const QFont *font = p.ti ? &p.ti->font() : 0;
|
||||
const QColor *color = p.ti ? &p.ti->fillColor() : 0;
|
||||
const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
|
||||
|
||||
PointItem *item = new PointItem(ll2xy(p.p->coordinates).toPoint(),
|
||||
p.lbl, font, img, color, hColor);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
@ -134,34 +112,34 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
|
||||
|
||||
for (int i = 0; i < _paths.size(); i++) {
|
||||
MapData::Path &path = _paths[i];
|
||||
QString *label = 0;
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
const QByteArray *lbl = 0;
|
||||
|
||||
if (!path.closed)
|
||||
if (!path.path->closed)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < labels.size(); j++) {
|
||||
const Style::TextRender *ri = labels.at(j);
|
||||
if (ri->rule().match(path.closed, path.tags)) {
|
||||
if ((label = pathLabel(ri, path))) {
|
||||
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||
if ((lbl = label(ri->key(), path.path->tags)))
|
||||
ti = ri;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < symbols.size(); j++) {
|
||||
const Style::Symbol *ri = symbols.at(j);
|
||||
if (ri->rule().match(path.tags)) {
|
||||
if (ri->rule().match(path.path->tags)) {
|
||||
si = ri;
|
||||
break;
|
||||
}
|
||||
@ -170,18 +148,15 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
||||
if (!ti && !si)
|
||||
continue;
|
||||
|
||||
if (!path.path.elementCount())
|
||||
path.path = painterPath(path.poly);
|
||||
|
||||
const QImage *img = si ? &si->img() : 0;
|
||||
const QFont *font = ti ? &ti->font() : 0;
|
||||
const QColor *color = ti ? &ti->fillColor() : 0;
|
||||
const QColor *hColor = ti ? haloColor(ti) : 0;
|
||||
QPointF pos = path.labelPos.isNull()
|
||||
? centroid(path.path) : ll2xy(path.labelPos);
|
||||
QPointF pos = path.path->labelPos.isNull()
|
||||
? centroid(path.pp) : ll2xy(path.path->labelPos);
|
||||
|
||||
TextPointItem *item = new TextPointItem(pos.toPoint(), label, font, img,
|
||||
color, hColor, 0);
|
||||
PointItem *item = new PointItem(pos.toPoint(), lbl, font, img, color,
|
||||
hColor);
|
||||
if (item->isValid() && _rect.contains(item->boundingRect().toRect())
|
||||
&& !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
@ -190,38 +165,39 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems)
|
||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
|
||||
QSet<QString> set;
|
||||
QSet<QByteArray> set;
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
const Style::TextRender *ri = instructions.at(i);
|
||||
|
||||
for (int j = 0; j < _paths.size(); j++) {
|
||||
MapData::Path &path = _paths[j];
|
||||
QString *label = 0;
|
||||
bool limit = false;
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
const QByteArray *lbl = label(ri->key(), path.path->tags);
|
||||
|
||||
if (!path.path.elementCount())
|
||||
if (!lbl)
|
||||
continue;
|
||||
if (!ri->rule().match(path.closed, path.tags))
|
||||
if (!ri->rule().match(path.path->closed, path.path->tags))
|
||||
continue;
|
||||
if (!(label = pathLabel(ri, path, &limit)))
|
||||
continue;
|
||||
if (limit && set.contains(path.label))
|
||||
bool limit = (ri->key() == "ref" || ri->key() == "ele"
|
||||
|| ri->key() == "ref_hike" || ri->key() == "ref_cycle"
|
||||
|| ri->key() == "ref_mtb");
|
||||
if (limit && set.contains(*lbl))
|
||||
continue;
|
||||
|
||||
TextPathItem *item = new TextPathItem(path.path, label, _rect,
|
||||
&ri->font(), &ri->fillColor(), haloColor(ri));
|
||||
PathItem *item = new PathItem(path.pp, lbl, _rect, &ri->font(),
|
||||
&ri->fillColor(), haloColor(ri));
|
||||
if (item->isValid() && !item->collides(textItems)) {
|
||||
textItems.append(item);
|
||||
if (limit)
|
||||
set.insert(path.label);
|
||||
set.insert(*lbl);
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,98 +208,121 @@ void RasterTile::drawTextItems(QPainter *painter,
|
||||
textItems.at(i)->paint(painter);
|
||||
}
|
||||
|
||||
QPainterPath RasterTile::painterPath(const Polygon &polygon) const
|
||||
QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
|
||||
path.moveTo(ll2xy(subpath.first()));
|
||||
for (int j = 1; j < subpath.size(); j++)
|
||||
path.lineTo(ll2xy(subpath.at(j)));
|
||||
if (curve) {
|
||||
QPointF p1(ll2xy(subpath.first()));
|
||||
QPointF p2(0, 0);
|
||||
QPointF p3(0, 0);
|
||||
|
||||
path.moveTo(p1);
|
||||
for (int j = 1; j < subpath.size(); j++) {
|
||||
p3 = ll2xy(subpath.at(j));
|
||||
p2 = QPointF((p1.x() + p3.x()) / 2.0, (p1.y() + p3.y()) / 2.0);
|
||||
path.quadTo(p1, p2);
|
||||
p1 = p3;
|
||||
}
|
||||
path.quadTo(p2, p3);
|
||||
} else {
|
||||
path.moveTo(ll2xy(subpath.first()));
|
||||
for (int j = 1; j < subpath.size(); j++)
|
||||
path.lineTo(ll2xy(subpath.at(j)));
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
QVector<RasterTile::PathInstruction> RasterTile::pathInstructions()
|
||||
void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QCache<Key, QVector<const Style::PathRender *> > cache(1024);
|
||||
QVector<PathInstruction> instructions;
|
||||
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QVector<const Style::PathRender*> *ri;
|
||||
QList<const Style::PathRender*> *ri;
|
||||
|
||||
for (int i = 0 ; i < _paths.size(); i++) {
|
||||
MapData::Path &path = _paths[i];
|
||||
for (int i = 0; i < _paths.size(); i++) {
|
||||
const MapData::Path &path = _paths.at(i);
|
||||
PainterPath &rp = paths[i];
|
||||
PathKey key(_zoom, path.closed, path.tags);
|
||||
|
||||
Key key(_zoom, path.closed, path.tags);
|
||||
QVector<const Style::PathRender*> *cached = cache.object(key);
|
||||
if (!cached) {
|
||||
ri = new QVector<const Style::PathRender*>(s.paths(_zoom,
|
||||
path.closed, path.tags));
|
||||
rp.path = &path;
|
||||
|
||||
if (!(ri = cache.object(key))) {
|
||||
ri = new QList<const Style::PathRender*>(s.paths(_zoom, path.closed,
|
||||
path.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(PathInstruction(ri->at(j), &path));
|
||||
instructions.append(RenderInstruction(ri->at(j), &rp));
|
||||
cache.insert(key, ri);
|
||||
} else {
|
||||
for (int j = 0; j < cached->size(); j++)
|
||||
instructions.append(PathInstruction(cached->at(j), &path));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &rp));
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(instructions.begin(), instructions.end());
|
||||
|
||||
return instructions;
|
||||
}
|
||||
|
||||
void RasterTile::drawPaths(QPainter *painter)
|
||||
void RasterTile::circleInstructions(
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QVector<PathInstruction> instructions(pathInstructions());
|
||||
const Style::PathRender *lri = 0;
|
||||
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::CircleRender*> *ri;
|
||||
|
||||
QPixmap layer(_pixmap.size());
|
||||
layer.setDevicePixelRatio(_ratio);
|
||||
layer.fill(Qt::transparent);
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point &point = _points.at(i);
|
||||
PointKey key(_zoom, point.tags);
|
||||
|
||||
QPainter lp(&layer);
|
||||
lp.setRenderHint(QPainter::Antialiasing);
|
||||
lp.translate(-_rect.x(), -_rect.y());
|
||||
lp.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
PathInstruction &is = instructions[i];
|
||||
const Style::PathRender *ri = is.render();
|
||||
|
||||
if (lri && lri != ri) {
|
||||
painter->drawPixmap(_rect.topLeft(), layer);
|
||||
lp.fillRect(QRect(_rect.topLeft(), _pixmap.size()), Qt::transparent);
|
||||
}
|
||||
|
||||
if (!is.path()->path.elementCount())
|
||||
is.path()->path = painterPath(is.path()->poly);
|
||||
|
||||
if (ri->area()) {
|
||||
lp.setPen(ri->pen(_zoom));
|
||||
lp.setBrush(ri->brush());
|
||||
lp.drawPath(is.path()->path);
|
||||
lri = ri;
|
||||
if (!(ri = cache.object(key))) {
|
||||
ri = new QList<const Style::CircleRender*>(s.circles(_zoom, point.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &point));
|
||||
cache.insert(key, ri);
|
||||
} else {
|
||||
painter->setPen(ri->pen(_zoom));
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawPath(is.path()->path);
|
||||
lri = 0;
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lri)
|
||||
painter->drawPixmap(_rect.topLeft(), layer);
|
||||
void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
|
||||
{
|
||||
QVector<RenderInstruction> instructions;
|
||||
pathInstructions(paths, instructions);
|
||||
circleInstructions(instructions);
|
||||
std::sort(instructions.begin(), instructions.end());
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
const RenderInstruction &is = instructions.at(i);
|
||||
PainterPath *path = is.path();
|
||||
|
||||
if (path) {
|
||||
const Style::PathRender *ri = is.pathRender();
|
||||
|
||||
if (!path->pp.elementCount())
|
||||
path->pp = painterPath(path->path->poly, ri->curve());
|
||||
|
||||
painter->setPen(ri->pen(_zoom));
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawPath(path->pp);
|
||||
} else {
|
||||
const Style::CircleRender *ri = is.circleRender();
|
||||
qreal radius = ri->radius(_zoom);
|
||||
|
||||
painter->setPen(ri->pen());
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawEllipse(ll2xy(is.point()->coordinates), radius, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
std::sort(_points.begin(), _points.end());
|
||||
|
||||
QList<TextItem*> textItems;
|
||||
QVector<PainterPath> renderPaths(_paths.size());
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
@ -332,11 +331,11 @@ void RasterTile::render()
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPaths(&painter);
|
||||
drawPaths(&painter, renderPaths);
|
||||
|
||||
processPointLabels(textItems);
|
||||
processAreaLabels(textItems);
|
||||
processLineLabels(textItems);
|
||||
processAreaLabels(textItems, renderPaths);
|
||||
processLineLabels(textItems, renderPaths);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
|
@ -4,12 +4,11 @@
|
||||
#include <QPixmap>
|
||||
#include "map/projection.h"
|
||||
#include "map/transform.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "style.h"
|
||||
#include "mapdata.h"
|
||||
|
||||
class MapsforgeMap;
|
||||
class TextItem;
|
||||
|
||||
namespace Mapsforge {
|
||||
|
||||
class RasterTile
|
||||
@ -30,33 +29,77 @@ public:
|
||||
void render();
|
||||
|
||||
private:
|
||||
class PathInstruction
|
||||
{
|
||||
public:
|
||||
PathInstruction() : _render(0), _path(0) {}
|
||||
PathInstruction(const Style::PathRender *render, MapData::Path *path)
|
||||
: _render(render), _path(path) {}
|
||||
struct PainterPath {
|
||||
PainterPath() : path(0) {}
|
||||
|
||||
bool operator<(const PathInstruction &other) const
|
||||
{
|
||||
if (_path->layer == other._path->layer)
|
||||
return _render->zOrder() < other._render->zOrder();
|
||||
else
|
||||
return (_path->layer < other._path->layer);
|
||||
}
|
||||
|
||||
const Style::PathRender *render() const {return _render;}
|
||||
MapData::Path *path() {return _path;}
|
||||
|
||||
private:
|
||||
const Style::PathRender *_render;
|
||||
MapData::Path *_path;
|
||||
QPainterPath pp;
|
||||
const MapData::Path *path;
|
||||
};
|
||||
|
||||
struct Key {
|
||||
Key(int zoom, bool closed, const QVector<MapData::Tag> &tags)
|
||||
struct PainterPoint {
|
||||
PainterPoint(const MapData::Point *p, const QByteArray *lbl,
|
||||
const Style::Symbol *si, const Style::TextRender *ti)
|
||||
: p(p), lbl(lbl), ti(ti), si(si)
|
||||
{
|
||||
Q_ASSERT(si || ti);
|
||||
}
|
||||
|
||||
bool operator<(const PainterPoint &other) const
|
||||
{
|
||||
if (priority() == other.priority())
|
||||
return p->id < other.p->id;
|
||||
else
|
||||
return (priority() > other.priority());
|
||||
}
|
||||
int priority() const {return si ? si->priority() : ti->priority();}
|
||||
|
||||
const MapData::Point *p;
|
||||
const QByteArray *lbl;
|
||||
const Style::TextRender *ti;
|
||||
const Style::Symbol *si;
|
||||
};
|
||||
|
||||
class RenderInstruction
|
||||
{
|
||||
public:
|
||||
RenderInstruction() : _pathRender(0), _circleRender(0), _path(0),
|
||||
_point(0) {}
|
||||
RenderInstruction(const Style::PathRender *render, PainterPath *path)
|
||||
: _pathRender(render), _circleRender(0), _path(path), _point(0) {}
|
||||
RenderInstruction(const Style::CircleRender *render,
|
||||
const MapData::Point *point) : _pathRender(0), _circleRender(render),
|
||||
_path(0), _point(point) {}
|
||||
|
||||
bool operator<(const RenderInstruction &other) const
|
||||
{
|
||||
if (layer() == other.layer())
|
||||
return zOrder() < other.zOrder();
|
||||
else
|
||||
return (layer() < other.layer());
|
||||
}
|
||||
|
||||
const Style::PathRender *pathRender() const {return _pathRender;}
|
||||
const Style::CircleRender *circleRender() const {return _circleRender;}
|
||||
PainterPath *path() const {return _path;}
|
||||
const MapData::Point *point() const {return _point;}
|
||||
|
||||
private:
|
||||
int layer() const {return _path ? _path->path->layer : _point->layer;}
|
||||
int zOrder() const
|
||||
{
|
||||
return _pathRender ? _pathRender->zOrder() : _circleRender->zOrder();
|
||||
}
|
||||
|
||||
const Style::PathRender *_pathRender;
|
||||
const Style::CircleRender *_circleRender;
|
||||
PainterPath *_path;
|
||||
const MapData::Point *_point;
|
||||
};
|
||||
|
||||
struct PathKey {
|
||||
PathKey(int zoom, bool closed, const QVector<MapData::Tag> &tags)
|
||||
: zoom(zoom), closed(closed), tags(tags) {}
|
||||
bool operator==(const Key &other) const
|
||||
bool operator==(const PathKey &other) const
|
||||
{
|
||||
return zoom == other.zoom && closed == other.closed
|
||||
&& tags == other.tags;
|
||||
@ -67,18 +110,54 @@ private:
|
||||
const QVector<MapData::Tag> &tags;
|
||||
};
|
||||
|
||||
friend HASH_T qHash(const RasterTile::Key &key);
|
||||
friend HASH_T qHash(const RasterTile::PathInstruction &pi);
|
||||
struct PointKey {
|
||||
PointKey(int zoom, const QVector<MapData::Tag> &tags)
|
||||
: zoom(zoom), tags(tags) {}
|
||||
bool operator==(const PointKey &other) const
|
||||
{
|
||||
return zoom == other.zoom && tags == other.tags;
|
||||
}
|
||||
|
||||
QVector<PathInstruction> pathInstructions();
|
||||
int zoom;
|
||||
const QVector<MapData::Tag> &tags;
|
||||
};
|
||||
|
||||
class PointItem : public TextPointItem
|
||||
{
|
||||
public:
|
||||
PointItem(const QPoint &point, const QByteArray *label,
|
||||
const QFont *font, const QImage *img, const QColor *color,
|
||||
const QColor *haloColor) : TextPointItem(point,
|
||||
label ? new QString(*label) : 0, font, img, color, haloColor, 0) {}
|
||||
~PointItem() {delete _text;}
|
||||
};
|
||||
|
||||
class PathItem : public TextPathItem
|
||||
{
|
||||
public:
|
||||
PathItem(const QPainterPath &line, const QByteArray *label,
|
||||
const QRect &tileRect, const QFont *font, const QColor *color,
|
||||
const QColor *haloColor) : TextPathItem(line,
|
||||
label ? new QString(*label) : 0, tileRect, font, color, haloColor) {}
|
||||
~PathItem() {delete _text;}
|
||||
};
|
||||
|
||||
friend HASH_T qHash(const RasterTile::PathKey &key);
|
||||
friend HASH_T qHash(const RasterTile::PointKey &key);
|
||||
|
||||
void pathInstructions(QVector<PainterPath> &paths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions);
|
||||
void circleInstructions(QVector<RasterTile::RenderInstruction> &instructions);
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
void processPointLabels(QList<TextItem*> &textItems);
|
||||
void processAreaLabels(QList<TextItem*> &textItems);
|
||||
void processLineLabels(QList<TextItem*> &textItems);
|
||||
QPainterPath painterPath(const Polygon &polygon) const;
|
||||
void processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths);
|
||||
void processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths);
|
||||
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
void drawPaths(QPainter *painter);
|
||||
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
@ -88,10 +167,16 @@ private:
|
||||
QPixmap _pixmap;
|
||||
QList<MapData::Path> _paths;
|
||||
QList<MapData::Point> _points;
|
||||
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
inline HASH_T qHash(const RasterTile::Key &key)
|
||||
inline HASH_T qHash(const RasterTile::PathKey &key)
|
||||
{
|
||||
return ::qHash(key.zoom) ^ ::qHash(key.tags);
|
||||
}
|
||||
|
||||
inline HASH_T qHash(const RasterTile::PointKey &key)
|
||||
{
|
||||
return ::qHash(key.zoom) ^ ::qHash(key.tags);
|
||||
}
|
||||
|
@ -79,10 +79,24 @@ bool Style::Rule::match(int zoom, bool closed,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::Rule::match(int zoom, const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
if (_type && NodeType != _type)
|
||||
return false;
|
||||
if (!_zooms.contains(zoom))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < _filters.size(); i++)
|
||||
if (!_filters.at(i).match(tags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule)
|
||||
{
|
||||
PathRender ri(rule, _paths.size());
|
||||
PathRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
QString file;
|
||||
int height = 0, width = 0;
|
||||
@ -127,7 +141,7 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
|
||||
void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
{
|
||||
PathRender ri(rule, _paths.size());
|
||||
PathRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool ok;
|
||||
|
||||
@ -169,12 +183,60 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
else if (join == "bevel")
|
||||
ri._strokeJoin = Qt::BevelJoin;
|
||||
}
|
||||
if (attr.hasAttribute("curve")) {
|
||||
QString curve(attr.value("curve").toString());
|
||||
if (curve == "cubic")
|
||||
ri._curve = true;
|
||||
}
|
||||
|
||||
_paths.append(ri);
|
||||
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::circle(QXmlStreamReader &reader, const Rule &rule)
|
||||
{
|
||||
CircleRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool ok;
|
||||
QColor fillColor, strokeColor;
|
||||
qreal strokeWidth = 0;
|
||||
|
||||
if (attr.hasAttribute("fill"))
|
||||
fillColor = QColor(attr.value("fill").toString());
|
||||
if (attr.hasAttribute("stroke"))
|
||||
strokeColor = QColor(attr.value("stroke").toString());
|
||||
if (attr.hasAttribute("stroke-width")) {
|
||||
strokeWidth = attr.value("stroke-width").toFloat(&ok);
|
||||
if (!ok || strokeWidth < 0) {
|
||||
reader.raiseError("invalid stroke-width value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("radius")) {
|
||||
ri._radius = attr.value("radius").toDouble(&ok);
|
||||
if (!ok || ri._radius <= 0) {
|
||||
reader.raiseError("invalid radius value");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reader.raiseError("missing radius");
|
||||
return;
|
||||
}
|
||||
if (attr.hasAttribute("scale-radius")) {
|
||||
if (attr.value("scale-radius").toString() == "true")
|
||||
ri._scale = true;
|
||||
}
|
||||
|
||||
ri._pen = (strokeColor.isValid() && strokeWidth > 0)
|
||||
? QPen(QBrush(strokeColor), strokeWidth) : Qt::NoPen;
|
||||
ri._brush = fillColor.isValid() ? QBrush(fillColor) : Qt::NoBrush;
|
||||
|
||||
_circles.append(ri);
|
||||
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
QList<QList<TextRender>*> &lists)
|
||||
{
|
||||
@ -183,6 +245,7 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
int fontSize = 9;
|
||||
bool bold = false, italic = false;
|
||||
QString fontFamily("Helvetica");
|
||||
QFont::Capitalization capitalization = QFont::MixedCase;
|
||||
bool ok;
|
||||
|
||||
if (attr.hasAttribute("k"))
|
||||
@ -223,11 +286,28 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
else if (family == "serif")
|
||||
fontFamily = "Times New Roman";
|
||||
}
|
||||
if (attr.hasAttribute("text-transform")) {
|
||||
QString transform(attr.value("text-transform").toString());
|
||||
if (transform == "uppercase")
|
||||
capitalization = QFont::AllUppercase;
|
||||
else if (transform == "lowercase")
|
||||
capitalization = QFont::AllLowercase;
|
||||
else if (transform == "capitalize")
|
||||
capitalization = QFont::Capitalize;
|
||||
}
|
||||
if (attr.hasAttribute("priority")) {
|
||||
ri._priority = attr.value("priority").toInt(&ok);
|
||||
if (!ok) {
|
||||
reader.raiseError("invalid priority value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ri._font.setFamily(fontFamily);
|
||||
ri._font.setPixelSize(fontSize);
|
||||
ri._font.setBold(bold);
|
||||
ri._font.setItalic(italic);
|
||||
ri._font.setCapitalization(capitalization);
|
||||
|
||||
if (fontSize)
|
||||
for (int i = 0; i < lists.size(); i++)
|
||||
@ -261,6 +341,13 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("priority")) {
|
||||
ri._priority = attr.value("priority").toInt(&ok);
|
||||
if (!ok) {
|
||||
reader.raiseError("invalid priority value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.isNull())
|
||||
ri._img = image(file, width, height, ratio);
|
||||
@ -321,6 +408,8 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
area(reader, dir, ratio, r);
|
||||
else if (reader.name() == QLatin1String("line"))
|
||||
line(reader, r);
|
||||
else if (reader.name() == QLatin1String("circle"))
|
||||
circle(reader, r);
|
||||
else if (reader.name() == QLatin1String("pathText")) {
|
||||
QList<QList<TextRender>*> list;
|
||||
list.append(&_pathLabels);
|
||||
@ -416,10 +505,10 @@ Style::Style(const QString &path, qreal ratio)
|
||||
loadXml(":/mapsforge/default.xml", ratio);
|
||||
}
|
||||
|
||||
QVector<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||
QList<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
QVector<const PathRender*> ri;
|
||||
QList<const PathRender*> ri;
|
||||
|
||||
for (int i = 0; i < _paths.size(); i++)
|
||||
if (_paths.at(i).rule().match(zoom, closed, tags))
|
||||
@ -428,6 +517,18 @@ QVector<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||
return ri;
|
||||
}
|
||||
|
||||
QList<const Style::CircleRender *> Style::circles(int zoom,
|
||||
const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
QList<const CircleRender*> ri;
|
||||
|
||||
for (int i = 0; i < _circles.size(); i++)
|
||||
if (_circles.at(i).rule().match(zoom, tags))
|
||||
ri.append(&_circles.at(i));
|
||||
|
||||
return ri;
|
||||
}
|
||||
|
||||
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
|
||||
{
|
||||
QList<const TextRender*> list;
|
||||
@ -519,3 +620,8 @@ QBrush Style::PathRender::brush() const
|
||||
else
|
||||
return Qt::NoBrush;
|
||||
}
|
||||
|
||||
qreal Style::CircleRender::radius(int zoom) const
|
||||
{
|
||||
return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _radius : _radius;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
bool match(bool closed, const QVector<MapData::Tag> &tags) const;
|
||||
bool match(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
bool match(int zoom, const QVector<MapData::Tag> &tags) const;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
@ -163,12 +164,13 @@ public:
|
||||
public:
|
||||
PathRender(const Rule &rule, int zOrder) : Render(rule),
|
||||
_zOrder(zOrder), _strokeWidth(0), _strokeCap(Qt::RoundCap),
|
||||
_strokeJoin(Qt::RoundJoin), _area(false) {}
|
||||
_strokeJoin(Qt::RoundJoin), _area(false), _curve(false) {}
|
||||
|
||||
int zOrder() const {return _zOrder;}
|
||||
QPen pen(int zoom) const;
|
||||
QBrush brush() const;
|
||||
bool area() const {return _area;}
|
||||
bool curve() const {return _curve;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
@ -180,25 +182,49 @@ public:
|
||||
Qt::PenCapStyle _strokeCap;
|
||||
Qt::PenJoinStyle _strokeJoin;
|
||||
QImage _fillImage;
|
||||
bool _area;
|
||||
bool _area, _curve;
|
||||
};
|
||||
|
||||
class CircleRender : public Render
|
||||
{
|
||||
public:
|
||||
CircleRender(const Rule &rule, int zOrder) : Render(rule),
|
||||
_zOrder(zOrder), _pen(Qt::NoPen), _brush(Qt::NoBrush),
|
||||
_scale(false) {}
|
||||
|
||||
int zOrder() const {return _zOrder;}
|
||||
const QPen &pen() const {return _pen;}
|
||||
const QBrush &brush() const {return _brush;}
|
||||
qreal radius(int zoom) const;
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _zOrder;
|
||||
QPen _pen;
|
||||
QBrush _brush;
|
||||
qreal _radius;
|
||||
bool _scale;
|
||||
};
|
||||
|
||||
class TextRender : public Render
|
||||
{
|
||||
public:
|
||||
TextRender(const Rule &rule)
|
||||
: Render(rule), _fillColor(Qt::black), _strokeColor(Qt::black),
|
||||
_strokeWidth(0) {}
|
||||
: Render(rule), _priority(0), _fillColor(Qt::black),
|
||||
_strokeColor(Qt::black), _strokeWidth(0) {}
|
||||
|
||||
const QFont &font() const {return _font;}
|
||||
const QColor &fillColor() const {return _fillColor;}
|
||||
const QColor &strokeColor() const {return _strokeColor;}
|
||||
qreal strokeWidth() const {return _strokeWidth;}
|
||||
const QByteArray &key() const {return _key;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _priority;
|
||||
QColor _fillColor, _strokeColor;
|
||||
qreal _strokeWidth;
|
||||
QFont _font;
|
||||
@ -208,19 +234,23 @@ public:
|
||||
class Symbol : public Render
|
||||
{
|
||||
public:
|
||||
Symbol(const Rule &rule) : Render(rule) {}
|
||||
Symbol(const Rule &rule) : Render(rule), _priority(0) {}
|
||||
|
||||
const QImage &img() const {return _img;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _priority;
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
Style(const QString &path, qreal ratio);
|
||||
|
||||
QVector<const PathRender *> paths(int zoom, bool closed,
|
||||
QList<const PathRender *> paths(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
QList<const CircleRender *> circles(int zoom,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
QList<const TextRender*> pathLabels(int zoom) const;
|
||||
QList<const TextRender*> pointLabels(int zoom) const;
|
||||
@ -230,6 +260,7 @@ public:
|
||||
|
||||
private:
|
||||
QList<PathRender> _paths;
|
||||
QList<CircleRender> _circles;
|
||||
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
||||
QList<Symbol> _symbols;
|
||||
|
||||
@ -243,6 +274,7 @@ private:
|
||||
void area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule);
|
||||
void line(QXmlStreamReader &reader, const Rule &rule);
|
||||
void circle(QXmlStreamReader &reader, const Rule &rule);
|
||||
void text(QXmlStreamReader &reader, const Rule &rule,
|
||||
QList<QList<TextRender> *> &lists);
|
||||
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
|
@ -14,6 +14,7 @@ public:
|
||||
: _file(file), _offset(offset), _size(size), _pos(-1),
|
||||
_blockNum(-1), _blockPos(-1) {}
|
||||
|
||||
quint64 offset() const {return _offset;}
|
||||
quint64 pos() const {return _pos;}
|
||||
bool seek(quint64 pos);
|
||||
|
||||
|