1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-03 22:39:15 +02:00

Compare commits

..

26 Commits
5.11 ... 5.12

Author SHA1 Message Date
bafd0b6af2 Translations update (#118) 2018-05-25 17:16:04 +02:00
eb89ef2f2b Refactoring 2018-05-24 23:19:30 +02:00
f9822b7c78 Translations update 2018-05-24 22:47:28 +02:00
e4feeae064 Improved error handling + code cleanup 2018-05-24 22:11:00 +02:00
31ff81576c Removed asserts from release code 2018-05-24 00:36:27 +02:00
0d879e61a9 Added support for Garmin JNX maps 2018-05-22 22:40:15 +02:00
ba7074f902 Version++ 2018-05-20 21:47:29 +02:00
f371500570 Fixed graph resize glitches 2018-05-20 19:38:01 +02:00
7324535bfc Some more code cleanup 2018-05-19 22:36:11 +02:00
59c95e53c4 Precompute some more constants 2018-05-19 20:55:43 +02:00
a66ca7b3a8 Includes cleanup 2018-05-19 20:32:00 +02:00
273a918ed9 Precache font related info 2018-05-19 20:30:29 +02:00
7198d610c5 Code cleanup 2018-05-18 22:22:36 +02:00
a6389f0174 Precompute e2s as well 2018-05-18 22:10:43 +02:00
d9c922aa47 Do not cache the grid, drawing it is faster 2018-05-18 20:11:41 +02:00
0156d2fbc0 Precompute all compute-intensive stuff 2018-05-18 20:08:52 +02:00
650eb1c302 Optimization/code cleanup 2018-05-18 01:38:33 +02:00
33919c501c Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-05-18 00:22:35 +02:00
be9da5aabe Some more naming unification 2018-05-18 00:21:59 +02:00
f341219613 Update gpxsee_sv.ts (#115) 2018-05-18 00:00:08 +02:00
a486f9e78d Datum shift optimization (precompute ellipsoid constants)
+ projections code unification
2018-05-17 22:41:56 +02:00
b3940283a8 Update Polish translation file. (#114) 2018-05-16 22:08:21 +02:00
74aebce357 Code cleanup 2018-05-16 22:01:21 +02:00
0cd6a82a0f Added support for Garmin route extension
Resolves #112
2018-05-16 21:53:06 +02:00
81a5c712c6 Projection error handling cleanup 2018-05-16 18:52:48 +02:00
025a403c73 PI defines cleanup 2018-05-15 21:51:56 +02:00
67 changed files with 969 additions and 716 deletions

View File

@ -1,4 +1,4 @@
version: 5.11.{build}
version: 5.12.{build}
configuration: Release
platform: Any CPU
environment:

View File

@ -1,5 +1,5 @@
TARGET = GPXSee
VERSION = 5.11
VERSION = 5.12
QT += core \
gui \
network
@ -15,6 +15,7 @@ HEADERS += src/config.h \
src/common/rectc.h \
src/common/wgs84.h \
src/common/str2int.h \
src/common/rtree.h \
src/GUI/app.h \
src/GUI/icons.h \
src/GUI/gui.h \
@ -117,7 +118,6 @@ HEADERS += src/config.h \
src/data/trackdata.h \
src/data/routedata.h \
src/data/path.h \
src/data/rtree.h \
src/data/gpxparser.h \
src/data/tcxparser.h \
src/data/csvparser.h \
@ -128,7 +128,8 @@ HEADERS += src/config.h \
src/data/oziparsers.h \
src/map/rectd.h \
src/map/geocentric.h \
src/map/mercator.h
src/map/mercator.h \
src/map/jnxmap.h
SOURCES += src/main.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
@ -224,7 +225,8 @@ SOURCES += src/main.cpp \
src/data/nmeaparser.cpp \
src/data/oziparsers.cpp \
src/map/geocentric.cpp \
src/map/mercator.cpp
src/map/mercator.cpp \
src/map/jnxmap.cpp
RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_cs.ts \
lang/gpxsee_sv.ts \
@ -271,5 +273,6 @@ win32 {
icons/plt.ico \
icons/rte.ico \
icons/wpt.ico
DEFINES += _USE_MATH_DEFINES
}
DEFINES += APP_VERSION=\\\"$$VERSION\\\"

View File

@ -884,27 +884,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Podporované soubory</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation>Garmin JNX mapy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>OziExplorer mapy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy mapy/atlasy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF obrázky</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Online mapové zdroje</translation>
</message>
@ -1366,28 +1371,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>nmi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -883,27 +883,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Unterstütze Dateien</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation>Garmin JNX Karten</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>OziExplorer Karten</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy Karten/Atlanten</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF Bilder</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Online-Kartenquellen</translation>
</message>
@ -1365,28 +1370,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>nmi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -883,27 +883,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Tuetut tiedostot</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation>Garmin JNX -kartat</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>OziExplorer -kartat</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy -kartat/kartastot</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF -kuvat</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Online-karttojen lähteet</translation>
</message>
@ -1365,28 +1370,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>mpk</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -883,27 +883,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Formats pris en charge</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>Cartes OziExplorer</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>Cartes ou atlas TrekBuddy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>Images GeoTIFF</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Cartes en ligne</translation>
</message>
@ -1365,28 +1370,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>pied</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>nmi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -884,27 +884,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Obsługiwane pliki</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>Mapy OziExplorer</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>Mapy/atlasy TrekBuddy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>Obrazy GeoTIFF</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Źródła map online</translation>
</message>
@ -1273,7 +1278,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="442"/>
<source>Connection timeout:</source>
<translation type="unfinished"></translation>
<translation>Limit czasu połączenia:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="455"/>
@ -1366,28 +1371,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>nmi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -884,27 +884,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Все поддерживаемые файлы</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation>Garmin JNX карты</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>OziExplorer карты</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy карты/атласы</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF изображения</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Источники онлайн карт</translation>
</message>
@ -1366,28 +1371,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>мл</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>фт</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>мор. мл</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>км</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>м</translation>
</message>

View File

@ -883,27 +883,32 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<location filename="../src/map/maplist.cpp" line="111"/>
<source>Supported files</source>
<translation>Filer som stöds</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<location filename="../src/map/maplist.cpp" line="112"/>
<source>Garmin JNX maps</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="113"/>
<source>OziExplorer maps</source>
<translation>OziExplorer-kartor</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<location filename="../src/map/maplist.cpp" line="114"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy-kartor/-atlaser</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="133"/>
<location filename="../src/map/maplist.cpp" line="115"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF-bilder</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="134"/>
<location filename="../src/map/maplist.cpp" line="116"/>
<source>Online map sources</source>
<translation>Online-kartkällor</translation>
</message>
@ -1272,7 +1277,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="442"/>
<source>Connection timeout:</source>
<translation type="unfinished"></translation>
<translation>Anslutningens tidsgräns:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="455"/>
@ -1365,28 +1370,28 @@
<context>
<name>ScaleItem</name>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="83"/>
<location filename="../src/GUI/scaleitem.cpp" line="111"/>
<source>mi</source>
<translation>mi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="84"/>
<location filename="../src/GUI/scaleitem.cpp" line="87"/>
<location filename="../src/GUI/scaleitem.cpp" line="112"/>
<location filename="../src/GUI/scaleitem.cpp" line="115"/>
<source>ft</source>
<translation>ft</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/>
<location filename="../src/GUI/scaleitem.cpp" line="114"/>
<source>nmi</source>
<translation>nmi</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/>
<location filename="../src/GUI/scaleitem.cpp" line="117"/>
<source>km</source>
<translation>km</translation>
</message>
<message>
<location filename="../src/GUI/scaleitem.cpp" line="90"/>
<location filename="../src/GUI/scaleitem.cpp" line="118"/>
<source>m</source>
<translation>m</translation>
</message>

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "5.11"
!define VERSION "5.12"
; The file to write
OutFile "GPXSee-${VERSION}.exe"

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "5.11"
!define VERSION "5.12"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -11,23 +11,28 @@
#define XTICKS 15
#define YTICKS 10
struct Label {
double min;
double max;
double d;
class Ticks
{
public:
Ticks(double minValue, double maxValue, int maxCount);
int count() const {return ((int)((_max - _min) / _d)) + 1;}
double val(int i) const {return _min + i * _d;}
double min() const {return _min;}
double max() const {return _max;}
private:
double _min;
double _max;
double _d;
};
static struct Label label(double min, double max, int ticks)
Ticks::Ticks(double minValue, double maxValue, int maxCount)
{
double range;
struct Label l;
range = niceNum(max - min, 0);
l.d = niceNum(range / ticks, 1);
l.min = ceil(min / l.d) * l.d;
l.max = floor(max / l.d) * l.d;
return l;
double range = niceNum(maxValue - minValue, 0);
_d = niceNum(range / maxCount, 1);
_min = ceil(minValue / _d) * _d;
_max = floor(maxValue / _d) * _d;
}
@ -36,6 +41,9 @@ AxisItem::AxisItem(Type type, QGraphicsItem *parent) : QGraphicsItem(parent)
_type = type;
_size = 0;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
#ifndef Q_OS_MAC
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
#endif // Q_OS_MAC
@ -45,6 +53,16 @@ void AxisItem::setRange(const RangeF &range)
{
prepareGeometryChange();
_range = range;
QFontMetrics fm(_font);
Ticks ticks(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
_ticks = QVector<Tick>(ticks.count());
for (int i = 0; i < ticks.count(); i++) {
Tick &t = _ticks[i];
t.value = ticks.val(i);
t.boundingBox = fm.tightBoundingRect(QString::number(t.value));
}
updateBoundingRect();
update();
}
@ -60,42 +78,28 @@ void AxisItem::setSize(qreal size)
void AxisItem::setLabel(const QString& label)
{
prepareGeometryChange();
QFontMetrics fm(_font);
_label = label;
_labelBB = fm.tightBoundingRect(label);
updateBoundingRect();
update();
}
void AxisItem::updateBoundingRect()
{
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QRect ss, es, ls;
struct Label l;
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
es = fm.tightBoundingRect(QString::number(l.max));
ss = fm.tightBoundingRect(QString::number(l.min));
ls = fm.tightBoundingRect(_label);
QFontMetrics fm(_font);
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
QRect ls(_labelBB);
if (_type == X) {
_boundingRect = QRectF(-ss.width()/2, -TICK/2,
_size + es.width()/2 + ss.width()/2,
ls.height() + es.height() - fm.descent() + TICK + 2*PADDING + 1);
_boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2
+ ss.width()/2, ls.height() + es.height() - fm.descent() + TICK
+ 2*PADDING + 1);
} else {
int mtw = 0;
QRect ts;
qreal val;
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
val = l.min + i * l.d;
QString str = QString::number(val);
ts = fm.tightBoundingRect(str);
mtw = qMax(ts.width(), mtw);
}
for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING + TICK/2),
-(_size + es.height()/2 + fm.descent()), ls.height() + mtw + 2*PADDING
+ TICK, _size + es.height()/2 + fm.descent() + ss.height()/2);
@ -107,60 +111,50 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QRect ts, ls;
struct Label l;
qreal range = _range.size();
qreal val;
QPen pen = QPen(Qt::black, AXIS_WIDTH);
QFontMetrics fm(_font);
QRect ts;
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setFont(font);
painter->setPen(pen);
ls = fm.tightBoundingRect(_label);
painter->setFont(_font);
painter->setPen(QPen(Qt::black, AXIS_WIDTH));
if (_type == X) {
painter->drawLine(0, 0, _size, 0);
l = label(_range.min(), _range.max(), XTICKS);
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
val = l.min + i * l.d;
QString str = QString::number(val);
for (int i = 0; i < _ticks.count(); i++) {
qreal val = _ticks.at(i).value;
ts = _ticks.at(i).boundingBox;
painter->drawLine((_size/range) * (val - _range.min()), TICK/2,
(_size/range) * (val - _range.min()), -TICK/2);
ts = fm.tightBoundingRect(str);
painter->drawText(((_size/range) * (val - _range.min()))
- (ts.width()/2), ts.height() + TICK/2 + PADDING, str);
painter->drawLine((_size/_range.size()) * (val - _range.min()),
TICK/2, (_size/_range.size()) * (val - _range.min()), -TICK/2);
painter->drawText(((_size/_range.size()) * (val - _range.min()))
- (ts.width()/2), ts.height() + TICK/2 + PADDING,
QString::number(val));
}
painter->drawText(_size/2 - ls.width()/2, ls.height() + ts.height()
- 2*fm.descent() + TICK/2 + 2*PADDING, _label);
painter->drawText(_size/2 - _labelBB.width()/2, _labelBB.height()
+ ts.height() - 2*fm.descent() + TICK/2 + 2*PADDING, _label);
} else {
painter->drawLine(0, 0, 0, -_size);
l = label(_range.min(), _range.max(), YTICKS);
int mtw = 0;
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
val = l.min + i * l.d;
QString str = QString::number(val);
painter->drawLine(TICK/2, -((_size/range) * (val - _range.min())),
-TICK/2, -((_size/range) * (val - _range.min())));
ts = fm.tightBoundingRect(str);
for (int i = 0; i < _ticks.count(); i++) {
qreal val = _ticks.at(i).value;
ts = _ticks.at(i).boundingBox;
mtw = qMax(ts.width(), mtw);
painter->drawText(-(ts.width() + PADDING + TICK/2), -((_size/range)
* (val - _range.min())) + (ts.height()/2), str);
painter->drawLine(TICK/2, -((_size/_range.size())
* (val - _range.min())), -TICK/2, -((_size/_range.size())
* (val - _range.min())));
painter->drawText(-(ts.width() + PADDING + TICK/2),
-((_size/_range.size()) * (val - _range.min())) + (ts.height()/2),
QString::number(val));
}
painter->rotate(-90);
painter->drawText(_size/2 - ls.width()/2, -(mtw + 2*PADDING + TICK/2),
_label);
painter->drawText(_size/2 - _labelBB.width()/2, -(mtw + 2*PADDING
+ TICK/2), _label);
painter->rotate(90);
}
@ -172,46 +166,28 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QSizeF AxisItem::margin() const
{
QFont font;
font.setPixelSize(FONT_SIZE);
QFontMetrics fm(font);
QRect ss, es, ls;
struct Label l;
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
es = fm.tightBoundingRect(QString::number(l.max));
ss = fm.tightBoundingRect(QString::number(l.min));
ls = fm.tightBoundingRect(_label);
QFontMetrics fm(_font);
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
if (_type == X) {
return QSizeF(es.width()/2,
ls.height() + es.height() - fm.descent() + TICK/2 + 2*PADDING);
return QSizeF(es.width()/2, _labelBB.height() + es.height()
- fm.descent() + TICK/2 + 2*PADDING);
} else {
int mtw = 0;
QRect ts;
qreal val;
for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
val = l.min + i * l.d;
QString str = QString::number(val);
ts = fm.tightBoundingRect(str);
mtw = qMax(ts.width(), mtw);
}
return QSizeF(ls.height() -fm.descent() + mtw + 2*PADDING
return QSizeF(_labelBB.height() -fm.descent() + mtw + 2*PADDING
+ TICK/2, es.height()/2 + fm.descent());
}
}
QList<qreal> AxisItem::ticks() const
{
struct Label l;
QList<qreal> list;
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++)
list.append(((_size/_range.size()) * ((l.min + i * l.d)
for (int i = 0; i < _ticks.count(); i++)
list.append(((_size/_range.size()) * (_ticks.at(i).value
- _range.min())));
return list;

View File

@ -2,6 +2,7 @@
#define AXISITEM_H
#include <QGraphicsItem>
#include <QVector>
#include "common/range.h"
class AxisItem : public QGraphicsItem
@ -23,13 +24,21 @@ public:
QList<qreal> ticks() const;
private:
struct Tick {
double value;
QRect boundingBox;
};
void updateBoundingRect();
Type _type;
RangeF _range;
qreal _size;
QString _label;
QRect _labelBB;
QVector<Tick> _ticks;
QRectF _boundingRect;
QFont _font;
};
#endif // AXISITEM_H

View File

@ -308,6 +308,7 @@ void GraphView::redraw(const QSizeF &size)
if (r.height() < _minYRange * sy)
r.adjust(0, -(_minYRange/2 * sy - r.height()/2), 0,
(_minYRange/2) * sy - r.height()/2);
r = r.toRect();
_xAxis->setSize(r.width());
_yAxis->setSize(r.height());

View File

@ -4,13 +4,6 @@
#define GRID_WIDTH 0
GridItem::GridItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
#ifndef Q_OS_MAC
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
#endif // Q_OS_MAC
}
void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{

View File

@ -6,7 +6,7 @@
class GridItem : public QGraphicsItem
{
public:
GridItem(QGraphicsItem *parent = 0);
GridItem(QGraphicsItem *parent = 0): QGraphicsItem(parent) {}
QRectF boundingRect() const {return _boundingRect;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,

View File

@ -7,6 +7,9 @@
InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
#ifndef Q_OS_MAC
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
#endif // Q_OS_MAC
@ -14,16 +17,14 @@ InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
void InfoItem::updateBoundingRect()
{
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QList<KV>::const_iterator i;
QFontMetrics fm(_font);
qreal width = 0;
for (i = _list.constBegin(); i != _list.constEnd(); i++) {
for (QList<KV>::const_iterator i = _list.constBegin();
i != _list.constEnd(); i++) {
width += fm.width(i->key + ": ");
width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
width += fm.width(i->value) + ((i == _list.constEnd() - 1)
? 0 : PADDING);
}
_boundingRect = QRectF(0, 0, width, _list.isEmpty() ? 0 : fm.height());
@ -34,22 +35,19 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
painter->setFont(font);
QFontMetrics fm(font);
QList<KV>::const_iterator i;
QFontMetrics fm(_font);
int width = 0;
painter->setFont(_font);
painter->setRenderHint(QPainter::Antialiasing, false);
for (i = _list.constBegin(); i != _list.constEnd(); i++) {
for (QList<KV>::const_iterator i = _list.constBegin();
i != _list.constEnd(); i++) {
painter->drawText(width, fm.height() - fm.descent(), i->key + ": ");
width += fm.width(i->key + ": ");
painter->drawText(width, fm.height() - fm.descent(), i->value);
width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
width += fm.width(i->value) + ((i == _list.constEnd() - 1)
? 0 : PADDING);
if (i != _list.constEnd() - 1) {
painter->save();
painter->setPen(Qt::gray);

View File

@ -33,6 +33,7 @@ private:
QList<KV> _list;
QRectF _boundingRect;
QFont _font;
};
#endif // INFOITEM_H

View File

@ -75,7 +75,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_plot = false;
_digitalZoom = 0;
_map->setBackgroundColor(_backgroundColor);
_res = _map->resolution(_map->bounds());
_scene->setSceneRect(_map->bounds());
@ -267,7 +266,6 @@ void MapView::setMap(Map *map)
_map = map;
_map->load();
_map->setBackgroundColor(_backgroundColor);
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
digitalZoom(0);
@ -746,7 +744,6 @@ void MapView::setMapOpacity(int opacity)
void MapView::setBackgroundColor(const QColor &color)
{
_backgroundColor = color;
_map->setBackgroundColor(color);
resetCachedContent();
}

View File

@ -18,52 +18,34 @@ ScaleItem::ScaleItem(QGraphicsItem *parent) : QGraphicsItem(parent)
_res = 1.0;
_digitalZoom = 0;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
#ifndef Q_OS_MAC
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
#endif // Q_OS_MAC
}
void ScaleItem::updateBoundingRect()
{
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QRect ss, es, us;
ss = fm.tightBoundingRect(QString::number(0));
es = fm.tightBoundingRect(QString::number(_length * SEGMENTS));
us = fm.tightBoundingRect(units());
_boundingRect = QRectF(-ss.width()/2, 0, _width * SEGMENTS + ss.width()/2
+ qMax(us.width() + PADDING, es.width()/2) + 1, SCALE_HEIGHT + PADDING
+ ss.height() + 2*fm.descent());
}
void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QFontMetrics fm(_font);
QRect br;
QPen pen = QPen(Qt::black, BORDER_WIDTH);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setFont(font);
painter->setPen(pen);
painter->setFont(_font);
painter->setPen(QPen(Qt::black, BORDER_WIDTH));
for (int i = 0; i <= SEGMENTS; i++) {
QString label = QString::number(_length * i);
br = fm.tightBoundingRect(label);
painter->drawText(_width * i - br.width()/2, br.height() + 1, label);
for (int i = 0; i < _ticks.size(); i++) {
br = _ticks.at(i).boundingBox;
painter->drawText(_width * i - br.width()/2, br.height() + 1,
QString::number(_ticks.at(i).value));
}
painter->drawText(_width * SEGMENTS + PADDING, SCALE_HEIGHT + PADDING
+ br.height() + fm.descent(), units());
+ br.height() + fm.descent(), _unitsStr);
painter->drawRect(QRectF(0, br.height() + PADDING, SEGMENTS * _width,
SCALE_HEIGHT));
@ -77,19 +59,6 @@ void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
*/
}
QString ScaleItem::units() const
{
if (_units == Imperial)
return _scale ? qApp->translate("ScaleItem", "mi")
: qApp->translate("ScaleItem", "ft");
else if (_units == Nautical)
return _scale ? qApp->translate("ScaleItem", "nmi")
: qApp->translate("ScaleItem", "ft");
else
return _scale ? qApp->translate("ScaleItem", "km")
: qApp->translate("ScaleItem", "m");
}
void ScaleItem::computeScale()
{
qreal res = _res * pow(2, -_digitalZoom);
@ -127,21 +96,50 @@ void ScaleItem::computeScale()
}
}
void ScaleItem::updateCache()
{
QFontMetrics fm(_font);
_ticks = QVector<Tick>(SEGMENTS + 1);
for (int i = 0; i < _ticks.size(); i++) {
Tick &t = _ticks[i];
t.value = _length * i;
t.boundingBox = fm.tightBoundingRect(QString::number(t.value));
}
if (_units == Imperial)
_unitsStr = _scale ? qApp->translate("ScaleItem", "mi")
: qApp->translate("ScaleItem", "ft");
else if (_units == Nautical)
_unitsStr = _scale ? qApp->translate("ScaleItem", "nmi")
: qApp->translate("ScaleItem", "ft");
else
_unitsStr = _scale ? qApp->translate("ScaleItem", "km")
: qApp->translate("ScaleItem", "m");
_unitsBB = fm.tightBoundingRect(_unitsStr);
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
_boundingRect = QRectF(-ss.width()/2, 0, _width * SEGMENTS + ss.width()/2
+ qMax(_unitsBB.width() + PADDING, es.width()/2) + 1, SCALE_HEIGHT
+ PADDING + ss.height() + 2*fm.descent());
}
void ScaleItem::setResolution(qreal res)
{
prepareGeometryChange();
_res = res;
computeScale();
updateBoundingRect();
updateCache();
update();
}
void ScaleItem::setUnits(enum Units units)
void ScaleItem::setUnits(Units units)
{
prepareGeometryChange();
_units = units;
computeScale();
updateBoundingRect();
updateCache();
update();
}
@ -150,7 +148,7 @@ void ScaleItem::setDigitalZoom(qreal zoom)
prepareGeometryChange();
_digitalZoom = zoom;
computeScale();
updateBoundingRect();
updateCache();
update();
setScale(pow(2, -_digitalZoom));

View File

@ -14,23 +14,29 @@ public:
QWidget *widget);
void setResolution(qreal res);
void setUnits(enum Units units);
void setUnits(Units units);
void setDigitalZoom(qreal zoom);
private:
void updateBoundingRect();
struct Tick {
double value;
QRect boundingBox;
};
void computeScale();
QString units() const;
void updateCache();
qreal _res;
qreal _width;
qreal _length;
Units _units;
bool _scale;
qreal _digitalZoom;
QRectF _boundingRect;
QFont _font;
QVector<Tick> _ticks;
QRect _unitsBB;
QString _unitsStr;
};
#endif // SCALEITEM_H

View File

@ -9,14 +9,14 @@ SliderInfoItem::SliderInfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_side = Right;
_color = Qt::red;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
}
void SliderInfoItem::updateBoundingRect()
{
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QFontMetrics fm(_font);
qreal width = qMax(fm.width(_x), fm.width(_y));
qreal height = 2 * fm.height() - 2*fm.descent();
@ -31,10 +31,7 @@ void SliderInfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont font;
font.setPixelSize(FONT_SIZE);
font.setFamily(FONT_FAMILY);
QFontMetrics fm(font);
QFontMetrics fm(_font);
QRectF rx, ry;
@ -57,7 +54,7 @@ void SliderInfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
painter->drawRect(rx);
painter->setBrush(Qt::NoBrush);
painter->setFont(font);
painter->setFont(_font);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setPen(_color);

View File

@ -25,6 +25,7 @@ private:
QString _x, _y;
QRectF _boundingRect;
QColor _color;
QFont _font;
};
#endif // SLIDERINFOITEM_H

View File

@ -36,11 +36,13 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
{
_waypoint = waypoint;
_showLabel = true;
_hover = false;
_size = 8;
_color = Qt::black;
updateShape();
_font.setPixelSize(FS(_size));
_font.setFamily(FONT_FAMILY);
updateCache();
setPos(map->ll2xy(waypoint.coordinates()));
setToolTip(toolTip(Metric, DecimalDegrees));
@ -48,23 +50,18 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
setAcceptHoverEvents(true);
}
void WaypointItem::updateShape()
void WaypointItem::updateCache()
{
QPainterPath p;
qreal pointSize = _hover ? HS(_size) : _size;
qreal pointSize = _font.bold() ? HS(_size) : _size;
if (_showLabel) {
QFont font;
font.setPixelSize(FS(_size));
font.setFamily(FONT_FAMILY);
if (_hover)
font.setBold(true);
QFontMetrics fm(font);
QRect ts = fm.tightBoundingRect(_waypoint.name());
QFontMetrics fm(_font);
_labelBB = fm.tightBoundingRect(_waypoint.name());
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
p.addRect(pointSize/2, pointSize/2,
ts.width(), ts.height() + fm.descent());
p.addRect(pointSize/2, pointSize/2, _labelBB.width(), _labelBB.height()
+ fm.descent());
} else
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
@ -76,23 +73,14 @@ void WaypointItem::paint(QPainter *painter,
{
Q_UNUSED(option);
Q_UNUSED(widget);
qreal pointSize = _hover ? HS(_size) : _size;
qreal pointSize = _font.bold() ? HS(_size) : _size;
painter->setPen(_color);
if (_showLabel) {
QFont font;
font.setPixelSize(FS(_size));
font.setFamily(FONT_FAMILY);
if (_hover)
font.setBold(true);
QFontMetrics fm(font);
QRect ts = fm.tightBoundingRect(_waypoint.name());
painter->setFont(font);
painter->drawText(pointSize/2 - qMax(ts.x(), 0), pointSize/2
+ ts.height(), _waypoint.name());
painter->setFont(_font);
painter->drawText(pointSize/2 - qMax(_labelBB.x(), 0), pointSize/2
+ _labelBB.height(), _waypoint.name());
}
painter->setBrush(QBrush(_color, Qt::SolidPattern));
@ -112,7 +100,8 @@ void WaypointItem::setSize(int size)
prepareGeometryChange();
_size = size;
updateShape();
_font.setPixelSize(FS(_size));
updateCache();
}
void WaypointItem::setColor(const QColor &color)
@ -136,7 +125,7 @@ void WaypointItem::showLabel(bool show)
prepareGeometryChange();
_showLabel = show;
updateShape();
updateCache();
}
void WaypointItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
@ -144,8 +133,8 @@ void WaypointItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Q_UNUSED(event);
prepareGeometryChange();
_hover = true;
updateShape();
_font.setBold(true);
updateCache();
setZValue(zValue() + 1.0);
}
@ -154,7 +143,7 @@ void WaypointItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Q_UNUSED(event);
prepareGeometryChange();
_hover = false;
updateShape();
_font.setBold(false);
updateCache();
setZValue(zValue() - 1.0);
}

View File

@ -31,16 +31,16 @@ private:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void updateShape();
void updateCache();
QString toolTip(Units units, CoordinatesFormat format);
QPainterPath _shape;
Waypoint _waypoint;
QPainterPath _shape;
QColor _color;
int _size;
bool _hover;
bool _showLabel;
QFont _font;
QRect _labelBB;
};
#endif // WAYPOINTITEM_H

View File

@ -4,9 +4,6 @@
#include <cmath>
#include <QDebug>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif // M_PI
#define deg2rad(d) (((d)*M_PI)/180.0)
#define rad2deg(d) (((d)*180.0)/M_PI)

View File

@ -20,10 +20,10 @@ RectC::RectC(const Coordinates &center, double radius)
double deltaLon = asin(sin(radDist) / cos(radlat));
minLon = radLon - deltaLon;
if (minLon < MIN_LON)
minLon += 2.0 * M_PI;
minLon += M_2_PI;
maxLon = radLon + deltaLon;
if (maxLon > MAX_LON)
maxLon -= 2.0 * M_PI;
maxLon -= M_2_PI;
} else {
// a pole is within the distance
minLat = qMax(minLat, MIN_LAT);

View File

@ -3,15 +3,9 @@
#include <cstdio>
#include <cmath>
#include <cassert>
#include <cstdlib>
#include <QtGlobal>
#define ASSERT assert // RTree uses ASSERT( condition )
#define Max(a,b) \
(((a) > (b)) ? (a) : (b))
#define Min(a,b) \
(((a) < (b)) ? (a) : (b))
#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, \
class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
@ -129,7 +123,7 @@ public:
/// Access the current data element.
DATATYPE& operator*()
{
ASSERT(IsNotNull());
Q_ASSERT(IsNotNull());
StackElement& curTos = m_stack[m_tos - 1];
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
}
@ -137,7 +131,7 @@ public:
/// Access the current data element.
const DATATYPE& operator*() const
{
ASSERT(IsNotNull());
Q_ASSERT(IsNotNull());
StackElement& curTos = m_stack[m_tos - 1];
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
}
@ -148,7 +142,7 @@ public:
/// Get the bounds for this node
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
{
ASSERT(IsNotNull());
Q_ASSERT(IsNotNull());
StackElement& curTos = m_stack[m_tos - 1];
Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
@ -206,13 +200,13 @@ public:
m_stack[m_tos].m_node = a_node;
m_stack[m_tos].m_branchIndex = a_branchIndex;
++m_tos;
ASSERT(m_tos <= MAX_STACK);
Q_ASSERT(m_tos <= MAX_STACK);
}
// Pop element off iteration stack
StackElement& Pop()
{
ASSERT(m_tos > 0);
Q_ASSERT(m_tos > 0);
--m_tos;
return m_stack[m_tos];
}
@ -356,12 +350,12 @@ protected:
RTREE_TEMPLATE
RTREE_QUAL::RTree()
{
ASSERT(MAXNODES > MINNODES);
ASSERT(MINNODES > 0);
Q_ASSERT(MAXNODES > MINNODES);
Q_ASSERT(MINNODES > 0);
// We only support machine word size simple data type eg. integer index or
// object pointer. Since we are storing as union with non data branch
ASSERT(sizeof(DATATYPE) == sizeof(void*) || sizeof(DATATYPE) == sizeof(int));
Q_ASSERT(sizeof(DATATYPE) == sizeof(void*) || sizeof(DATATYPE) == sizeof(int));
// Precomputed volumes of the unit spheres for the first few dimensions
const float UNIT_SPHERE_VOLUMES[] = {
@ -393,7 +387,7 @@ void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS],
{
#ifdef _DEBUG
for (int index=0; index<NUMDIMS; ++index)
ASSERT(a_min[index] <= a_max[index]);
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
Rect rect;
@ -413,7 +407,7 @@ void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS],
{
#ifdef _DEBUG
for (int index=0; index<NUMDIMS; ++index)
ASSERT(a_min[index] <= a_max[index]);
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
Rect rect;
@ -433,7 +427,7 @@ int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDI
{
#ifdef _DEBUG
for (int index=0; index<NUMDIMS; ++index)
ASSERT(a_min[index] <= a_max[index]);
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
Rect rect;
@ -502,8 +496,8 @@ void RTREE_QUAL::Reset()
RTREE_TEMPLATE
void RTREE_QUAL::RemoveAllRec(Node* a_node)
{
ASSERT(a_node);
ASSERT(a_node->m_level >= 0);
Q_ASSERT(a_node);
Q_ASSERT(a_node->m_level >= 0);
if (a_node->IsInternalNode()) { // This is an internal node in the tree
for (int index=0; index < a_node->m_count; ++index)
@ -530,7 +524,7 @@ typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
RTREE_TEMPLATE
void RTREE_QUAL::FreeNode(Node* a_node)
{
ASSERT(a_node);
Q_ASSERT(a_node);
#ifdef RTREE_DONT_USE_MEMPOOLS
delete a_node;
@ -593,8 +587,8 @@ RTREE_TEMPLATE
bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
Node** a_newNode, int a_level)
{
ASSERT(a_rect && a_node && a_newNode);
ASSERT(a_level >= 0 && a_level <= a_node->m_level);
Q_ASSERT(a_rect && a_node && a_newNode);
Q_ASSERT(a_level >= 0 && a_level <= a_node->m_level);
int index;
Branch branch;
@ -621,7 +615,7 @@ bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
return AddBranch(&branch, a_node, a_newNode);
} else {
// Should never occur
ASSERT(0);
Q_ASSERT(0);
return false;
}
}
@ -638,11 +632,11 @@ RTREE_TEMPLATE
bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
int a_level)
{
ASSERT(a_rect && a_root);
ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
Q_ASSERT(a_rect && a_root);
Q_ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
#ifdef _DEBUG
for (int index=0; index < NUMDIMS; ++index)
ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
Q_ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
#endif //_DEBUG
Node* newRoot;
@ -672,7 +666,7 @@ bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
RTREE_TEMPLATE
typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
{
ASSERT(a_node);
Q_ASSERT(a_node);
int firstTime = true;
Rect rect;
@ -698,8 +692,8 @@ typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
RTREE_TEMPLATE
bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
{
ASSERT(a_branch);
ASSERT(a_node);
Q_ASSERT(a_branch);
Q_ASSERT(a_node);
if (a_node->m_count < MAXNODES) { // Split won't be necessary
a_node->m_branch[a_node->m_count] = *a_branch;
@ -707,7 +701,7 @@ bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
return false;
} else {
ASSERT(a_newNode);
Q_ASSERT(a_newNode);
SplitNode(a_node, a_branch, a_newNode);
return true;
@ -721,8 +715,8 @@ bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
RTREE_TEMPLATE
void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
{
ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
ASSERT(a_node->m_count > 0);
Q_ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
Q_ASSERT(a_node->m_count > 0);
// Remove element by swapping with the last element to prevent gaps in array
a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
@ -739,7 +733,7 @@ void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
RTREE_TEMPLATE
int RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node)
{
ASSERT(a_rect && a_node);
Q_ASSERT(a_rect && a_node);
bool firstTime = true;
ELEMTYPEREAL increase;
@ -774,13 +768,13 @@ int RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node)
RTREE_TEMPLATE
typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB)
{
ASSERT(a_rectA && a_rectB);
Q_ASSERT(a_rectA && a_rectB);
Rect newRect;
for (int index = 0; index < NUMDIMS; ++index) {
newRect.m_min[index] = Min(a_rectA->m_min[index], a_rectB->m_min[index]);
newRect.m_max[index] = Max(a_rectA->m_max[index], a_rectB->m_max[index]);
newRect.m_min[index] = qMin(a_rectA->m_min[index], a_rectB->m_min[index]);
newRect.m_max[index] = qMax(a_rectA->m_max[index], a_rectB->m_max[index]);
}
return newRect;
@ -795,8 +789,8 @@ typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB)
RTREE_TEMPLATE
void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
{
ASSERT(a_node);
ASSERT(a_branch);
Q_ASSERT(a_node);
Q_ASSERT(a_branch);
// Could just use local here, but member or external is faster since it is
// reused
@ -816,7 +810,7 @@ void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
(*a_newNode)->m_level = a_node->m_level = level;
LoadNodes(a_node, *a_newNode, parVars);
ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
Q_ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
}
@ -824,14 +818,14 @@ void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
RTREE_TEMPLATE
ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
{
ASSERT(a_rect);
Q_ASSERT(a_rect);
ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
for (int index=0; index<NUMDIMS; ++index)
volume *= a_rect->m_max[index] - a_rect->m_min[index];
ASSERT(volume >= (ELEMTYPEREAL)0);
Q_ASSERT(volume >= (ELEMTYPEREAL)0);
return volume;
}
@ -841,7 +835,7 @@ ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
RTREE_TEMPLATE
ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
{
ASSERT(a_rect);
Q_ASSERT(a_rect);
ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
ELEMTYPEREAL radius;
@ -881,10 +875,10 @@ RTREE_TEMPLATE
void RTREE_QUAL::GetBranches(Node* a_node, Branch* a_branch,
PartitionVars* a_parVars)
{
ASSERT(a_node);
ASSERT(a_branch);
Q_ASSERT(a_node);
Q_ASSERT(a_branch);
ASSERT(a_node->m_count == MAXNODES);
Q_ASSERT(a_node->m_count == MAXNODES);
// Load the branch buffer
for (int index=0; index < MAXNODES; ++index)
@ -917,7 +911,7 @@ void RTREE_QUAL::GetBranches(Node* a_node, Branch* a_branch,
RTREE_TEMPLATE
void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
{
ASSERT(a_parVars);
Q_ASSERT(a_parVars);
ELEMTYPEREAL biggestDiff;
int group, chosen = 0, betterGroup = 0;
@ -973,8 +967,8 @@ void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
}
}
ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
Q_ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
Q_ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
(a_parVars->m_count[1] >= a_parVars->m_minFill));
}
@ -983,12 +977,12 @@ void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
RTREE_TEMPLATE
void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
{
ASSERT(a_nodeA);
ASSERT(a_nodeB);
ASSERT(a_parVars);
Q_ASSERT(a_nodeA);
Q_ASSERT(a_nodeB);
Q_ASSERT(a_parVars);
for (int index=0; index < a_parVars->m_total; ++index) {
ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
Q_ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
if (a_parVars->m_partition[index] == 0)
AddBranch(&a_parVars->m_branchBuf[index], a_nodeA, NULL);
@ -1003,7 +997,7 @@ RTREE_TEMPLATE
void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects,
int a_minFill)
{
ASSERT(a_parVars);
Q_ASSERT(a_parVars);
a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
@ -1049,8 +1043,8 @@ void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
RTREE_TEMPLATE
void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
{
ASSERT(a_parVars);
ASSERT(!a_parVars->m_taken[a_index]);
Q_ASSERT(a_parVars);
Q_ASSERT(!a_parVars->m_taken[a_index]);
a_parVars->m_partition[a_index] = a_group;
a_parVars->m_taken[a_index] = true;
@ -1073,8 +1067,8 @@ void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
RTREE_TEMPLATE
bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
{
ASSERT(a_rect && a_root);
ASSERT(*a_root);
Q_ASSERT(a_rect && a_root);
Q_ASSERT(*a_root);
Node* tempNode;
ListNode* reInsertList = NULL;
@ -1100,7 +1094,7 @@ bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode()) {
tempNode = (*a_root)->m_branch[0].m_child;
ASSERT(tempNode);
Q_ASSERT(tempNode);
FreeNode(*a_root);
*a_root = tempNode;
}
@ -1119,8 +1113,8 @@ RTREE_TEMPLATE
bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
ListNode** a_listNode)
{
ASSERT(a_rect && a_node && a_listNode);
ASSERT(a_node->m_level >= 0);
Q_ASSERT(a_rect && a_node && a_listNode);
Q_ASSERT(a_node->m_level >= 0);
if (a_node->IsInternalNode()) { // not a leaf node
for (int index = 0; index < a_node->m_count; ++index) {
@ -1160,7 +1154,7 @@ bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
RTREE_TEMPLATE
bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
{
ASSERT(a_rectA && a_rectB);
Q_ASSERT(a_rectA && a_rectB);
for (int index=0; index < NUMDIMS; ++index) {
if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
@ -1193,9 +1187,9 @@ bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount,
bool (*a_resultCallback)(DATATYPE a_data, void* a_context),
void* a_context) const
{
ASSERT(a_node);
ASSERT(a_node->m_level >= 0);
ASSERT(a_rect);
Q_ASSERT(a_node);
Q_ASSERT(a_node->m_level >= 0);
Q_ASSERT(a_rect);
if (a_node->IsInternalNode()) { // This is an internal node in the tree
for (int index=0; index < a_node->m_count; ++index) {

View File

@ -51,6 +51,15 @@ Coordinates GPXParser::coordinates()
return Coordinates(lon, lat);
}
void GPXParser::rpExtension(TrackData *autoRoute)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "rpt")
autoRoute->append(Trackpoint(coordinates()));
_reader.skipCurrentElement();
}
}
void GPXParser::tpExtension(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
@ -63,7 +72,17 @@ void GPXParser::tpExtension(Trackpoint &trackpoint)
}
}
void GPXParser::extensions(Trackpoint &trackpoint)
void GPXParser::rteptExtensions(TrackData *autoRoute)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "RoutePointExtension")
rpExtension(autoRoute);
else
_reader.skipCurrentElement();
}
}
void GPXParser::trkptExtensions(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == "speed")
@ -95,7 +114,7 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
else if (_reader.name() == "geoidheight")
gh = number();
else if (_reader.name() == "extensions")
extensions(trackpoint);
trkptExtensions(trackpoint);
else
_reader.skipCurrentElement();
}
@ -104,7 +123,7 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
trackpoint.setElevation(trackpoint.elevation() - gh);
}
void GPXParser::waypointData(Waypoint &waypoint)
void GPXParser::waypointData(Waypoint &waypoint, TrackData *autoRoute)
{
qreal gh = NAN;
@ -119,6 +138,8 @@ void GPXParser::waypointData(Waypoint &waypoint)
gh = number();
else if (_reader.name() == "time")
waypoint.setTimestamp(time());
else if (autoRoute && _reader.name() == "extensions")
rteptExtensions(autoRoute);
else
_reader.skipCurrentElement();
}
@ -138,12 +159,14 @@ void GPXParser::trackpoints(TrackData &track)
}
}
void GPXParser::routepoints(RouteData &route)
void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
{
TrackData autoRoute;
while (_reader.readNextStartElement()) {
if (_reader.name() == "rtept") {
route.append(Waypoint(coordinates()));
waypointData(route.last());
waypointData(route.last(), &autoRoute);
} else if (_reader.name() == "name")
route.setName(_reader.readElementText());
else if (_reader.name() == "desc")
@ -151,6 +174,12 @@ void GPXParser::routepoints(RouteData &route)
else
_reader.skipCurrentElement();
}
if (!autoRoute.isEmpty()) {
autoRoute.setName(route.name());
autoRoute.setDescription(route.description());
tracks.append(autoRoute);
}
}
void GPXParser::track(TrackData &track)
@ -176,7 +205,7 @@ void GPXParser::gpx(QList<TrackData> &tracks, QList<RouteData> &routes,
track(tracks.back());
} else if (_reader.name() == "rte") {
routes.append(RouteData());
routepoints(routes.back());
routepoints(routes.back(), tracks);
} else if (_reader.name() == "wpt") {
waypoints.append(Waypoint(coordinates()));
waypointData(waypoints.last());

View File

@ -18,11 +18,13 @@ private:
QList<Waypoint> &waypoints);
void track(TrackData &track);
void trackpoints(TrackData &track);
void routepoints(RouteData &route);
void routepoints(RouteData &route, QList<TrackData> &tracks);
void rpExtension(TrackData *autoRoute);
void tpExtension(Trackpoint &trackpoint);
void extensions(Trackpoint &trackpoint);
void trkptExtensions(Trackpoint &trackpoint);
void rteptExtensions(TrackData *autoRoute);
void trackpointData(Trackpoint &trackpoint);
void waypointData(Waypoint &waypoint);
void waypointData(Waypoint &waypoint, TrackData *autoRoute = 0);
qreal number();
QDateTime time();
Coordinates coordinates();

View File

@ -5,7 +5,7 @@
#include <QPointF>
#include <QString>
#include <QStringList>
#include "rtree.h"
#include "common/rtree.h"
#include "waypoint.h"
#include "path.h"

View File

@ -45,16 +45,12 @@ Defense.
#include "albersequal.h"
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#define ONE_MINUS_SQR(x) (1.0 - (x) * (x))
#define ALBERS_Q(slat, one_minus_sqr_es_sin, es_sin) \
(_one_minus_es2 * ((slat) / (one_minus_sqr_es_sin) - \
(1 / (_two_es)) * log((1 - (es_sin)) / (1 + (es_sin)))))
#define ALBERS_M(clat, one_minus_sqr_es_sin) \
((clat) / sqrt(one_minus_sqr_es_sin))
#define ALBERS_Q(slat, one_minus_sqr_e_sin, es_sin) \
(_one_minus_es * ((slat) / (one_minus_sqr_e_sin) - \
(1 / (_two_e)) * log((1 - (es_sin)) / (1 + (es_sin)))))
#define ALBERS_M(clat, one_minus_sqr_e_sin) \
((clat) / sqrt(one_minus_sqr_e_sin))
AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
@ -64,8 +60,8 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
double sin_lat, sin_lat1, sin_lat2, cos_lat1, cos_lat2;
double m1, m2, sqr_m1, sqr_m2;
double q0, q1, q2;
double es_sin, es_sin1, es_sin2;
double one_minus_sqr_es_sin1, one_minus_sqr_es_sin2;
double e_sin, e_sin1, e_sin2;
double one_minus_sqr_e_sin1, one_minus_sqr_e_sin2;
double nq0;
double sp1, sp2;
@ -79,31 +75,30 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
sp2 = deg2rad(standardParallel2);
_a2 = ellipsoid->radius() * ellipsoid->radius();
_es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(_es2);
_one_minus_es2 = 1 - _es2;
_two_es = 2 * _es;
_es = ellipsoid->es();
_e = sqrt(_es);
_one_minus_es = 1 - _es;
_two_e = 2 * _e;
sin_lat = sin(_latitudeOrigin);
es_sin = _es * sin_lat;
q0 = ALBERS_Q(sin_lat, ONE_MINUS_SQR(es_sin), es_sin);
e_sin = _e * sin_lat;
q0 = ALBERS_Q(sin_lat, ONE_MINUS_SQR(e_sin), e_sin);
sin_lat1 = sin(sp1);
cos_lat1 = cos(sp1);
es_sin1 = _es * sin_lat1;
one_minus_sqr_es_sin1 = ONE_MINUS_SQR(es_sin1);
m1 = ALBERS_M(cos_lat1, one_minus_sqr_es_sin1);
q1 = ALBERS_Q(sin_lat1, one_minus_sqr_es_sin1, es_sin1);
e_sin1 = _e * sin_lat1;
one_minus_sqr_e_sin1 = ONE_MINUS_SQR(e_sin1);
m1 = ALBERS_M(cos_lat1, one_minus_sqr_e_sin1);
q1 = ALBERS_Q(sin_lat1, one_minus_sqr_e_sin1, e_sin1);
sqr_m1 = m1 * m1;
if (fabs(sp1 - sp2) > 1.0e-10) {
sin_lat2 = sin(sp2);
cos_lat2 = cos(sp2);
es_sin2 = _es * sin_lat2;
one_minus_sqr_es_sin2 = ONE_MINUS_SQR(es_sin2);
m2 = ALBERS_M(cos_lat2, one_minus_sqr_es_sin2);
q2 = ALBERS_Q(sin_lat2, one_minus_sqr_es_sin2, es_sin2);
e_sin2 = _e * sin_lat2;
one_minus_sqr_e_sin2 = ONE_MINUS_SQR(e_sin2);
m2 = ALBERS_M(cos_lat2, one_minus_sqr_e_sin2);
q2 = ALBERS_Q(sin_lat2, one_minus_sqr_e_sin2, e_sin2);
sqr_m2 = m2 * m2;
_n = (sqr_m1 - sqr_m2) / (q2 - q1);
} else
@ -119,7 +114,7 @@ PointD AlbersEqual::ll2xy(const Coordinates &c) const
{
double dlam;
double sin_lat;
double es_sin;
double e_sin;
double q;
double rho;
double theta;
@ -128,13 +123,13 @@ PointD AlbersEqual::ll2xy(const Coordinates &c) const
dlam = deg2rad(c.lon()) - _longitudeOrigin;
if (dlam > M_PI)
dlam -= 2.0 * M_PI;
dlam -= M_2_PI;
if (dlam < -M_PI)
dlam += 2.0 * M_PI;
dlam += M_2_PI;
sin_lat = sin(deg2rad(c.lat()));
es_sin = _es * sin_lat;
q = ALBERS_Q(sin_lat, ONE_MINUS_SQR(es_sin), es_sin);
e_sin = _e * sin_lat;
q = ALBERS_Q(sin_lat, ONE_MINUS_SQR(e_sin), e_sin);
nq = _n * q;
rho = (_C < nq) ? 0 : _a_over_n * sqrt(_C - nq);
theta = _n * dlam;
@ -151,7 +146,7 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
double rho, rho_n;
double phi, delta_phi = 1.0;
double sin_phi;
double es_sin, one_minus_sqr_es_sin;
double e_sin, one_minus_sqr_e_sin;
double theta = 0.0;
int count = 30;
double tolerance = 4.85e-10;
@ -174,7 +169,7 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
theta = atan2(dx, rho0_minus_dy);
rho_n = rho * _n;
q = (_C - (rho_n * rho_n) / _a2) / _n;
qc = 1 - ((_one_minus_es2) / (_two_es)) * log((1.0 - _es) / (1.0 + _es));
qc = 1 - ((_one_minus_es) / (_two_e)) * log((1.0 - _e) / (1.0 + _e));
if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) {
q_over_2 = q / 2.0;
if (q_over_2 > 1.0)
@ -183,17 +178,17 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
lat = -M_PI_2;
else {
phi = asin(q_over_2);
if (_es < 1.0e-10)
if (_e < 1.0e-10)
lat = phi;
else {
while ((fabs(delta_phi) > tolerance) && count) {
sin_phi = sin(phi);
es_sin = _es * sin_phi;
one_minus_sqr_es_sin = ONE_MINUS_SQR(es_sin);
delta_phi = (one_minus_sqr_es_sin * one_minus_sqr_es_sin)
/ (2.0 * cos(phi)) * (q / (_one_minus_es2) - sin_phi
/ one_minus_sqr_es_sin + (log((1.0 - es_sin)
/ (1.0 + es_sin)) / (_two_es)));
e_sin = _e * sin_phi;
one_minus_sqr_e_sin = ONE_MINUS_SQR(e_sin);
delta_phi = (one_minus_sqr_e_sin * one_minus_sqr_e_sin)
/ (2.0 * cos(phi)) * (q / (_one_minus_es) - sin_phi
/ one_minus_sqr_e_sin + (log((1.0 - e_sin)
/ (1.0 + e_sin)) / (_two_e)));
phi += delta_phi;
count --;
}
@ -216,9 +211,9 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
lon = _longitudeOrigin + theta / _n;
if (lon > M_PI)
lon -= M_PI * 2;
lon -= M_2_PI;
if (lon < -M_PI)
lon += M_PI * 2;
lon += M_2_PI;
if (lon > M_PI)
lon = M_PI;

View File

@ -27,11 +27,11 @@ private:
double _rho0;
double _C;
double _n;
double _e;
double _es;
double _es2;
double _a_over_n;
double _one_minus_es2;
double _two_es;
double _one_minus_es;
double _two_e;
};
#endif // ALBERSEQUAL_H

View File

@ -276,7 +276,6 @@ void Atlas::draw(QPainter *painter, const QRectF &rect, bool block)
}
// Multiple maps
painter->fillRect(rect, _backgroundColor);
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
QRectF ir = rect.intersected(_bounds.at(i).xy);
if (!ir.isNull())

View File

@ -12,6 +12,7 @@ public:
CoordinateSystem(AxisOrder axisOrder) : _axisOrder(axisOrder) {}
CoordinateSystem(int code);
bool isNull() const {return (_axisOrder == Unknown);}
bool isValid() const {return (_axisOrder != Unknown);}
AxisOrder axisOrder() const {return _axisOrder;}

View File

@ -4,6 +4,8 @@
#define as2rad(x) ((x) * (M_PI/648000.0))
#define rad2as(x) ((x) * (648000.0/M_PI))
#define ds2scale(x) (1.0 + (x) * 1e-6)
#define scale2ds(x) (((x) - 1.0) / 1e-6)
static Ellipsoid WGS84e = Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING);
static Datum WGS84 = Datum(&WGS84e, 0.0, 0.0, 0.0);
@ -34,64 +36,41 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
double adb = 1.0 / (1.0 - from_f);
double rn = from_a / sqrt(1 - from_esq * ssqlat);
double rm = from_a * (1 - from_esq) / pow((1 - from_esq * ssqlat), 1.5);
double from_h = 0.0;
double dlat = (-dx * slat * clon - dy * slat * slon + dz * clat + da
* rn * from_esq * slat * clat / from_a + df * (rm * adb + rn / adb) * slat
* clat) / (rm + from_h);
* clat) / rm;
double dlon = (-dx * slon + dy * clon) / ((rn + from_h) * clat);
double dlon = (-dx * slon + dy * clon) / (rn * clat);
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
}
Point3D Datum::helmert(const Point3D &p) const
{
double scale = 1 + _ds * 1e-6;
double R00 = 1;
double R01 = _rz;
double R02 = -_ry;
double R10 = -_rz;
double R11 = 1;
double R12 = _rx;
double R20 = _ry;
double R21 = -_rx;
double R22 = 1;
return Point3D(scale * (R00 * p.x() + R01 * p.y() + R02 * p.z()) + _dx,
scale * (R10 * p.x() + R11 * p.y() + R12 * p.z()) + _dy,
scale * (R20 * p.x() + R21 * p.y() + R22 * p.z()) + _dz);
return Point3D(_scale * (p.x() + _rz * p.y() -_ry * p.z()) + _dx,
_scale * (-_rz * p.x() + p.y() + _rx * p.z()) + _dy,
_scale * (_ry * p.x() -_rx * p.y() + p.z()) + _dz);
}
Point3D Datum::helmertr(const Point3D &p) const
{
double scale = 1 + _ds * 1e-6;
double R00 = 1;
double R01 = _rz;
double R02 = -_ry;
double R10 = -_rz;
double R11 = 1;
double R12 = _rx;
double R20 = _ry;
double R21 = -_rx;
double R22 = 1;
double x = (p.x() - _dx) / _scale;
double y = (p.y() - _dy) / _scale;
double z = (p.z() - _dz) / _scale;
double x = (p.x() - _dx) / scale;
double y = (p.y() - _dy) / scale;
double z = (p.z() - _dz) / scale;
return Point3D(R00 * x + R10 * y + R20 * z, R01 * x + R11 * y + R21 * z,
R02 * x + R12 * y + R22 * z);
return Point3D(x -_rz * y + _ry * z, _rz * x + y + -_rx * z, -_ry * x + _rx
* y + z);
}
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
double rx, double ry, double rz, double ds)
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
_ry(as2rad(ry)), _rz(as2rad(rz)), _ds(ds)
_ry(as2rad(ry)), _rz(as2rad(rz)), _scale(ds2scale(ds))
{
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && _ds == 0.0)
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
_transformation = None;
else
_transformation = Helmert;
@ -99,7 +78,7 @@ Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(0.0), _ry(0.0),
_rz(0.0), _ds(0.0)
_rz(0.0), _scale(1.0)
{
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
@ -113,7 +92,7 @@ Coordinates Datum::toWGS84(const Coordinates &c) const
switch (_transformation) {
case Helmert:
return Geocentric::toGeodetic(helmert(Geocentric::fromGeodetic(c,
*this)), WGS84);
ellipsoid())), WGS84.ellipsoid());
case Molodensky:
return molodensky(c, *this, WGS84);
default:
@ -126,7 +105,7 @@ Coordinates Datum::fromWGS84(const Coordinates &c) const
switch (_transformation) {
case Helmert:
return Geocentric::toGeodetic(helmertr(Geocentric::fromGeodetic(c,
WGS84)), *this);
WGS84.ellipsoid())), ellipsoid());
case Molodensky:
return molodensky(c, WGS84, *this);
default:
@ -140,7 +119,7 @@ QDebug operator<<(QDebug dbg, const Datum &datum)
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
<< ", " << datum.dy() << ", " << datum.dz() << ", " << rad2as(datum.rx())
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
<< datum.ds() << ")";
<< scale2ds(datum.scale()) << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -11,7 +11,7 @@ class Datum
{
public:
Datum() : _ellipsoid(0), _transformation(None), _dx(NAN), _dy(NAN),
_dz(NAN), _rx(NAN), _ry(NAN), _rz(NAN), _ds(NAN) {}
_dz(NAN), _rx(NAN), _ry(NAN), _rz(NAN), _scale(NAN) {}
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
double rx, double ry, double rz, double ds);
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz);
@ -20,16 +20,16 @@ public:
double dx() const {return _dx;}
double dy() const {return _dy;}
double dz() const {return _dz;}
double ds() const {return _ds;}
double rx() const {return _rx;}
double ry() const {return _ry;}
double rz() const {return _rz;}
double scale() const {return _scale;}
bool isNull() const
{return !_ellipsoid;}
bool isValid() const
{return (_ellipsoid && !std::isnan(_dx) && !std::isnan(_dy)
&& !std::isnan(_dz) && !std::isnan(_ds) && !std::isnan(_rx)
&& !std::isnan(_dz) && !std::isnan(_scale) && !std::isnan(_rx)
&& !std::isnan(_ry) && !std::isnan(_rz));}
Coordinates toWGS84(const Coordinates &c) const;
@ -47,13 +47,13 @@ private:
const Ellipsoid *_ellipsoid;
TransformationType _transformation;
double _dx, _dy, _dz, _rx, _ry, _rz, _ds;
double _dx, _dy, _dz, _rx, _ry, _rz, _scale;
};
inline bool operator==(const Datum &d1, const Datum &d2)
{return (*d1.ellipsoid() == *d2.ellipsoid() && d1.dx() == d2.dx()
&& d1.dy() == d2.dy() && d1.dz() == d2.dz() && d1.rx() == d2.rx()
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.ds() == d2.ds());}
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.scale() == d2.scale());}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Datum &datum);

