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

Compare commits

..

26 Commits
11.7 ... 11.9

Author SHA1 Message Date
ac5f4cafeb Code cleanup 2022-11-17 13:26:45 +01:00
ccb0364e76 Some more missing ENC objects 2022-11-17 13:05:38 +01:00
414bdead17 Docks render style 2022-11-17 10:37:05 +01:00
8cf09a68d1 Some more missing ENC render style 2022-11-17 08:25:53 +01:00
e4c79d7275 Added missing dams and pylons rendering 2022-11-16 22:51:16 +01:00
a718f1e122 Properly handle non-ASCII characters
(Support for UCS-2 encoded files is still missing as there is no such sample
file available.)
2022-11-16 22:47:30 +01:00
6507764545 Version++ 2022-11-16 00:39:23 +01:00
bd2d66ecd3 Added traffic lines arrows 2022-11-14 22:29:27 +01:00
c09525f306 Fixed map order 2022-11-14 07:09:46 +01:00
5bc7487c3a Still wrong... Fixed the broken mask. 2022-11-11 11:26:15 +01:00
9b73b0f70e Fixed broken points ordering 2022-11-11 10:40:59 +01:00
4f1f3e569b Limit ENC maps zooms
+ somemore style adjustments
2022-11-10 23:53:34 +01:00
e4847ac243 Some more ENC objects to render 2022-11-10 09:43:14 +01:00
8b039cb9a7 Merge branch 'origin/master' into Weblate. 2022-11-10 07:34:02 +01:00
37bff3d50c Version++ 2022-11-10 07:33:51 +01:00
70941405ad Merge branch 'origin/master' into Weblate. 2022-11-09 23:13:26 +01:00
c96a0fd8f4 Added missing traffic separation line style 2022-11-09 23:12:40 +01:00
5ad8f762f7 Merge branch 'origin/master' into Weblate. 2022-11-09 21:38:28 +01:00
raf
297f5f13fb Translated using Weblate (Catalan)
Currently translated at 100.0% (466 of 466 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ca/
2022-11-09 21:38:27 +01:00
985ccaf931 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (466 of 466 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2022-11-09 21:38:27 +01:00
877d9331e4 ENC map style enhancement
+ code cleanup
2022-11-09 21:37:33 +01:00
9d8c23bc32 Fixed crash on ENC map unload 2022-11-09 21:37:05 +01:00
51dd85f973 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (466 of 466 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2022-11-08 13:04:32 +01:00
af688314fb Define symbols draw order 2022-11-08 01:16:38 +01:00
1946c3cc6f Image polygon lines 2022-11-08 00:38:45 +01:00
8ae8c3b0a3 Added missing 000 files association 2022-11-06 22:13:53 +01:00
19 changed files with 341 additions and 75 deletions

View File

@ -1,4 +1,4 @@
version: 11.7.{build}
version: 11.9.{build}
configuration:
- Release

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else {
TARGET = GPXSee
}
VERSION = 11.7
VERSION = 11.9
QT += core \
gui \
@ -29,6 +29,7 @@ HEADERS += src/common/config.h \
src/GUI/pluginparameters.h \
src/common/garmin.h \
src/common/coordinates.h \
src/common/linec.h \
src/common/range.h \
src/common/rectc.h \
src/common/textcodec.h \

View File

@ -172,6 +172,7 @@
<file alias="chimney.png">icons/map/marine/chimney.png</file>
<file alias="platform.png">icons/map/marine/platform.png</file>
<file alias="ferry-line.png">icons/map/marine/ferry-line.png</file>
<file alias="dw-route-line.png">icons/map/marine/dw-route-line.png</file>
</qresource>
<!-- Mapsforge rendertheme -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1216,7 +1216,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="158"/>
<source>Electronic Navigational Charts</source>
<translation type="unfinished"></translation>
<translation>Cartes Nàutiques Electròniques</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="159"/>

View File

@ -1246,7 +1246,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="158"/>
<source>Electronic Navigational Charts</source>
<translation type="unfinished"></translation>
<translation>Elektroniske sjøkart</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="165"/>

View File

@ -1240,7 +1240,7 @@
<message>
<location filename="../src/map/maplist.cpp" line="158"/>
<source>Electronic Navigational Charts</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="165"/>

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "11.7"
!define VERSION "11.9"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -181,13 +181,14 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "qct" "QuickChart Map File" 24
!insertmacro FILE_ASSOCIATION_ADD "trk" "TwoNav Track File" 25
!insertmacro FILE_ASSOCIATION_ADD "gemf" "GEMF Map File" 26
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 27
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 27
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 28
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 29
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 30
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 31
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 32
!insertmacro FILE_ASSOCIATION_ADD "000" "IHO S-57 Electronic Navigation Chart" 27
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 28
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 28
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 29
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 30
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 31
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 32
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 33
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
@ -237,6 +238,7 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".qct\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".trk\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".gemf\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".000\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -392,6 +394,7 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "qct"
!insertmacro FILE_ASSOCIATION_REMOVE "trk"
!insertmacro FILE_ASSOCIATION_REMOVE "gemf"
!insertmacro FILE_ASSOCIATION_REMOVE "000"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -440,6 +443,7 @@ Section "Uninstall"
DeleteRegValue HKCR ".qct\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".trk\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".gemf\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".000\OpenWithList" "GPXSee.exe"
DeleteRegKey HKCR "Applications\GPXSee.exe"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'

25
src/common/linec.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef LINEC_H
#define LINEC_H
#include "coordinates.h"
class LineC
{
public:
LineC(const Coordinates &c1, const Coordinates &c2) : _c1(c1), _c2(c2) {}
const Coordinates &c1() const {return _c1;}
const Coordinates &c2() const {return _c2;}
Coordinates pointAt(double t) const
{
return Coordinates(
_c1.lon() + (_c2.lon() - _c1.lon()) * t,
_c1.lat() + (_c2.lat() - _c1.lat()) * t);
}
private:
Coordinates _c1, _c2;
};
#endif // LINEC_H

View File

@ -1,14 +1,20 @@
#ifndef ENC_ATTRIBUTES_H
#define ENC_ATTRIBUTES_H
#define CATACH 8
#define CATBUA 10
#define CATHAF 30
#define CATLMK 35
#define CATMOR 40
#define CATTRK 54
#define CATREA 56
#define CATWRK 71
#define DRVAL1 87
#define ELEVAT 90
#define OBJNAM 116
#define ORIENT 117
#define RESTRN 131
#define VALDCO 174
#define WATLEV 187
#endif // ENC_ATTRIBUTES_H

View File

@ -2,6 +2,7 @@
#include "common/util.h"
#include "objects.h"
#include "attributes.h"
#include "style.h"
#include "mapdata.h"
using namespace ENC;
@ -15,6 +16,52 @@ using namespace ENC;
#define PRIM_L 2
#define PRIM_A 3
static QMap<uint,uint> orderMapInit()
{
QMap<uint,uint> map;
map.insert(SUBTYPE(BUAARE, 1), 1);
map.insert(SUBTYPE(BUAARE, 5), 2);
map.insert(SUBTYPE(BUAARE, 4), 3);
map.insert(SUBTYPE(BUAARE, 3), 4);
map.insert(SUBTYPE(BUAARE, 2), 5);
map.insert(SUBTYPE(BUAARE, 6), 6);
map.insert(SUBTYPE(BUAARE, 0), 7);
map.insert(TYPE(BCNISD), 8);
map.insert(TYPE(BCNLAT), 9);
map.insert(TYPE(BCNSAW), 10);
map.insert(TYPE(BCNSPP), 11);
map.insert(TYPE(BOYCAR), 12);
map.insert(TYPE(BOYINB), 13);
map.insert(TYPE(BOYISD), 14);
map.insert(TYPE(BOYLAT), 15);
map.insert(TYPE(BOYSAW), 16);
map.insert(TYPE(BOYSPP), 17);
map.insert(TYPE(MORFAC), 18);
map.insert(TYPE(OFSPLF), 19);
map.insert(TYPE(LIGHTS), 20);
map.insert(TYPE(OBSTRN), 21);
map.insert(TYPE(WRECKS), 22);
map.insert(TYPE(UWTROC), 23);
map.insert(TYPE(HRBFAC), 24);
map.insert(TYPE(PILPNT), 25);
map.insert(TYPE(ACHBRT), 26);
map.insert(TYPE(LNDELV), 27);
map.insert(TYPE(LNDMRK), 28);
map.insert(TYPE(SOUNDG), 0xFFFFFFFF);
return map;
}
static QMap<uint,uint> orderMap = orderMapInit();
static uint order(uint type)
{
uint st = ((type>>16) == BUAARE) ? type : (type & 0xFFFF0000);
QMap<uint, uint>::const_iterator it = orderMap.find(st);
return (it == orderMap.constEnd()) ? (type>>16) + 512 : it.value();
}
static void warning(const ISO8211::Field &FRID, uint PRIM)
{
uint RCID = 0xFFFFFFFF;
@ -132,6 +179,13 @@ static Coordinates point(const ISO8211::Record &r, uint COMF)
return coordinates(x, y, COMF);
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label)
: _type(type), _pos(c), _label(label)
{
uint hash = (uint)qHash(QPair<double,double>(c.lon(), c.lat()));
_id = ((quint64)order(type))<<32 | hash;
}
QVector<MapData::Sounding> MapData::soundings(const ISO8211::Record &r,
uint COMF, uint SOMF)
{
@ -212,7 +266,7 @@ QVector<Coordinates> MapData::lineGeometry(const ISO8211::Record &r,
{
QVector<Coordinates> path;
Coordinates c[2];
uint ORNT, MASK;
uint ORNT;
quint8 type;
quint32 id;
@ -224,8 +278,6 @@ QVector<Coordinates> MapData::lineGeometry(const ISO8211::Record &r,
if (!parseNAME(FSPT, &type, &id, i) || type != RCNM_VE)
return QVector<Coordinates>();
ORNT = FSPT->data().at(i).at(1).toUInt();
MASK = FSPT->data().at(i).at(3).toUInt();
Q_ASSERT(MASK != 1);
RecordMapIterator it = ve.find(id);
if (it == ve.constEnd())
@ -280,7 +332,7 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
Polygon path;
QVector<Coordinates> v;
Coordinates c[2];
uint ORNT, USAG, MASK;
uint ORNT, USAG;
quint8 type;
quint32 id;
@ -293,8 +345,6 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
return Polygon();
ORNT = FSPT->data().at(i).at(1).toUInt();
USAG = FSPT->data().at(i).at(2).toUInt();
MASK = FSPT->data().at(i).at(3).toUInt();
Q_ASSERT(MASK != 1);
if (USAG == 2 && path.isEmpty()) {
path.append(v);
@ -370,12 +420,14 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = av.at(1).toString();
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == HRBFAC && key == CATHAF)
|| (OBJL == LNDMRK && key == CATLMK)
|| (OBJL == WRECKS && key == CATWRK)
|| (OBJL == MORFAC && key == CATMOR))
subtype = av.at(1).toString().toUInt();
|| (OBJL == MORFAC && key == CATMOR)
|| (OBJL == UWTROC && key == WATLEV)
|| (OBJL == BUAARE && key == CATBUA))
subtype = av.at(1).toByteArray().toUInt();
}
return Attr(subtype, label);
@ -395,10 +447,12 @@ MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = av.at(1).toString();
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == DEPCNT && key == VALDCO)
|| (OBJL == LNDELV && key == ELEVAT))
label = av.at(1).toString();
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == RECTRC || OBJL == RCRTCL) && key == CATTRK)
subtype = av.at(1).toByteArray().toUInt();
}
return Attr(subtype, label);
@ -418,9 +472,17 @@ MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL)
uint key = av.at(0).toUInt();
if (OBJL == DEPARE && key == DRVAL1)
subtype = depthLevel(av.at(1).toString());
else if (OBJL == RESARE && key == CATREA)
subtype = av.at(1).toString().toUInt();
subtype = depthLevel(av.at(1).toByteArray());
else if ((OBJL == RESARE && key == CATREA)
|| (OBJL == ACHARE && key == CATACH))
subtype = av.at(1).toByteArray().toUInt();
else if (OBJL == RESARE && key == RESTRN) {
if (av.at(1).toByteArray().toUInt() == 1)
subtype = 2;
} else if (OBJL == TSSLPT && key == ORIENT) {
double angle = av.at(1).toByteArray().toDouble();
subtype = (uint)(angle * 10);
}
}
return Attr(subtype, label);
@ -557,7 +619,7 @@ bool MapData::bounds(const QVector<ISO8211::Record> &gv, Rect &b)
return true;
}
bool MapData::fetchBoundsAndName()
MapData::MapData(const QString &path): _fileName(path)
{
QFile file(_fileName);
QVector<ISO8211::Record> gv;
@ -566,42 +628,34 @@ bool MapData::fetchBoundsAndName()
if (!file.open(QIODevice::ReadOnly)) {
_errorString = file.errorString();
return false;
return;
}
if (!ddf.readDDR(file)) {
_errorString = ddf.errorString();
return false;
return;
}
while (!file.atEnd()) {
ISO8211::Record record;
if (!ddf.readRecord(file, record)) {
_errorString = ddf.errorString();
return false;
return;
}
if (!processRecord(record, gv, COMF, _name))
return false;
return;
}
Rect b;
if (!bounds(gv, b)) {
_errorString = "Error fetching geometries bounds";
return false;
return;
}
RectC br(Coordinates(b.minX() / (double)COMF, b.maxY() / (double)COMF),
Coordinates(b.maxX() / (double)COMF, b.minY() / (double)COMF));
if (!br.isValid()) {
if (!br.isValid())
_errorString = "Invalid geometries bounds";
return false;
} else
else
_bounds = br;
return true;
}
MapData::MapData(const QString &path): _fileName(path)
{
fetchBoundsAndName();
}
MapData::~MapData()
@ -731,3 +785,41 @@ void MapData::polygons(const RectC &rect, QList<Poly*> *polygons)
rectcBounds(rect, min, max);
_areas.Search(min, max, polygonCb, polygons);
}
Range MapData::zooms() const
{
double size = qMin(_bounds.width(), _bounds.height());
if (size > 180)
return Range(0, 20);
else if (size > 90)
return Range(1, 20);
else if (size > 45)
return Range(2, 20);
else if (size > 22.5)
return Range(3, 20);
else if (size > 11.25)
return Range(4, 20);
else if (size > 5.625)
return Range(5, 20);
else if (size > 2.813)
return Range(6, 20);
else if (size > 1.406)
return Range(7, 20);
else if (size > 0.703)
return Range(8, 20);
else if (size > 0.352)
return Range(9, 20);
else if (size > 0.176)
return Range(10, 20);
else if (size > 0.088)
return Range(11, 20);
else if (size > 0.044)
return Range(12, 20);
else if (size > 0.022)
return Range(13, 20);
else if (size > 0.011)
return Range(14, 20);
else
return Range(15, 20);
}