View File

@ -66,6 +66,14 @@ void Ellipsoid::loadList(const QString &path)
}
}
Ellipsoid::Ellipsoid(double radius, double flattening)
: _radius(radius), _flattening(flattening)
{
_es = 2.0 * flattening - flattening * flattening;
_e2s = (1.0 / (1.0 - _es)) - 1.0;
_b = radius * (1.0 - flattening);
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid)
{

View File

@ -9,12 +9,14 @@
class Ellipsoid
{
public:
Ellipsoid() : _radius(NAN), _flattening(NAN) {}
Ellipsoid(double radius, double flattening)
: _radius(radius), _flattening(flattening) {}
Ellipsoid() : _radius(NAN), _flattening(NAN), _es(NAN), _b(NAN) {}
Ellipsoid(double radius, double flattening);
double radius() const {return _radius;}
double flattening() const {return _flattening;}
double es() const {return _es;}
double e2s() const {return _e2s;}
double b() const {return _b;}
bool isNull() const
{return (std::isnan(_radius) && std::isnan(_flattening));}
@ -27,6 +29,7 @@ public:
private:
double _radius;
double _flattening;
double _es, _e2s, _b;
static QMap<int, Ellipsoid> WGS84();
static QMap<int, Ellipsoid> _ellipsoids;

View File

@ -12,12 +12,12 @@
static QPointF ll2m(const Coordinates &c)
{
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
return QPointF(c.lon(), rad2deg(log(tan(M_PI_4 + deg2rad(c.lat())/2.0))));
}
static Coordinates m2ll(const QPointF &p)
{
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
return Coordinates(p.x(), rad2deg(2.0 * atan(exp(deg2rad(p.y()))) - M_PI_2));
}
static qreal zoom2scale(int zoom)
@ -87,8 +87,9 @@ int EmptyMap::zoomOut()
void EmptyMap::draw(QPainter *painter, const QRectF &rect, bool block)
{
Q_UNUSED(painter);
Q_UNUSED(rect);
Q_UNUSED(block);
painter->fillRect(rect, _backgroundColor);
}
QPointF EmptyMap::ll2xy(const Coordinates &c) const

View File

@ -41,45 +41,33 @@ Defense.
*/
#include "datum.h"
#include "ellipsoid.h"
#include "geocentric.h"
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#define AD_C 1.0026000
Point3D Geocentric::fromGeodetic(const Coordinates &c, const Datum &datum)
Point3D Geocentric::fromGeodetic(const Coordinates &c, const Ellipsoid *e)
{
const Ellipsoid *e = datum.ellipsoid();
double e2 = 2.0 * e->flattening() - e->flattening() * e->flattening();
double lat = deg2rad(c.lat());
double lon = deg2rad(c.lon());
double slat = sin(lat);
double slat2 = slat * slat;
double clat = cos(lat);
double Rn = e->radius() / (sqrt(1.0 - e2 * slat2));
double Rn = e->radius() / (sqrt(1.0 - e->es() * slat2));
if (lon > M_PI)
lon -= (2 * M_PI);
lon -= M_2_PI;
return Point3D(Rn * clat * cos(lon), Rn * clat * sin(lon),
(Rn * (1 - e2)) * slat);
(Rn * (1 - e->es())) * slat);
}
Coordinates Geocentric::toGeodetic(const Point3D &p, const Datum &datum)
Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid *e)
{
const Ellipsoid *e = datum.ellipsoid();
double b = e->radius() * (1.0 - e->flattening());
double e2 = 2.0 * e->flattening() - e->flattening() * e->flattening();
double ep2 = (1.0 / (1.0 - e2)) - 1.0;
bool pole = false;
double lat, lon;
if (p.x() == 0.0) {
if (p.y() > 0)
lon = M_PI_2;
@ -105,8 +93,8 @@ Coordinates Geocentric::toGeodetic(const Point3D &p, const Datum &datum)
double Sin_B0 = T0 / S0;
double Cos_B0 = W / S0;
double Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
double T1 = p.z() + b * ep2 * Sin3_B0;
double Sum = W - e->radius() * e2 * Cos_B0 * Cos_B0 * Cos_B0;
double T1 = p.z() + e->b() * e->e2s() * Sin3_B0;
double Sum = W - e->radius() * e->es() * Cos_B0 * Cos_B0 * Cos_B0;
double S1 = sqrt(T1*T1 + Sum * Sum);
double Sin_p1 = T1 / S1;
double Cos_p1 = Sum / S1;

View File

@ -4,7 +4,7 @@
#include <cmath>
#include "common/coordinates.h"
class Datum;
class Ellipsoid;
class Point3D {
public:
@ -22,8 +22,8 @@ private:
};
namespace Geocentric {
Point3D fromGeodetic(const Coordinates &c, const Datum &datum);
Coordinates toGeodetic(const Point3D &p, const Datum &datum);
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid *e);
Coordinates toGeodetic(const Point3D &p, const Ellipsoid *e);
}
#endif // GEOCENTRIC_H

View File

@ -1,5 +1,3 @@
#include <QFileInfo>
#include <QtEndian>
#include "pcs.h"
#include "tifffile.h"
#include "geotiff.h"

249
src/map/jnxmap.cpp Normal file
View File

@ -0,0 +1,249 @@
#include <QtEndian>
#include <QPainter>
#include <QFileInfo>
#include "transform.h"
#include "rectd.h"
#include "jnxmap.h"
#define ic2dc(x) ((x) * 180.0 / 0x7FFFFFFF)
struct Level {
quint32 count;
quint32 offset;
quint32 scale;
};
struct Ctx {
QPainter *painter;
QFile *file;
Ctx(QPainter *painter, QFile *file) : painter(painter), file(file) {}
};
template<class T> bool JNXMap::readValue(T &val)
{
T data;
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
return false;
if (sizeof(T) > 1)
val = qFromLittleEndian(data);
else
val = data;
return true;
}
bool JNXMap::readString(QByteArray& ba)
{
char byte;
while (true) {
if (!_file.getChar(&byte))
return false;
else if (!byte)
return true;
else
ba += byte;
}
}
bool JNXMap::readTiles()
{
qint32 lat1, lon2, lat2, lon1;
quint32 version, dummy, levels;
if (!(readValue(version) && readValue(dummy) && readValue(lat1)
&& readValue(lon2) && readValue(lat2) && readValue(lon1)
&& readValue(levels)))
return false;
_bounds = RectC(Coordinates(ic2dc(lon1), ic2dc(lat1)),
Coordinates(ic2dc(lon2), ic2dc(lat2)));
if (!levels || !_bounds.isValid())
return false;
if (!_file.seek(version > 3 ? 0x34 : 0x30))
return false;
QVector<Level> lh(levels);
for (int i = 0; i < lh.count(); i++) {
Level &l = lh[i];
if (!(readValue(l.count) && readValue(l.offset) && readValue(l.scale)))
return false;
if (version > 3) {
QByteArray ba;
if (!(readValue(dummy) && readString(ba)))
return false;
}
}
_zooms = QVector<Zoom>(lh.size());
for (int i = 0; i < lh.count(); i++) {
Zoom &z = _zooms[i];
const Level &l = lh.at(i);
if (!_file.seek(l.offset))
return false;
z.tiles = QVector<Tile>(l.count);
for (quint32 j = 0; j < l.count; j++) {
Tile &tile = z.tiles[j];
qint32 top, right, bottom, left;
quint16 width, height;
if (!(readValue(top) && readValue(right) && readValue(bottom)
&& readValue(left) && readValue(width)
&& readValue(height) && readValue(tile.size)
&& readValue(tile.offset)))
return false;
RectD rect(PointD(ic2dc(left), ic2dc(top)), PointD(ic2dc(right),
ic2dc(bottom)));
if (j == 0) {
ReferencePoint tl(PointD(0, 0), rect.topLeft());
ReferencePoint br(PointD(width, height), rect.bottomRight());
z.transform = Transform(tl, br);
}
QRectF trect(z.transform.proj2img(rect.topLeft()),
z.transform.proj2img(rect.bottomRight()));
tile.pos = trect.topLeft();
qreal min[2], max[2];
min[0] = trect.left();
min[1] = trect.top();
max[0] = trect.right();
max[1] = trect.bottom();
z.tree.Insert(min, max, &tile);
}
}
return true;
}
JNXMap::JNXMap(const QString &fileName, QObject *parent)
: Map(parent), _file(fileName), _zoom(0), _valid(false)
{
_name = QFileInfo(fileName).fileName();
if (!_file.open(QIODevice::ReadOnly)) {
_errorString = QString("%1: Error opening file").arg(fileName);
return;
}
if (!readTiles()) {
_errorString = "JNX file format error";
return;
}
_valid = true;
}
QPointF JNXMap::ll2xy(const Coordinates &c) const
{
const Transform &t = _zooms.at(_zoom).transform;
return t.proj2img(PointD(c.lon(), c.lat()));
}
Coordinates JNXMap::xy2ll(const QPointF &p) const
{
const Transform &t = _zooms.at(_zoom).transform;
PointD pp(t.img2proj(p));
return Coordinates(pp.x(), pp.y());
}
QRectF JNXMap::bounds() const
{
const Transform &t = _zooms.at(_zoom).transform;
return QRectF(t.proj2img(PointD(_bounds.topLeft().lon(),
_bounds.topLeft().lat())), t.proj2img(PointD(_bounds.bottomRight().lon(),
_bounds.bottomRight().lat())));
}
qreal JNXMap::resolution(const QRectF &rect) const
{
Coordinates tl = xy2ll((rect.topLeft()));
Coordinates br = xy2ll(rect.bottomRight());
qreal ds = tl.distanceTo(br);
qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
return ds/ps;
}
int JNXMap::zoomFit(const QSize &size, const RectC &rect)
{
if (!rect.isValid())
_zoom = _zooms.size() - 1;
else {
for (int i = 1; i < _zooms.count(); i++) {
_zoom = i;
QRect sbr(QPoint(ll2xy(rect.topLeft()).toPoint()),
QPoint(ll2xy(rect.bottomRight()).toPoint()));
if (sbr.size().width() >= size.width() || sbr.size().height()
>= size.height()) {
_zoom--;
break;
}
}
}
return _zoom;
}
int JNXMap::zoomIn()
{
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
return _zoom;
}
int JNXMap::zoomOut()
{
_zoom = qMax(_zoom - 1, 0);
return _zoom;
}
QPixmap JNXMap::pixmap(const Tile *tile, QFile *file)
{
QByteArray ba;
ba.resize(tile->size + 2);
ba[0] = (char)0xFF;
ba[1] = (char)0xD8;
char *data = ba.data() + 2;
if (!file->seek(tile->offset))
return QPixmap();
if (!file->read(data, tile->size))
return QPixmap();
return QPixmap::fromImage(QImage::fromData(ba));
}
bool JNXMap::cb(Tile *tile, void *context)
{
Ctx *ctx = static_cast<Ctx*>(context);
ctx->painter->drawPixmap(tile->pos, pixmap(tile, ctx->file));
return true;
}
void JNXMap::draw(QPainter *painter, const QRectF &rect, bool block)
{
Q_UNUSED(block);
const RTree<Tile*, qreal, 2> &tree = _zooms.at(_zoom).tree;
Ctx ctx(painter, &_file);
qreal min[2], max[2];
min[0] = rect.left();
min[1] = rect.top();
max[0] = rect.right();
max[1] = rect.bottom();
tree.Search(min, max, cb, &ctx);
}

73
src/map/jnxmap.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef JNXMAP_H
#define JNXMAP_H
#include <QFile>
#include <QVector>
#include "common/rtree.h"
#include "common/rectc.h"
#include "transform.h"
#include "map.h"
class JNXMap : public Map
{
public:
Q_OBJECT
public:
JNXMap(const QString &fileName, QObject *parent = 0);
const QString &name() const {return _name;}
QRectF bounds() const;
qreal resolution(const QRectF &rect) const;
int zoom() const {return _zoom;}
void setZoom(int zoom) {_zoom = zoom;}
int zoomFit(const QSize &size, const RectC &rect);
int zoomIn();
int zoomOut();
QPointF ll2xy(const Coordinates &c)
{return static_cast<const JNXMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const JNXMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect, bool block);
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
private:
struct Tile {
QPointF pos;
quint32 size;
quint32 offset;
};
struct Zoom {
Transform transform;
QVector<Tile> tiles;
RTree<Tile*, qreal, 2> tree;
};
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
template<class T> bool readValue(T &val);
bool readString(QByteArray &ba);
bool readTiles();
static bool cb(Tile *tile, void *context);
static QPixmap pixmap(const Tile *tile, QFile *file);
QString _name;
QFile _file;
QVector<Zoom> _zooms;
int _zoom;
RectC _bounds;
bool _valid;
QString _errorString;
};
#endif // JNXMAP_H

View File

@ -16,19 +16,17 @@ LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
_lon0 = deg2rad(longitudeOrigin);
_a = ellipsoid->radius();
_es = ellipsoid->es();
_e = sqrt(_es);
_es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(_es2);
double q0 = (1.0 - _es2) * ((sin(lat0) / (1.0 - _es2 * sin2(lat0)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat0)) / (1.0 + _es
double q0 = (1.0 - _es) * ((sin(lat0) / (1.0 - _es * sin2(lat0)))
- ((1.0/(2.0*_e)) * log((1.0 - _e * sin(lat0)) / (1.0 + _e
* sin(lat0)))));
_qP = (1.0 - _es2) * ((1.0 / (1.0 - _es2)) - ((1.0/(2.0*_es))
* log((1.0 - _es) / (1.0 + _es))));
_qP = (1.0 - _es) * ((1.0 / (1.0 - _es)) - ((1.0/(2.0*_e))
* log((1.0 - _e) / (1.0 + _e))));
_beta0 = asin(q0 / _qP);
_Rq = _a * sqrt(_qP / 2.0);
_D = _a * (cos(lat0) / sqrt(1.0 - _es2 * sin2(lat0))) / (_Rq * cos(_beta0));
_D = _a * (cos(lat0) / sqrt(1.0 - _es * sin2(lat0))) / (_Rq * cos(_beta0));
}
PointD LambertAzimuthal::ll2xy(const Coordinates &c) const
@ -36,8 +34,8 @@ PointD LambertAzimuthal::ll2xy(const Coordinates &c) const
double lon = deg2rad(c.lon());
double lat = deg2rad(c.lat());
double q = (1.0 - _es2) * ((sin(lat) / (1.0 - _es2 * sin2(lat)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat)) / (1.0 + _es
double q = (1.0 - _es) * ((sin(lat) / (1.0 - _es * sin2(lat)))
- ((1.0/(2.0*_e)) * log((1.0 - _e * sin(lat)) / (1.0 + _e
* sin(lat)))));
double beta = asin(q / _qP);
double B = _Rq * sqrt(2.0 / (1.0 + sin(_beta0) * sin(beta) + (cos(_beta0)
@ -52,8 +50,8 @@ PointD LambertAzimuthal::ll2xy(const Coordinates &c) const
Coordinates LambertAzimuthal::xy2ll(const PointD &p) const
{
double es4 = _es2 * _es2;
double es6 = _es2 * es4;
double es4 = _es * _es;
double es6 = _es * es4;
double rho = sqrt(sqr((p.x() - _falseEasting) / _D) + sqr(_D * (p.y()
- _falseNorthing)));
@ -64,7 +62,7 @@ Coordinates LambertAzimuthal::xy2ll(const PointD &p) const
double lon = _lon0 + atan((p.x() - _falseEasting) * sin(C) / (_D * rho
* cos(_beta0) * cos(C) - sqr(_D) * (p.y() - _falseNorthing) * sin(_beta0)
* sin(C)));
double lat = betaS + ((_es2/3.0 + 31.0*es4/180.0 + 517.0*es6/5040.0)
double lat = betaS + ((_es/3.0 + 31.0*es4/180.0 + 517.0*es6/5040.0)
* sin(2.0*betaS)) + ((23.0*es4/360.0 + 251.0*es6/3780.0) * sin(4.0*betaS))
+ ((761.0*es6/45360.0)*sin(6.0*betaS));

View File

@ -20,7 +20,7 @@ private:
double _lon0;
double _falseNorthing;
double _falseEasting;
double _a, _es, _es2, _qP, _beta0, _Rq, _D;
double _a, _e, _es, _qP, _beta0, _Rq, _D;
};
#endif // LAMBERTAZIMUTHAL_H

View File

@ -45,12 +45,6 @@ Defense.
#include "ellipsoid.h"
#include "lambertconic.h"
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#ifndef M_PI_4
#define M_PI_4 0.785398163397448309616
#endif /* M_PI_4 */
#define LAMBERT_m(clat, essin) (clat / sqrt(1.0 - essin * essin))
#define LAMBERT2_t(lat, essin, es_over_2) \
@ -63,8 +57,7 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double scale, double falseEasting,
double falseNorthing)
{
double es2;
double es_sin;
double e_sin;
double m0;
double lat_orig;
@ -72,21 +65,19 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
lat_orig = deg2rad(latitudeOrigin);
_longitudeOrigin = deg2rad(longitudeOrigin);
if (_longitudeOrigin > M_PI)
_longitudeOrigin -= 2 * M_PI;
_longitudeOrigin -= M_2_PI;
_falseEasting = falseEasting;
_falseNorthing = falseNorthing;
es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(es2);
_es_over_2 = _es / 2.0;
_e = sqrt(ellipsoid->es());
_e_over_2 = _e / 2.0;
_n = sin(lat_orig);
es_sin = _es * sin(lat_orig);
m0 = LAMBERT_m(cos(lat_orig), es_sin);
_t0 = LAMBERT1_t(lat_orig, es_sin, _es_over_2);
e_sin = _e * sin(lat_orig);
m0 = LAMBERT_m(cos(lat_orig), e_sin);
_t0 = LAMBERT1_t(lat_orig, e_sin, _e_over_2);
_rho0 = ellipsoid->radius() * scale * m0 / _n;
@ -103,7 +94,7 @@ PointD LambertConic1::ll2xy(const Coordinates &c) const
if (fabs(fabs(lat) - M_PI_2) > 1.0e-10) {
t = LAMBERT1_t(lat, _es * sin(lat), _es_over_2);
t = LAMBERT1_t(lat, _e * sin(lat), _e_over_2);
rho = _rho0 * pow(t / _t0, _n);
} else
rho = 0.0;
@ -111,9 +102,9 @@ PointD LambertConic1::ll2xy(const Coordinates &c) const
dlam = deg2rad(c.lon()) - _longitudeOrigin;
if (dlam > M_PI)
dlam -= 2 * M_PI;
dlam -= M_2_PI;
if (dlam < -M_PI)
dlam += 2 * M_PI;
dlam += M_2_PI;
theta = _n * dlam;
@ -154,9 +145,9 @@ Coordinates LambertConic1::xy2ll(const PointD &p) const
PHI = M_PI_2 - 2.0 * atan(t);
while (fabs(PHI - tempPHI) > tolerance && count) {
tempPHI = PHI;
es_sin = _es * sin(PHI);
es_sin = _e * sin(PHI);
PHI = M_PI_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin),
_es_over_2));
_e_over_2));
count--;
}
@ -177,13 +168,13 @@ Coordinates LambertConic1::xy2ll(const PointD &p) const
if (lon - M_PI < 3.5e-6)
lon = M_PI;
else
lon -= 2 * M_PI;
lon -= M_2_PI;
}
if (lon < -M_PI) {
if (fabs(lon + M_PI) < 3.5e-6)
lon = -M_PI;
else
lon += 2 * M_PI;
lon += M_2_PI;
}
if (fabs(lon) < 2.0e-7)
@ -207,7 +198,7 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
double standardParallel1, double standardParallel2, double latitudeOrigin,
double longitudeOrigin, double falseEasting, double falseNorthing)
{
double es, es_over_2, es2, es_sin;
double e, e_over_2, e_sin;
double lat0;
double k0;
double t0;
@ -227,29 +218,27 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
sp2 = deg2rad(standardParallel2);
if (fabs(sp1 - sp2) > 1.0e-10) {
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
es = sqrt(es2);
es_over_2 = es / 2.0;
e = sqrt(ellipsoid->es());
e_over_2 = e / 2.0;
es_sin = es * sin(lat_orig);
t_olat = LAMBERT2_t(lat_orig, es_sin, es_over_2);
e_sin = e * sin(lat_orig);
t_olat = LAMBERT2_t(lat_orig, e_sin, e_over_2);
es_sin = es * sin(sp1);
m1 = LAMBERT_m(cos(sp1), es_sin);
t1 = LAMBERT2_t(sp1, es_sin, es_over_2);
e_sin = e * sin(sp1);
m1 = LAMBERT_m(cos(sp1), e_sin);
t1 = LAMBERT2_t(sp1, e_sin, e_over_2);
es_sin = es * sin(sp2);
m2 = LAMBERT_m(cos(sp2), es_sin);
t2 = LAMBERT2_t(sp2, es_sin, es_over_2);
e_sin = e * sin(sp2);
m2 = LAMBERT_m(cos(sp2), e_sin);
t2 = LAMBERT2_t(sp2, e_sin, e_over_2);
n = log(m1 / m2) / log(t1 / t2);
lat0 = asin(n);
es_sin = es * sin(lat0);
m0 = LAMBERT_m(cos(lat0), es_sin);
t0 = LAMBERT2_t(lat0, es_sin, es_over_2);
e_sin = e * sin(lat0);
m0 = LAMBERT_m(cos(lat0), e_sin);
t0 = LAMBERT2_t(lat0, e_sin, e_over_2);
k0 = (m1 / m0) * (pow(t0 / t1, n));

View File

@ -23,8 +23,8 @@ private:
double _falseEasting;
double _falseNorthing;
double _es;
double _es_over_2;
double _e;
double _e_over_2;
double _n;
double _t0;
double _rho0;

View File

@ -15,7 +15,7 @@ class Map : public QObject
Q_OBJECT
public:
Map(QObject *parent = 0) : QObject(parent), _backgroundColor(Qt::white) {}
Map(QObject *parent = 0) : QObject(parent) {}
virtual ~Map() {}
virtual const QString &name() const = 0;
@ -41,13 +41,8 @@ public:
virtual bool isValid() const {return true;}
virtual QString errorString() const {return QString();}
void setBackgroundColor(const QColor &color) {_backgroundColor = color;}
signals:
void loaded();
protected:
QColor _backgroundColor;
};
#endif // MAP_H

View File

@ -3,33 +3,13 @@
#include "atlas.h"
#include "offlinemap.h"
#include "onlinemap.h"
#include "jnxmap.h"
#include "mapsource.h"
#include "maplist.h"
bool MapList::loadSource(const QString &path, bool dir)
bool MapList::loadMap(Map* map, const QString &path, bool dir)
{
MapSource ms;
Map *map;
if (!(map = ms.loadFile(path))) {
if (dir)
_errorString += path + ": " + ms.errorString() + "\n";
else
_errorString = ms.errorString();
return false;
}
map->setParent(this);
_maps.append(map);
return true;
}
bool MapList::loadMap(const QString &path, bool dir)
{
OfflineMap *map = new OfflineMap(path, this);
if (map->isValid()) {
_maps.append(map);
return true;
@ -38,26 +18,27 @@ bool MapList::loadMap(const QString &path, bool dir)
_errorString += path + ": " + map->errorString() + "\n";
else
_errorString = map->errorString();
delete map;
return false;
}
}
bool MapList::loadAtlas(const QString &path, bool dir)
bool MapList::loadSource(const QString &path, bool dir)
{
Atlas *atlas = new Atlas(path, this);
QString err;
Map *map = MapSource::loadMap(path, err);
if (atlas->isValid()) {
_maps.append(atlas);
return true;
} else {
if (!map) {
if (dir)
_errorString += path + ": " + atlas->errorString() + "\n";
_errorString += path + ": " + err + "\n";
else
_errorString = atlas->errorString();
delete atlas;
_errorString = err;
return false;
}
map->setParent(this);
return loadMap(map, path, dir);
}
bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
@ -67,14 +48,13 @@ bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
if (Atlas::isAtlas(path)) {
*atlas = true;
return loadAtlas(path, dir);
} else if (suffix == "xml") {
*atlas = false;
return loadMap(new Atlas(path, this), path, dir);
} else if (suffix == "xml")
return loadSource(path, dir);
} else {
*atlas = false;
return loadMap(path, dir);
}
else if (suffix == "jnx")
return loadMap(new JNXMap(path, this), path, dir);
else
return loadMap(new OfflineMap(path, this), path, dir);
}
bool MapList::loadDirR(const QString &path)
@ -83,11 +63,12 @@ bool MapList::loadDirR(const QString &path)
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
md.setSorting(QDir::DirsLast);
QFileInfoList ml = md.entryInfoList();
bool atlas, ret = true;
bool ret = true;
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
QString suffix = fi.suffix().toLower();
bool atlas = false;
if (fi.isDir() && fi.fileName() != "set") {
if (!loadDirR(fi.absoluteFilePath()))
@ -127,7 +108,8 @@ void MapList::clear()
QString MapList::formats()
{
return
tr("Supported files") + " (*.map *.tar *.tba *.tif *.tiff *.xml);;"
tr("Supported files") + " (*.jnx *.map *.tar *.tba *.tif *.tiff *.xml);;"
+ tr("Garmin JNX maps") + " (*.jnx);;"
+ tr("OziExplorer maps") + " (*.map);;"
+ tr("TrekBuddy maps/atlases") + " (*.tar *.tba);;"
+ tr("GeoTIFF images") + " (*.tif *.tiff);;"
@ -137,6 +119,7 @@ QString MapList::formats()
QStringList MapList::filter()
{
QStringList filter;
filter << "*.map" << "*.tba" << "*.tar" << "*.xml" << "*.tif" << "*.tiff";
filter << "*.jnx *.map" << "*.tba" << "*.tar" << "*.xml" << "*.tif"
<< "*.tiff";
return filter;
}

View File

@ -26,12 +26,8 @@ public:
private:
bool loadFile(const QString &path, bool *atlas, bool dir);
bool loadDirR(const QString &path);
Map *loadListEntry(const QByteArray &line);
bool loadSource(const QString &path, bool dir);
bool loadMap(const QString &path, bool dir);
bool loadAtlas(const QString &path, bool dir);
bool loadMap(Map *map, const QString &path, bool dir);
QList<Map*> _maps;
QString _errorString;

View File

@ -164,20 +164,18 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
}
}
Map *MapSource::loadFile(const QString &path)
Map *MapSource::loadMap(const QString &path, QString &errorString)
{
QFile file(path);
QXmlStreamReader reader;
Config config;
Map *m;
QFile file(path);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
errorString = file.errorString();
return 0;
}
reader.setDevice(&file);
QXmlStreamReader reader(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "map")
map(reader, config);
@ -185,59 +183,51 @@ Map *MapSource::loadFile(const QString &path)
reader.raiseError("Not an online map source file");
}
if (reader.error()) {
_errorString = QString("%1: %2").arg(reader.lineNumber())
errorString = QString("%1: %2").arg(reader.lineNumber())
.arg(reader.errorString());
return 0;
}
if (config.name.isEmpty()) {
_errorString = "Missing name definition";
errorString = "Missing name definition";
return 0;
}
if (config.url.isEmpty()) {
_errorString = "Missing URL definition";
errorString = "Missing URL definition";
return 0;
}
if (config.type == WMTS || config.type == WMS) {
if (config.layer.isEmpty()) {
_errorString = "Missing layer definition";
errorString = "Missing layer definition";
return 0;
}
if (config.format.isEmpty()) {
_errorString = "Missing format definition";
errorString = "Missing format definition";
return 0;
}
}
if (config.type == WMTS) {
if (config.set.isEmpty()) {
_errorString = "Missing set definiton";
errorString = "Missing set definiton";
return 0;
}
}
if (config.type == WMS) {
if (config.crs.isEmpty()) {
_errorString = "Missing CRS definiton";
errorString = "Missing CRS definiton";
return 0;
}
}
if (config.type == WMTS)
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
return new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
config.set, config.style, config.format, config.rest,
config.coordinateSystem, config.dimensions, config.authorization));
else if (config.type == WMS)
m = new WMSMap(config.name, WMS::Setup(config.url, config.layer,
return new WMSMap(config.name, WMS::Setup(config.url, config.layer,
config.style, config.format, config.crs, config.coordinateSystem,
config.dimensions, config.authorization));
else
m = new OnlineMap(config.name, config.url, config.zooms, config.bounds,
config.authorization);
if (!m->isValid()) {
_errorString = m->errorString();
delete m;
return 0;
}
return m;
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.authorization);
}

View File

@ -13,8 +13,7 @@ class QXmlStreamReader;
class MapSource
{
public:
Map *loadFile(const QString &path);
const QString &errorString() const {return _errorString;}
static Map *loadMap(const QString &path, QString &errorString);
private:
enum Type {
@ -42,11 +41,9 @@ private:
Config();
};
RectC bounds(QXmlStreamReader &reader);
Range zooms(QXmlStreamReader &reader);
void map(QXmlStreamReader &reader, Config &config);
QString _errorString;
static RectC bounds(QXmlStreamReader &reader);
static Range zooms(QXmlStreamReader &reader);
static void map(QXmlStreamReader &reader, Config &config);
};
#endif // MAPSOURCE_H

View File

@ -47,28 +47,29 @@ Defense.
Mercator::Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double falseEasting, double falseNorthing)
{
double es = ellipsoid->es();
double es2;
double es3;
double es4;
double sin_olat;
_a = ellipsoid->radius();
_latitudeOrigin = deg2rad(latitudeOrigin);
_longitudeOrigin = deg2rad(longitudeOrigin);
if (_longitudeOrigin > M_PI)
_longitudeOrigin -= 2*M_PI;
_longitudeOrigin -= M_2_PI;
_falseNorthing = falseNorthing;
_falseEasting = falseEasting;
_es = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_e = sqrt(_es);
_a = ellipsoid->radius();
_e = sqrt(es);
sin_olat = sin(_latitudeOrigin);
_scaleFactor = 1.0 / (sqrt(1.e0 - _es * sin_olat * sin_olat)
_scaleFactor = 1.0 / (sqrt(1.e0 - es * sin_olat * sin_olat)
/ cos(_latitudeOrigin));
es2 = _es * _es;
es3 = es2 * _es;
es4 = es3 * _es;
_ab = _es / 2.e0 + 5.e0 * es2 / 24.e0 + es3 / 12.e0 + 13.e0 * es4 / 360.e0;
es2 = es * es;
es3 = es2 * es;
es4 = es3 * es;
_ab = es / 2.e0 + 5.e0 * es2 / 24.e0 + es3 / 12.e0 + 13.e0 * es4 / 360.e0;
_bb = 7.e0 * es2 / 48.e0 + 29.e0 * es3 / 240.e0 + 811.e0 * es4 / 11520.e0;
_cb = 7.e0 * es3 / 120.e0 + 81.e0 * es4 / 1120.e0;
_db = 4279.e0 * es4 / 161280.e0;
@ -85,16 +86,16 @@ PointD Mercator::ll2xy(const Coordinates &c) const
double pow_temp;
if (lon > M_PI)
lon -= 2*M_PI;
lon -= M_2_PI;
e_x_sinlat = _e * sin(lat);
tan_temp = tan(M_PI / 4.e0 + lat / 2.e0);
tan_temp = tan(M_PI_4 + lat / 2.e0);
pow_temp = pow((1.e0 - e_x_sinlat) / (1.e0 + e_x_sinlat), _e / 2.e0);
ctanz2 = tan_temp * pow_temp;
delta_lon = lon - _longitudeOrigin;
if (delta_lon > M_PI)
delta_lon -= 2 * M_PI;
delta_lon -= M_2_PI;
if (delta_lon < -M_PI)
delta_lon += 2 * M_PI;
delta_lon += M_2_PI;
return PointD(_scaleFactor * _a * delta_lon + _falseEasting,
_scaleFactor * _a * log(ctanz2) + _falseNorthing);
@ -110,13 +111,13 @@ Coordinates Mercator::xy2ll(const PointD &p) const
dy = p.y() - _falseNorthing;
dx = p.x() - _falseEasting;
lon = _longitudeOrigin + dx / (_scaleFactor * _a);
xphi = M_PI / 2.e0 - 2.e0 * atan(1.e0 / exp(dy / (_scaleFactor * _a)));
xphi = M_PI_2 - 2.e0 * atan(1.e0 / exp(dy / (_scaleFactor * _a)));
lat = xphi + _ab * sin(2.e0 * xphi) + _bb * sin(4.e0 * xphi)
+ _cb * sin(6.e0 * xphi) + _db * sin(8.e0 * xphi);
if (lon > M_PI)
lon -= 2 * M_PI;
lon -= M_2_PI;
if (lon < -M_PI)
lon += 2 * M_PI;
lon += M_2_PI;
return Coordinates(rad2deg(lon), rad2deg(lat));
}

View File

@ -17,7 +17,7 @@ public:
virtual Coordinates xy2ll(const PointD &p) const;
private:
double _a, _es, _e;
double _a, _e;
double _latitudeOrigin;
double _longitudeOrigin;
double _falseNorthing;

View File

@ -262,12 +262,10 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const
} else
pixmap = QPixmap(tileName);
if (pixmap.isNull()) {
if (pixmap.isNull())
qWarning("%s: error loading tile image", qPrintable(
_tile.path.arg(QString::number(x), QString::number(y))));
painter->fillRect(QRectF(QPoint(x, y), _tile.size),
_backgroundColor);
} else
else
painter->drawPixmap(QPoint(x, y), pixmap);
}
}
@ -294,11 +292,9 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const
QPixmapCache::insert(key, pixmap);
}
if (pixmap.isNull()) {
if (pixmap.isNull())
qWarning("%s: error loading tile image", qPrintable(key));
painter->fillRect(QRectF(QPoint(x, y), _ozf->tileSize()),
_backgroundColor);
} else
else
painter->drawPixmap(QPoint(x, y), pixmap);
}
}
@ -321,8 +317,6 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect, bool block)
drawTiled(painter, rect);
else if (_img && !_img->isNull())
drawImage(painter, rect);
else
painter->fillRect(rect, _backgroundColor);
}
QPointF OfflineMap::ll2xy(const Coordinates &c) const