View File

@ -5,6 +5,7 @@
#include "common/rectc.h"
#include "common/rtree.h"
#include "common/polygon.h"
#include "common/range.h"
#include "iso8211.h"
namespace ENC {
@ -52,12 +53,7 @@ public:
class Point {
public:
Point(uint type, const Coordinates &c, const QString &label)
: _type(type), _pos(c), _label(label)
{
uint hash = (uint)qHash(QPair<double,double>(c.lon(), c.lat()));
_id = ((quint64)type)<<32 | hash;
}
Point(uint type, const Coordinates &c, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
@ -78,6 +74,7 @@ public:
const QString &name() const {return _name;}
RectC bounds() const {return _bounds;}
Range zooms() const;
void polygons(const RectC &rect, QList<Poly*> *polygons);
void lines(const RectC &rect, QList<Line*> *lines);
@ -152,8 +149,6 @@ private:
typedef RTree<Line*, double, 2> LineTree;
typedef RTree<Point*, double, 2> PointTree;
bool fetchBoundsAndName();
static QVector<Sounding> soundings(const ISO8211::Record &r, uint COMF,
uint SOMF);
static QVector<Sounding> soundingGeometry(const ISO8211::Record &r,

View File

@ -9,6 +9,7 @@
#define BCNLAT 7
#define BCNSAW 8
#define BCNSPP 9
#define BERTHS 10
#define BRIDGE 11
#define BUISGL 12
#define BUAARE 13
@ -22,13 +23,17 @@
#define CBLSUB 22
#define CANALS 23
#define COALNE 30
#define DAMCON 38
#define DWRTPT 41
#define DEPARE 42
#define DEPCNT 43
#define DRGARE 46
#define DRYDOC 47
#define DMPGRD 48
#define DYKCON 49
#define FAIRWY 51
#define FERYRT 53
#define FLODOC 57
#define GATCON 61
#define HRBFAC 64
#define LAKARE 69
@ -43,14 +48,20 @@
#define PILPNT 90
#define PIPSOL 94
#define PONTON 95
#define PRCARE 96
#define PYLONS 98
#define RAILWY 106
#define RCRTCL 108
#define RECTRC 109
#define RESARE 112
#define RIVERS 114
#define ROADWY 116
#define SLCONS 122
#define SLOTOP 126
#define SOUNDG 129
#define TSELNE 145
#define TSSBND 146
#define TSSLPT 148
#define TSEZNE 150
#define UWTROC 153
#define UNSARE 154

View File

@ -1,4 +1,6 @@
#include <QtMath>
#include <QPainter>
#include "common/linec.h"
#include "map/bitmapline.h"
#include "map/textpointitem.h"
#include "map/textpathitem.h"
@ -8,9 +10,12 @@
using namespace ENC;
#define ICON_PADDING 2
#define ARROW_SIZE 0.005
#define ECDIS(x) (((x)>TYPE(17000))?((x)-TYPE(17000)):(x))
const float C1 = 0.866025f; /* sqrt(3)/2 */
static const QColor haloColor(Qt::white);
static struct {
@ -51,6 +56,36 @@ static const Style& style()
return s;
}
static double area(const QVector<Coordinates> &polygon)
{
double area = 0;
for (int i = 0; i < polygon.size(); i++) {
int j = (i + 1) % polygon.size();
area += polygon.at(i).lon() * polygon.at(j).lat();
area -= polygon.at(i).lat() * polygon.at(j).lon();
}
area /= 2.0;
return area;
}
static Coordinates centroid(const QVector<Coordinates> &polygon)
{
double cx = 0, cy = 0;
double factor = 1.0 / (6.0 * area(polygon));
for (int i = 0; i < polygon.size(); i++) {
int j = (i + 1) % polygon.size();
qreal f = (polygon.at(i).lon() * polygon.at(j).lat()
- polygon.at(j).lon() * polygon.at(i).lat());
cx += (polygon.at(i).lon() + polygon.at(j).lon()) * f;
cy += (polygon.at(i).lat() + polygon.at(j).lat()) * f;
}
return Coordinates(cx * factor, cy * factor);
}
QPainterPath RasterTile::painterPath(const Polygon &polygon) const
{
QPainterPath path;
@ -77,6 +112,48 @@ QPolygonF RasterTile::polyline(const QVector<Coordinates> &path) const
return polygon;
}
QPolygonF RasterTile::arrow(const Coordinates &c, qreal angle) const
{
Coordinates t[3], r[4];
QPolygonF polygon;
t[0] = c;
t[1] = Coordinates(t[0].lon() - qCos(angle - M_PI/3) * ARROW_SIZE,
t[0].lat() - qSin(angle - M_PI/3) * ARROW_SIZE);
t[2] = Coordinates(t[0].lon() - qCos(angle - M_PI + M_PI/3) * ARROW_SIZE,
t[0].lat() - qSin(angle - M_PI + M_PI/3) * ARROW_SIZE);
LineC l(t[1], t[2]);
r[0] = l.pointAt(0.25);
r[1] = l.pointAt(0.75);
r[2] = Coordinates(r[0].lon() - C1 * ARROW_SIZE * qCos(angle - M_PI/2),
r[0].lat() - C1 * ARROW_SIZE * qSin(angle - M_PI/2));
r[3] = Coordinates(r[1].lon() - C1 * ARROW_SIZE * qCos(angle - M_PI/2),
r[1].lat() - C1 * ARROW_SIZE * qSin(angle - M_PI/2));
polygon << ll2xy(t[0]) << ll2xy(t[2]) << ll2xy(r[1]) << ll2xy(r[3])
<< ll2xy(r[2]) << ll2xy(r[0]) << ll2xy(t[1]);
return polygon;
}
void RasterTile::drawArrows(QPainter *painter)
{
painter->setPen(QPen(QColor("#eb49eb"), 1));
painter->setBrush(QBrush("#80eb49eb"));
for (int i = 0; i < _polygons.size(); i++) {
const MapData::Poly *poly = _polygons.at(i);
if (poly->type()>>16 == TSSLPT) {
qreal angle = (poly->type() & 0xFFFF) / 10.0;
QPolygonF polygon(arrow(centroid(poly->path().first()),
deg2rad(180 - angle)));
painter->drawPolygon(polygon);
}
}
}
void RasterTile::drawPolygons(QPainter *painter)
{
const Style &s = style();
@ -88,9 +165,15 @@ void RasterTile::drawPolygons(QPainter *painter)
continue;
const Style::Polygon &style = s.polygon(ECDIS(poly->type()));
painter->setPen(style.pen());
painter->setBrush(style.brush());
painter->drawPath(painterPath(poly->path()));
if (!style.img().isNull()) {
for (int i = 0; i < poly->path().size(); i++)
BitmapLine::draw(painter, polyline(poly->path().at(i)),
style.img());
} else {
painter->setPen(style.pen());
painter->setBrush(style.brush());
painter->drawPath(painterPath(poly->path()));
}
}
}
}
@ -192,6 +275,7 @@ void RasterTile::render()
drawPolygons(&painter);
drawLines(&painter);
drawArrows(&painter);
drawTextItems(&painter, textItems);

View File

@ -32,10 +32,12 @@ private:
{return _transform.proj2img(_proj.ll2xy(c));}
QPainterPath painterPath(const Polygon &polygon) const;
QPolygonF polyline(const QVector<Coordinates> &path) const;
QPolygonF arrow(const Coordinates &c, qreal angle) const;
void processPoints(QList<TextItem*> &textItems);
void processLines(QList<TextItem*> &textItems);
void drawBitmapPath(QPainter *painter, const QImage &img,
const Polygon &polygon);
void drawArrows(QPainter *painter);
void drawPolygons(QPainter *painter);
void drawLines(QPainter *painter);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);

View File

@ -36,10 +36,9 @@ void Style::defaultPolygonStyle()
_polygons[TYPE(OBSTRN)] = Polygon(Qt::NoBrush, QPen(QColor("#000000"), 1.5,
Qt::DotLine));
_polygons[TYPE(PONTON)] = Polygon(QBrush("#333333"));
_polygons[TYPE(DRYDOC)] = Polygon(QBrush("#333333"));
_polygons[TYPE(SLCONS)] = Polygon(Qt::NoBrush, QPen(QColor("#333333"), 1.5,
Qt::DashLine));
_polygons[TYPE(ACHARE)] = Polygon(Qt::NoBrush, QPen(QColor("#e728e7"), 1,
Qt::DashDotLine));
_polygons[TYPE(LAKARE)] = Polygon(QBrush("#9fc4e1"),
QPen(QColor("#000000"), 1));
_polygons[TYPE(CANALS)] = Polygon(QBrush("#9fc4e1"),
@ -48,12 +47,25 @@ void Style::defaultPolygonStyle()
_polygons[TYPE(DYKCON)] = Polygon(QBrush(QColor("#9fc4e1"),
Qt::Dense4Pattern), QPen(QColor("#000000"), 1));
_polygons[TYPE(AIRARE)] = Polygon(QBrush("#333333"));
_polygons[SUBTYPE(RESARE, 9)] = Polygon(QBrush(QColor("#ff0000"),
Qt::BDiagPattern), QPen(QColor("#ff0000"), 1));
_polygons[TYPE(TSEZNE)] = Polygon(QBrush("#80fcb4fc"));
_polygons[TYPE(DRGARE)] = Polygon(QBrush(QColor("#a0a0ff"),
Qt::Dense4Pattern));
_polygons[TYPE(UNSARE)] = Polygon(QBrush("#999999"));
_polygons[SUBTYPE(RESARE, 9)] = Polygon(QBrush(QColor("#ff0000"),
Qt::BDiagPattern));
_polygons[SUBTYPE(RESARE, 2)] = Polygon(QImage(":/marine/noanchor-line.png"));
_polygons[SUBTYPE(ACHARE, 1)] = Polygon(QImage(":/marine/anchor-line.png"));
_polygons[TYPE(PRCARE)] = Polygon(QBrush(QColor("#eb49eb"),
Qt::BDiagPattern));
_polygons[TYPE(DAMCON)] = Polygon(QBrush("#d98b21"), QPen(QColor("#000000"),
1));
_polygons[TYPE(DRYDOC)] = Polygon(QBrush("#ebab54"), QPen(QColor("#000000"),
1));
_polygons[TYPE(PYLONS)] = Polygon(QBrush("#a58140"), QPen(QColor("#000000"),
1));
_polygons[TYPE(FLODOC)] = Polygon(QBrush("#333333"), QPen(QColor("#000000"),
1));
_polygons[TYPE(DWRTPT)] = Polygon(QImage(":/marine/dw-route-line"));
_drawOrder
<< TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0)
@ -62,12 +74,15 @@ void Style::defaultPolygonStyle()
<< SUBTYPE(DEPARE, 6) << TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON)
<< TYPE(RIVERS) << TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(BUAARE)
<< TYPE(BUISGL) << TYPE(AIRARE) << TYPE(BRIDGE) << TYPE(SLCONS)
<< TYPE(PONTON) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN)
<< TYPE(ACHARE) << SUBTYPE(RESARE, 9) << TYPE(154);
<< TYPE(PONTON) << TYPE(FLODOC) << TYPE(DRYDOC) << TYPE(DAMCON)
<< TYPE(PYLONS) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN)
<< TYPE(DWRTPT) << SUBTYPE(ACHARE, 1) << SUBTYPE(RESARE, 9)
<< SUBTYPE(RESARE, 2) << TYPE(PRCARE);
}
void Style::defaultLineStyle()
{
_lines[TYPE(BUISGL)] = Line(QPen(QColor("#966118"), 1.5));
_lines[TYPE(DEPCNT)] = Line(QPen(QColor("#659aef"), 1, Qt::SolidLine));
_lines[TYPE(DEPCNT)].setTextColor(QColor("#558adf"));
_lines[TYPE(DEPCNT)].setTextFontSize(Small);
@ -92,11 +107,22 @@ void Style::defaultLineStyle()
_lines[TYPE(RAILWY)] = Line(railroad());
_lines[TYPE(ROADWY)] = Line(QPen(QColor("#000000"), 2, Qt::SolidLine));
_lines[TYPE(GATCON)] = Line(QPen(QColor("#000000"), 2, Qt::SolidLine));
_lines[TYPE(TSELNE)] = Line(QPen(QColor("#80fcb4fc"), 4, Qt::SolidLine));
_lines[SUBTYPE(RECTRC, 1)] = Line(QPen(QColor("#000000"), 0, Qt::SolidLine));
_lines[SUBTYPE(RECTRC, 2)] = Line(QPen(QColor("#000000"), 0, Qt::DashLine));
_lines[SUBTYPE(RCRTCL, 1)] = Line(QPen(QColor("#eb49eb"), 0, Qt::SolidLine));
_lines[SUBTYPE(RCRTCL, 2)] = Line(QPen(QColor("#eb49eb"), 0, Qt::DashLine));
_lines[TYPE(FAIRWY)] = Line(QPen(QColor("#888888"), 1, Qt::DashDotDotLine));
_lines[TYPE(BERTHS)] = Line(QPen(QColor("#333333"), 2));
}
void Style::defaultPointStyle()
{
_points[TYPE(BUAARE)].setTextFontSize(Large);
_points[SUBTYPE(BUAARE, 1)].setTextFontSize(Large);
_points[SUBTYPE(BUAARE, 5)].setTextFontSize(Large);
_points[SUBTYPE(BUAARE, 3)].setTextFontSize(Small);
_points[SUBTYPE(BUAARE, 6)].setTextFontSize(Small);
_points[SUBTYPE(BUAARE, 0)].setTextFontSize(Small);
_points[TYPE(SOUNDG)].setTextFontSize(Small);
_points[TYPE(LIGHTS)] = Point(QImage(":/marine/light-major.png"), Small);
_points[TYPE(BOYCAR)] = Point(QImage(":/marine/buoy.png"), Small);
@ -114,19 +140,28 @@ void Style::defaultPointStyle()
_points[SUBTYPE(LNDMRK, 17)] = Point(QImage(":/marine/tower.png"));
_points[TYPE(LNDELV)] = Point(QImage(":/marine/triangulation-point.png"));
_points[TYPE(OBSTRN)] = Point(QImage(":/marine/obstruction.png"), Small);
_points[TYPE(WRECKS)] = Point(QImage(":/marine/wreck.png"), Small);
_points[SUBTYPE(WRECKS, 1)] = Point(QImage(":/marine/wreck.png"), Small);
_points[SUBTYPE(WRECKS, 2)] = Point(QImage(":/marine/wreck-dangerous.png"),
Small);
_points[SUBTYPE(WRECKS, 3)] = Point(QImage(":/marine/wreck.png"), Small);
_points[SUBTYPE(WRECKS, 4)] = Point(QImage(":/marine/wreck.png"), Small);
_points[SUBTYPE(WRECKS, 5)] = Point(QImage(":/marine/wreck-exposed.png"));
_points[TYPE(UWTROC)] = Point(QImage(":/marine/rock-dangerous.png"), Small);
_points[SUBTYPE(UWTROC, 1)] = Point(QImage(":/marine/rock-exposed.png"),
Small);
_points[SUBTYPE(UWTROC, 2)] = Point(QImage(":/marine/rock-exposed.png"),
Small);
_points[SUBTYPE(UWTROC, 3)] = Point(QImage(":/marine/rock-dangerous.png"),
Small);
_points[SUBTYPE(UWTROC, 4)] = Point(QImage(":/marine/rock-dangerous.png"),
Small);
_points[SUBTYPE(UWTROC, 5)] = Point(QImage(":/marine/rock-dangerous.png"),
Small);
_points[SUBTYPE(HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png"));
_points[TYPE(ACHBRT)] = Point(QImage(":/marine/anchorage.png"));
_points[TYPE(OFSPLF)] = Point(QImage(":/marine/platform.png"));
_points[TYPE(PILPNT)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 1)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 3)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 5)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 7)] = Point(QImage(":/marine/mooring-buoy.png"),
Small);