View File

@ -12,12 +12,12 @@
static QPointF ll2m(const Coordinates &c)
{
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
return QPointF(c.lon(), rad2deg(log(tan(M_PI_4 + deg2rad(c.lat())/2.0))));
}
static Coordinates m2ll(const QPointF &p)
{
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
return Coordinates(p.x(), rad2deg(2.0 * atan(exp(deg2rad(p.y()))) - M_PI_2));
}
static QPoint mercator2tile(const QPointF &m, int z)
@ -136,10 +136,7 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, bool block)
Tile &t = tiles[i];
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE,
tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE);
if (t.pixmap().isNull())
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
_backgroundColor);
else
if (!t.pixmap().isNull())
painter->drawPixmap(tp, t.pixmap());
}
}

View File

@ -25,10 +25,11 @@ public:
const CoordinateSystem &coordinateSystem() const {return _cs;}
bool isNull() const
{return (_gcs->isNull() && _units.isNull() && _method.isNull()
&& _setup.isNull());}
{return (!_gcs && _units.isNull() && _method.isNull() && _setup.isNull()
&& _cs.isNull());}
bool isValid() const
{return (_gcs->isValid() && _units.isValid() && _method.isValid());}
{return (_gcs && _gcs->isValid() && _units.isValid()
&& _method.isValid() && _cs.isValid());}
static void loadList(const QString &path);
static const PCS *pcs(int id);

View File

@ -110,14 +110,14 @@ Projection &Projection::operator=(const Projection &p)
PointD Projection::ll2xy(const Coordinates &c) const
{
return isValid()
? _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c))) : PointD();
Q_ASSERT(isValid());
return _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c)));
}
Coordinates Projection::xy2ll(const PointD &p) const
{
return isValid()
? _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p))) : Coordinates();
Q_ASSERT(isValid());
return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p)));
}
#ifndef QT_NO_DEBUG

View File

@ -72,11 +72,9 @@ TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
_falseEasting = falseEasting;
_falseNorthing = falseNorthing;
_es = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = ellipsoid->es();
_ebs = (1 / (1 - _es)) - 1;
b = _a * (1 - ellipsoid->flattening());
b = ellipsoid->b();
tn = (_a - b) / (_a + b);
tn2 = tn * tn;
@ -109,9 +107,9 @@ PointD TransverseMercator::ll2xy(const Coordinates &c) const
dlam = deg2rad(c.lon()) - _longitudeOrigin;
if (dlam > M_PI)
dlam -= (2 * M_PI);
dlam -= M_2_PI;
if (dlam < -M_PI)
dlam += (2 * M_PI);
dlam += M_2_PI;
if (fabs(dlam) < 2.e-10)
dlam = 0.0;
@ -237,20 +235,20 @@ Coordinates TransverseMercator::xy2ll(const PointD &p) const
lat = M_PI - lat;
lon += M_PI;
if (lon > M_PI)
lon -= (2 * M_PI);
lon -= M_2_PI;
}
while (lat < deg2rad(-90.0)) {
lat = - (lat + M_PI);
lon += M_PI;
if (lon > M_PI)
lon -= (2 * M_PI);
lon -= M_2_PI;
}
if (lon > (2 * M_PI))
lon -= (2 * M_PI);
if (lon > M_2_PI)
lon -= M_2_PI;
if (lon < -M_PI)
lon += (2 * M_PI);
lon += M_2_PI;
return Coordinates(rad2deg(lon), rad2deg(lat));
}