View File

@ -29,13 +29,18 @@ public:
{
_pen = (pen == Qt::NoPen) ? QPen(_brush, 0) : pen;
}
Polygon(const QImage &img)
: _brush(Qt::NoBrush), _pen(Qt::NoPen), _img(img.convertToFormat(
QImage::Format_ARGB32_Premultiplied)) {}
const QPen &pen() const {return _pen;}
const QBrush &brush() const {return _brush;}
const QImage &img() const {return _img;}
private:
QBrush _brush;
QPen _pen;
QImage _img;
};
class Line {

View File

@ -11,7 +11,6 @@
using namespace ENC;
static Range ZOOMS = Range(0, 20);
ENCMap::ENCMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _data(fileName), _projection(PCS::pcs(3857)),
@ -30,6 +29,7 @@ void ENCMap::load()
void ENCMap::unload()
{
cancelJobs(true);
_data.clear();
}
@ -38,8 +38,8 @@ int ENCMap::zoomFit(const QSize &size, const RectC &rect)
if (rect.isValid()) {
RectD pr(rect, _projection, 10);
_zoom = ZOOMS.min();
for (int i = ZOOMS.min() + 1; i <= ZOOMS.max(); i++) {
_zoom = _data.zooms().min();
for (int i = _data.zooms().min() + 1; i <= _data.zooms().max(); i++) {
Transform t(transform(i));
QRectF r(t.proj2img(pr.topLeft()), t.proj2img(pr.bottomRight()));
if (size.width() < r.width() || size.height() < r.height())
@ -47,7 +47,7 @@ int ENCMap::zoomFit(const QSize &size, const RectC &rect)
_zoom = i;
}
} else
_zoom = ZOOMS.max();
_zoom = _data.zooms().max();
updateTransform();
@ -56,18 +56,18 @@ int ENCMap::zoomFit(const QSize &size, const RectC &rect)
int ENCMap::zoomIn()
{
cancelJobs();
cancelJobs(false);
_zoom = qMin(_zoom + 1, ZOOMS.max());
_zoom = qMin(_zoom + 1, _data.zooms().max());
updateTransform();
return _zoom;
}
int ENCMap::zoomOut()
{
cancelJobs();
cancelJobs(false);
_zoom = qMax(_zoom - 1, ZOOMS.min());
_zoom = qMax(_zoom - 1, _data.zooms().min());
updateTransform();
return _zoom;
}
@ -141,10 +141,10 @@ void ENCMap::jobFinished(ENCMapJob *job)
emit tilesLoaded();
}
void ENCMap::cancelJobs()
void ENCMap::cancelJobs(bool wait)
{
for (int i = 0; i < _jobs.size(); i++)
_jobs.at(i)->cancel();
_jobs.at(i)->cancel(wait);
}
QString ENCMap::key(int zoom, const QPoint &xy) const

View File

@ -23,7 +23,12 @@ public:
_future = QtConcurrent::map(_tiles, &ENC::RasterTile::render);
_watcher.setFuture(_future);
}
void cancel() {_future.cancel();}
void cancel(bool wait)
{
_future.cancel();
if (wait)
_future.waitForFinished();
}
const QList<ENC::RasterTile> &tiles() const {return _tiles;}
signals:
@ -82,7 +87,7 @@ private:
bool isRunning(int zoom, const QPoint &xy) const;
void runJob(ENCMapJob *job);
void removeJob(ENCMapJob *job);
void cancelJobs();
void cancelJobs(bool wait);
QString key(int zoom, const QPoint &xy) const;
ENC::MapData _data;