View File

@ -24,7 +24,6 @@ private:
double _falseEasting;
double _falseNorthing;
double _a;
double _es;
double _ebs;
double _ap, _bp, _cp, _dp, _ep;

View File

@ -6,11 +6,11 @@
PointD WebMercator::ll2xy(const Coordinates &c) const
{
return PointD(deg2rad(c.lon()) * WGS84_RADIUS,
log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0)) * WGS84_RADIUS);
log(tan(M_PI_4 + deg2rad(c.lat())/2.0)) * WGS84_RADIUS);
}
Coordinates WebMercator::xy2ll(const PointD &p) const
{
return Coordinates(rad2deg(p.x() / WGS84_RADIUS),
rad2deg(2 * atan(exp(p.y() / WGS84_RADIUS)) - M_PI/2));
rad2deg(2.0 * atan(exp(p.y() / WGS84_RADIUS)) - M_PI_2));
}

View File

@ -227,7 +227,7 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
}
_projection = CRS::projection(ctx.setup.crs());
if (_projection.isNull()) {
if (!_projection.isValid()) {
_errorString = ctx.setup.crs() + ": unknown CRS";
return false;
}

View File

@ -227,10 +227,7 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, bool block)
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
QPoint tp(t.xy().x() * TILE_SIZE, t.xy().y() * TILE_SIZE);
if (t.pixmap().isNull())
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
_backgroundColor);
else
if (!t.pixmap().isNull())
painter->drawPixmap(tp, t.pixmap());
}
}

View File

@ -261,7 +261,7 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
return false;
}
_projection = CRS::projection(ctx.crs);
if (_projection.isNull()) {
if (!_projection.isValid()) {
_errorString = ctx.crs + ": unknown CRS";
return false;
}

View File

@ -184,9 +184,7 @@ void WMTSMap::draw(QPainter *painter, const QRectF &rect, bool block)
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
QPoint tp(t.xy().x() * z.tile().width(), t.xy().y() * z.tile().height());
if (t.pixmap().isNull())
painter->fillRect(QRect(tp, z.tile()), _backgroundColor);
else
if (!t.pixmap().isNull())
painter->drawPixmap(tp, t.pixmap());
}
}