1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-12 22:30:47 +01:00

Colored lights + sector lights in ENC maps

This commit is contained in:
Martin Tůma 2025-02-06 01:10:44 +01:00
parent 98acd3f75a
commit 0ee28d7f45
12 changed files with 319 additions and 252 deletions

View File

@ -193,6 +193,9 @@
<file alias="overfalls.png">icons/map/marine/overfalls.png</file> <file alias="overfalls.png">icons/map/marine/overfalls.png</file>
<file alias="boarding-place.png">icons/map/marine/boarding-place.png</file> <file alias="boarding-place.png">icons/map/marine/boarding-place.png</file>
<file alias="light.png">icons/map/marine/light.png</file> <file alias="light.png">icons/map/marine/light.png</file>
<file alias="light-red.png">icons/map/marine/light-red.png</file>
<file alias="light-green.png">icons/map/marine/light-green.png</file>
<file alias="light-yellow.png">icons/map/marine/light-yellow.png</file>
<file alias="building.png">icons/map/marine/building.png</file> <file alias="building.png">icons/map/marine/building.png</file>
<file alias="fog-signal.png">icons/map/marine/fog-signal.png</file> <file alias="fog-signal.png">icons/map/marine/fog-signal.png</file>
<file alias="construction.png">icons/map/marine/construction.png</file> <file alias="construction.png">icons/map/marine/construction.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

View File

@ -6,6 +6,7 @@
#define CATDIS 21 #define CATDIS 21
#define CATHAF 30 #define CATHAF 30
#define CATLMK 35 #define CATLMK 35
#define CATLIT 37
#define CATMFA 38 #define CATMFA 38
#define CATMOR 40 #define CATMOR 40
#define CATTRK 54 #define CATTRK 54
@ -16,14 +17,18 @@
#define CATWAT 69 #define CATWAT 69
#define CATWED 70 #define CATWED 70
#define CATWRK 71 #define CATWRK 71
#define COLOUR 75
#define COMCHA 77 #define COMCHA 77
#define CURVEL 84 #define CURVEL 84
#define DRVAL1 87 #define DRVAL1 87
#define ELEVAT 90 #define ELEVAT 90
#define FUNCTN 94 #define FUNCTN 94
#define LITVIS 108
#define OBJNAM 116 #define OBJNAM 116
#define ORIENT 117 #define ORIENT 117
#define RESTRN 131 #define RESTRN 131
#define SECTR1 136
#define SECTR2 137
#define TRAFIC 172 #define TRAFIC 172
#define VALDCO 174 #define VALDCO 174
#define VERCLR 181 #define VERCLR 181

View File

@ -173,19 +173,31 @@ static bool polygonCb(const MapData::Poly *polygon, void *context)
static bool polygonPointCb(const MapData::Poly *polygon, void *context) static bool polygonPointCb(const MapData::Poly *polygon, void *context)
{ {
QList<MapData::Point> *points = (QList<MapData::Point>*)context; QList<MapData::Point> *points = (QList<MapData::Point>*)context;
uint baseType = polygon->type()>>16; uint type = polygon->type();
uint baseType = type>>16;
if (!polygon->label().isEmpty() || baseType == TSSLPT || baseType == RCTLPT if (baseType == TSSLPT || baseType == RCTLPT || baseType == I_TRNBSN
|| baseType == I_TRNBSN || baseType == BRIDGE || baseType == I_BRIDGE || baseType == BUAARE
|| polygon->type() == SUBTYPE(ACHARE, 2) || baseType == RESARE || baseType == I_RESARE || baseType == LNDARE
|| polygon->type() == SUBTYPE(ACHARE, 3) || baseType == LNDRGN
|| polygon->type() == SUBTYPE(ACHARE, 9) || type == SUBTYPE(ACHARE, 2) || type == SUBTYPE(ACHARE, 3)
|| polygon->type() == SUBTYPE(I_ACHARE, 2) || type == SUBTYPE(ACHARE, 9) || type == SUBTYPE(I_ACHARE, 2)
|| polygon->type() == SUBTYPE(I_ACHARE, 3) || type == SUBTYPE(I_ACHARE, 3) || type == SUBTYPE(I_ACHARE, 9)
|| polygon->type() == SUBTYPE(I_ACHARE, 9) || type == SUBTYPE(I_BERTHS, 6))
|| polygon->type() == SUBTYPE(I_BERTHS, 6)) points->append(MapData::Point(baseType, polygon->bounds().center(),
points->append(MapData::Point(polygon->type(), polygon->bounds().center(), polygon->attributes(), polygon->HUNI()));
polygon->label(), polygon->param()));
return true;
}
static bool linePointCb(const MapData::Line *line, void *context)
{
QList<MapData::Point> *points = (QList<MapData::Point>*)context;
uint baseType = line->type()>>16;
if (baseType == RDOCAL || baseType == I_RDOCAL)
points->append(MapData::Point(baseType, line->bounds().center(),
line->attributes(), 1));
return true; return true;
} }
@ -207,10 +219,8 @@ static Coordinates point(const ISO8211::Record &r, uint COMF)
return coordinates(x, y, COMF); return coordinates(x, y, COMF);
} }
static uint depthLevel(const QByteArray &ba) static uint depthLevel(double minDepth)
{ {
double minDepth = ba.isEmpty() ? -1 : ba.toDouble();
if (minDepth < 0) if (minDepth < 0)
return 0; return 0;
else if (minDepth < 2) else if (minDepth < 2)
@ -275,72 +285,143 @@ static QString weed(uint type)
} }
} }
MapData::Point::Point(uint type, const Coordinates &c, const QString &label, MapData::Point::Point(uint type, const Coordinates &c, const QString &label)
const QVector<QByteArray> &params) : _type(type), _pos(c), _label(label) : _type(SUBTYPE(type, 0)), _pos(c), _label(label)
{ {
_id = ((quint64)order(type))<<32 | (uint)qHash(c); _id = ((quint64)order(_type))<<32 | (uint)qHash(c);
}
if (type>>16 == I_DISMAR && params.size()) { MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr,
_label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0)); uint HUNI) : _pos(c), _attr(attr)
_type = SUBTYPE(I_DISMAR, type & 0xFF); {
} else if ((type>>16 == I_RDOCAL || type>>16 == RDOCAL) && params.size() > 1) { uint subtype = 0;
if (!params.at(1).isEmpty())
_label = QString("VHF ") + QString::fromLatin1(params.at(1)); if (type == HRBFAC)
_param = QVariant(params.at(0).toDouble()); subtype = CATHAF;
} else if (type>>16 == CURENT && params.size() > 1) { else if (type == I_HRBFAC)
if (!params.at(1).isEmpty()) subtype = I_CATHAF;
_label = QString::fromLatin1(params.at(1)) else if (type == LNDMRK)
+ QString::fromUtf8("\xE2\x80\x89kt"); subtype = CATLMK;
_param = QVariant(params.at(0).toDouble()); else if (type == WRECKS)
} else if (type>>16 == I_SISTAT || type>>16 == SISTAT) { subtype = CATWRK;
else if (type == MORFAC)
subtype = CATMOR;
else if (type == UWTROC)
subtype = WATLEV;
else if (type == BUAARE)
subtype = CATBUA;
else if (type == SMCFAC)
subtype = CATSCF;
else if (type == BUISGL)
subtype = FUNCTN;
else if (type == WATTUR)
subtype = CATWAT;
else if (type == RDOCAL)
subtype = TRAFIC;
else if (type == I_RDOCAL)
subtype = TRAFIC;
else if (type == SILTNK)
subtype = CATSIL;
else if (type == WEDKLP)
subtype = CATWED;
else if (type == LIGHTS)
subtype = CATLIT;
else if (type == I_DISMAR)
subtype = CATDIS;
_type = SUBTYPE(type, _attr.value(subtype).toUInt());
_id = ((quint64)order(_type))<<32 | (uint)qHash(c);
_label = QString::fromLatin1(_attr.value(OBJNAM));
if (type == I_DISMAR) {
if (_attr.contains(I_WTWDIS) && _attr.contains(I_HUNITS))
_label = hUnits(_attr.value(I_HUNITS).toUInt()) + " "
+ QString::fromLatin1(_attr.value(I_WTWDIS));
} else if (type == I_RDOCAL || type == RDOCAL) {
QByteArray cc(_attr.value(COMCHA));
if (!cc.isEmpty())
_label = QString("VHF ") + QString::fromLatin1(cc);
} else if (type == CURENT) {
QByteArray cv(_attr.value(CURVEL));
if (!cv.isEmpty())
_label = QString::fromLatin1(cv) + QString::fromUtf8("\xE2\x80\x89kt");
} else if (type == SISTAT) {
if (_label.isEmpty() && _attr.contains(CATSIT))
_label = sistat(_attr.value(CATSIT).toUInt());
} else if (type == I_SISTAT) {
if (_label.isEmpty() && _attr.contains(I_CATSIT))
_label = sistat(_attr.value(I_CATSIT).toUInt());
} else if (type == WEDKLP) {
if (_label.isEmpty()) if (_label.isEmpty())
_label = sistat(type & 0xFF); _label = weed(_type & 0xFF);
_type = TYPE(SISTAT); } else if (type == LNDELV) {
} else if (type>>16 == WEDKLP) {
if (_label.isEmpty()) if (_label.isEmpty())
_label = weed(type & 0xFF); _label = QString::fromLatin1(_attr.value(ELEVAT))
} else if (type>>16 == LNDELV && params.size()) {
if (_label.isEmpty())
_label = QString::fromLatin1(params.at(0))
+ QString::fromUtf8("\xE2\x80\x89m"); + QString::fromUtf8("\xE2\x80\x89m");
else else
_label += "\n(" + QString::fromLatin1(params.at(0)) _label += "\n(" + QString::fromLatin1(_attr.value(ELEVAT))
+ "\xE2\x80\x89m)"; + "\xE2\x80\x89m)";
} else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size()) } else if (type == BRIDGE || type == I_BRIDGE) {
_param = QVariant(params.at(0).toDouble()); double clr = _attr.value(VERCLR).toDouble();
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
const QVariant &param) : _type(type), _pos(c), _label(label), _param(param)
{
_id = ((quint64)order(type))<<32 | (uint)qHash(c);
}
MapData::Poly::Poly(uint type, const Polygon &path, const QString &label,
const QVector<QByteArray> &params, uint HUNI) : _type(type), _path(path)
{
if (type == TYPE(DEPARE) && params.size())
_type = SUBTYPE(DEPARE, depthLevel(params.at(0)));
else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size())
_param = QVariant(params.at(0).toDouble());
else if ((type == TYPE(BRIDGE) || type == TYPE(I_BRIDGE))
&& params.size()) {
double clr = params.at(0).toDouble();
if (clr > 0) { if (clr > 0) {
_label = QString::fromUtf8("\xE2\x86\x95") + UNIT_SPACE _label = QString::fromUtf8("\xE2\x86\x95") + UNIT_SPACE
+ QString::number(clr) + UNIT_SPACE + hUnits(HUNI); + QString::number(clr) + UNIT_SPACE + hUnits(HUNI);
} }
} else if (type>>16 == LNDARE || type>>16 == SEAARE || type>>16 == BERTHS }
|| type>>16 == I_BERTHS || type>>16 == BUAARE) }
_label = label;
MapData::Poly::Poly(uint type, const Polygon &path, const Attributes &attr,
uint HUNI) : _path(path), _attr(attr), _HUNI(HUNI)
{
uint subtype = 0;
if (type == RESARE || type == I_RESARE)
subtype = CATREA;
else if (type == ACHARE)
subtype = CATACH;
else if (type == I_ACHARE)
subtype = I_CATACH;
else if (type == HRBFAC)
subtype = CATHAF;
else if (type == MARKUL)
subtype = CATMFA;
else if (type == I_BERTHS)
subtype = I_CATBRT;
else if (type == RESARE || type == I_RESARE) {
uint restr = _attr.value((type == RESARE) ? RESTRN : I_RESTRN).toUInt();
if (restr == 1)
subtype = 2;
else if (restr == 7)
subtype = 17;
}
_type = (type == DEPARE)
? SUBTYPE(DEPARE, depthLevel(_attr.value(DRVAL1).toDouble()))
: SUBTYPE(type, _attr.value(subtype).toUInt());
} }
MapData::Line::Line(uint type, const QVector<Coordinates> &path, MapData::Line::Line(uint type, const QVector<Coordinates> &path,
const QString &label, const QVector<QByteArray> &params) const Attributes &attr) : _path(path), _attr(attr)
: _type(type), _path(path), _label(label)
{ {
if ((type == TYPE(DEPCNT) || type == TYPE(LNDELV)) && params.size()) uint subtype = 0;
_label = QString::fromLatin1(params.at(0));
if (type == RECTRC)
subtype = CATTRK;
else if (type == RCRTCL)
subtype = CATTRK;
else if (type == RDOCAL)
subtype = TRAFIC;
else if (type == I_RDOCAL)
subtype = TRAFIC;
_type = SUBTYPE(type, _attr.value(subtype).toUInt());
if (type == DEPCNT)
_label = QString::fromLatin1(_attr.value(VALDCO));
else if (type == LNDELV)
_label = QString::fromLatin1(_attr.value(ELEVAT));
else
_label = QString::fromLatin1(_attr.value(OBJNAM));
} }
RectC MapData::Line::bounds() const RectC MapData::Line::bounds() const
@ -581,169 +662,46 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
return path; return path;
} }
MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL) MapData::Attributes MapData::attributes(const ISO8211::Record &r)
{ {
QString label; Attributes attr;
QVector<QByteArray> params(2);
uint subtype = 0;
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF"); const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2)) if (!(ATTF && ATTF->data().at(0).size() == 2))
return Attr(); return attr;
for (int i = 0; i < ATTF->data().size(); i++) { for (int i = 0; i < ATTF->data().size(); i++) {
const QVector<QVariant> &av = ATTF->data().at(i); const QVector<QVariant> &av = ATTF->data().at(i);
uint key = av.at(0).toUInt(); attr.insert(av.at(0).toUInt(), av.at(1).toByteArray());
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == HRBFAC && key == CATHAF)
|| (OBJL == I_HRBFAC && key == I_CATHAF)
|| (OBJL == LNDMRK && key == CATLMK)
|| (OBJL == WRECKS && key == CATWRK)
|| (OBJL == MORFAC && key == CATMOR)
|| (OBJL == UWTROC && key == WATLEV)
|| (OBJL == BUAARE && key == CATBUA)
|| (OBJL == SMCFAC && key == CATSCF)
|| (OBJL == BUISGL && key == FUNCTN)
|| (OBJL == WATTUR && key == CATWAT)
|| (OBJL == SISTAT && key == CATSIT)
|| (OBJL == I_SISTAT && key == I_CATSIT)
|| (OBJL == RDOCAL && key == TRAFIC)
|| (OBJL == I_RDOCAL && key == TRAFIC)
|| (OBJL == SILTNK && key == CATSIL)
|| (OBJL == WEDKLP && key == CATWED))
subtype = av.at(1).toByteArray().toUInt();
else if (OBJL == I_DISMAR && key == CATDIS)
subtype |= av.at(1).toByteArray().toUInt();
else if (OBJL == I_DISMAR && key == I_HUNITS)
subtype |= av.at(1).toByteArray().toUInt() << 8;
if ((OBJL == I_DISMAR && key == I_WTWDIS)
|| (OBJL == RDOCAL && key == ORIENT)
|| (OBJL == I_RDOCAL && key == ORIENT)
|| (OBJL == CURENT && key == ORIENT)
|| (OBJL == LNDELV && key == ELEVAT)
|| (OBJL == TSSLPT && key == ORIENT)
|| (OBJL == RCTLPT && key == ORIENT))
params[0] = av.at(1).toByteArray();
if ((OBJL == I_RDOCAL && key == COMCHA)
|| (OBJL == RDOCAL && key == COMCHA)
|| (OBJL == CURENT && key == CURVEL))
params[1] = av.at(1).toByteArray();
} }
return Attr(subtype, label, params); return attr;
}
MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QVector<QByteArray> params(1);
uint subtype = 0;
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2))
return Attr();
for (int i = 0; i < ATTF->data().size(); i++) {
const QVector<QVariant> &av = ATTF->data().at(i);
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == RECTRC || OBJL == RCRTCL) && key == CATTRK)
subtype = av.at(1).toByteArray().toUInt();
if ((OBJL == DEPCNT && key == VALDCO)
|| (OBJL == LNDELV && key == ELEVAT))
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, params);
}
MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QVector<QByteArray> params(1);
uint subtype = 0;
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2))
return Attr();
for (int i = 0; i < ATTF->data().size(); i++) {
const QVector<QVariant> &av = ATTF->data().at(i);
uint key = av.at(0).toUInt();
if (key == OBJNAM)
label = QString::fromLatin1(av.at(1).toByteArray());
if ((OBJL == RESARE && key == CATREA)
|| (OBJL == I_RESARE && key == CATREA)
|| (OBJL == ACHARE && key == CATACH)
|| (OBJL == I_ACHARE && key == I_CATACH)
|| (OBJL == HRBFAC && key == CATHAF)
|| (OBJL == MARKUL && key == CATMFA)
|| (OBJL == I_BERTHS && key == I_CATBRT))
subtype = av.at(1).toByteArray().toUInt();
else if ((OBJL == RESARE && key == RESTRN)
|| (OBJL == I_RESARE && key == I_RESTRN)) {
if (av.at(1).toByteArray().toUInt() == 1)
subtype = 2;
if (av.at(1).toByteArray().toUInt() == 7)
subtype = 17;
}
if ((OBJL == TSSLPT && key == ORIENT)
|| (OBJL == RCTLPT && key == ORIENT)
|| (OBJL == DEPARE && key == DRVAL1))
params[0] = av.at(1).toByteArray();
if ((OBJL == BRIDGE && key == VERCLR)
|| (OBJL == I_BRIDGE && key == VERCLR))
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, params);
} }
MapData::Point *MapData::pointObject(const Sounding &s) MapData::Point *MapData::pointObject(const Sounding &s)
{ {
return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth), return new Point(SOUNDG, s.c, QString::number(s.depth));
QVector<QByteArray>());
} }
MapData::Point *MapData::pointObject(const ISO8211::Record &r, MapData::Point *MapData::pointObject(const ISO8211::Record &r,
const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL) const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL, uint HUNI)
{ {
Coordinates c(pointGeometry(r, vi, vc, COMF)); Coordinates c(pointGeometry(r, vi, vc, COMF));
Attr attr(pointAttr(r, OBJL)); return (c.isNull() ? 0 : new Point(OBJL, c, attributes(r), HUNI));
return (c.isNull() ? 0 : new Point(SUBTYPE(OBJL,attr.subtype()), c,
attr.label(), attr.params()));
} }
MapData::Line *MapData::lineObject(const ISO8211::Record &r, MapData::Line *MapData::lineObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL) const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL)
{ {
QVector<Coordinates> path(lineGeometry(r, vc, ve, COMF)); QVector<Coordinates> path(lineGeometry(r, vc, ve, COMF));
Attr attr(lineAttr(r, OBJL)); return (path.isEmpty() ? 0 : new Line(OBJL, path, attributes(r)));
return (path.isEmpty() ? 0 : new Line(SUBTYPE(OBJL, attr.subtype()), path,
attr.label(), attr.params()));
} }
MapData::Poly *MapData::polyObject(const ISO8211::Record &r, MapData::Poly *MapData::polyObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI) const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI)
{ {
Polygon path(polyGeometry(r, vc, ve, COMF)); Polygon path(polyGeometry(r, vc, ve, COMF));
Attr attr(polyAttr(r, OBJL)); return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI));
return (path.isEmpty() ? 0 : new Poly(SUBTYPE(OBJL, attr.subtype()), path,
attr.label(), attr.params(), HUNI));
} }
bool MapData::processRecord(const ISO8211::Record &record, bool MapData::processRecord(const ISO8211::Record &record,
@ -828,7 +786,7 @@ MapData::MapData(const QString &path)
_points.Insert(min, max, point); _points.Insert(min, max, point);
} }
} else { } else {
if ((point = pointObject(r, vi, vc, COMF, OBJL))) { if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) {
pointBounds(point->pos(), min, max); pointBounds(point->pos(), min, max);
_points.Insert(min, max, point); _points.Insert(min, max, point);
} else } else
@ -875,6 +833,7 @@ void MapData::points(const RectC &rect, QList<Point> *points) const
rectcBounds(rect, min, max); rectcBounds(rect, min, max);
_points.Search(min, max, pointCb, points); _points.Search(min, max, pointCb, points);
_areas.Search(min, max, polygonPointCb, points); _areas.Search(min, max, polygonPointCb, points);
_lines.Search(min, max, linePointCb, points);
} }
void MapData::lines(const RectC &rect, QList<Line> *lines) const void MapData::lines(const RectC &rect, QList<Line> *lines) const

View File

@ -11,51 +11,51 @@ namespace ENC {
class MapData class MapData
{ {
public: public:
typedef QMap<uint, QByteArray> Attributes;
class Poly { class Poly {
public: public:
Poly(uint type, const Polygon &path, const QString &label, Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
const QVector<QByteArray> &params, uint HUNI);
RectC bounds() const {return _path.boundingRect();} RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;} const Polygon &path() const {return _path;}
uint type() const {return _type;} uint type() const {return _type;}
const QString &label() const {return _label;} const Attributes &attributes() const {return _attr;}
const QVariant &param() const {return _param;} uint HUNI() const {return _HUNI;}
private: private:
uint _type; uint _type;
Polygon _path; Polygon _path;
QString _label; Attributes _attr;
QVariant _param; uint _HUNI;
}; };
class Line { class Line {
public: public:
Line(uint type, const QVector<Coordinates> &path, const QString &label, Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
const QVector<QByteArray> &params);
RectC bounds() const; RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;} const QVector<Coordinates> &path() const {return _path;}
uint type() const {return _type;} uint type() const {return _type;}
const QString &label() const {return _label;} const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
private: private:
uint _type; uint _type;
QVector<Coordinates> _path; QVector<Coordinates> _path;
QString _label; QString _label;
Attributes _attr;
}; };
class Point { class Point {
public: public:
Point(uint type, const Coordinates &c, const QString &label, Point(uint type, const Coordinates &c, const Attributes &attr, uint HUNI);
const QVector<QByteArray> &params); Point(uint type, const Coordinates &s, const QString &label);
Point(uint type, const Coordinates &c, const QString &label,
const QVariant &param);
const Coordinates &pos() const {return _pos;} const Coordinates &pos() const {return _pos;}
uint type() const {return _type;} uint type() const {return _type;}
const QString &label() const {return _label;} const QString &label() const {return _label;}
const QVariant &param() const {return _param;} const Attributes &attributes() const {return _attr;}
bool operator<(const Point &other) const bool operator<(const Point &other) const
{return _id < other._id;} {return _id < other._id;}
@ -65,7 +65,7 @@ public:
Coordinates _pos; Coordinates _pos;
QString _label; QString _label;
quint64 _id; quint64 _id;
QVariant _param; Attributes _attr;
}; };
MapData(const QString &path); MapData(const QString &path);
@ -76,23 +76,6 @@ public:
void points(const RectC &rect, QList<Point> *points) const; void points(const RectC &rect, QList<Point> *points) const;
private: private:
class Attr {
public:
Attr() : _subtype(0) {}
Attr(uint subtype, const QString &label,
const QVector<QByteArray> &params)
: _subtype(subtype), _label(label), _params(params) {}
unsigned subtype() const {return _subtype;}
const QString &label() const {return _label;}
const QVector<QByteArray> &params() const {return _params;}
private:
unsigned _subtype;
QString _label;
QVector<QByteArray> _params;
};
struct Sounding { struct Sounding {
Sounding() : depth(NAN) {} Sounding() : depth(NAN) {}
Sounding(const Coordinates &c, double depth) : c(c), depth(depth) {} Sounding(const Coordinates &c, double depth) : c(c), depth(depth) {}
@ -117,12 +100,10 @@ private:
const RecordMap &vc, const RecordMap &ve, uint COMF); const RecordMap &vc, const RecordMap &ve, uint COMF);
static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc, static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint COMF); const RecordMap &ve, uint COMF);
static Attr pointAttr(const ISO8211::Record &r, uint OBJL); static Attributes attributes(const ISO8211::Record &r);
static Attr lineAttr(const ISO8211::Record &r, uint OBJL);
static Attr polyAttr(const ISO8211::Record &r, uint OBJL);
static Point *pointObject(const Sounding &s); static Point *pointObject(const Sounding &s);
static Point *pointObject(const ISO8211::Record &r, const RecordMap &vi, static Point *pointObject(const ISO8211::Record &r, const RecordMap &vi,
const RecordMap &vc, uint COMF, uint OBJL); const RecordMap &vc, uint COMF, uint OBJL, uint HUNI);
static Line *lineObject(const ISO8211::Record &r, const RecordMap &vc, static Line *lineObject(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint COMF, uint OBJL); const RecordMap &ve, uint COMF, uint OBJL);
static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc, static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc,

View File

@ -51,6 +51,7 @@
#define LAKARE 69 #define LAKARE 69
#define LNDARE 71 #define LNDARE 71
#define LNDELV 72 #define LNDELV 72
#define LNDRGN 73
#define LNDMRK 74 #define LNDMRK 74
#define LIGHTS 75 #define LIGHTS 75
#define LOKBSN 79 #define LOKBSN 79

View File

@ -5,6 +5,7 @@
#include "map/textpointitem.h" #include "map/textpointitem.h"
#include "map/rectd.h" #include "map/rectd.h"
#include "objects.h" #include "objects.h"
#include "attributes.h"
#include "style.h" #include "style.h"
#include "rastertile.h" #include "rastertile.h"
@ -12,8 +13,7 @@ using namespace ENC;
#define TEXT_EXTENT 160 #define TEXT_EXTENT 160
#define TSSLPT_SIZE 24 #define TSSLPT_SIZE 24
#define SECTOR_RADIUS 40
typedef QSet<Coordinates> PointSet;
static const float C1 = 0.866025f; /* sqrt(3)/2 */ static const float C1 = 0.866025f; /* sqrt(3)/2 */
static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb); static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb);
@ -145,7 +145,7 @@ void RasterTile::drawArrows(QPainter *painter,
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) { if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()), QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
deg2rad(point.param().toDouble()))); deg2rad(point.attributes().value(ORIENT).toDouble())));
drawArrow(painter, polygon, point.type()); drawArrow(painter, polygon, point.type());
} }
} }
@ -213,10 +213,42 @@ void RasterTile::drawTextItems(QPainter *painter,
} }
} }
void RasterTile::processPoints(QList<MapData::Point> &points, void RasterTile::drawSectorLights(QPainter *painter,
QList<TextItem*> &textItems, QList<TextItem*> &lights) const QList<SectorLight> &lights)
{ {
PointSet lightsSet, signalsSet; for (int i = 0; i < lights.size(); i++) {
const SectorLight &l = lights.at(i);
QPointF pos(ll2xy(l.pos));
QRectF rect(pos.x() - SECTOR_RADIUS, pos.y() - SECTOR_RADIUS,
2*SECTOR_RADIUS, 2*SECTOR_RADIUS);
double a1 = -(l.end + 90);
double a2 = -(l.start + 90);
if (a1 > a2)
a2 += 360;
if (l.visibility == 3 || l.visibility >= 6)
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
else
painter->setPen(QPen(Style::color(l.color), 5, Qt::SolidLine,
Qt::FlatCap));
painter->drawArc(rect, a1 * 16, (a2 - a1) * 16);
QLineF ln(pos, QPointF(pos.x() + 2*SECTOR_RADIUS, pos.y()));
ln.setAngle(a1);
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
painter->drawLine(ln);
ln.setAngle(a2);
painter->drawLine(ln);
}
}
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<SectorLight> &sectorLights)
{
LightMap lightsMap;
SignalSet signalsSet;
int i; int i;
std::sort(points.begin(), points.end()); std::sort(points.begin(), points.end());
@ -224,9 +256,18 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
/* Lights & Signals */ /* Lights & Signals */
for (i = 0; i < points.size(); i++) { for (i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i); const MapData::Point &point = points.at(i);
if (point.type()>>16 == LIGHTS)
lightsSet.insert(point.pos()); if (point.type()>>16 == LIGHTS) {
else if (point.type()>>16 == FOGSIG) const MapData::Attributes &attr = point.attributes();
Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
if (attr.contains(SECTR1)) {
sectorLights.append(SectorLight(point.pos(), color,
attr.value(LITVIS).toUInt(), attr.value(SECTR1).toDouble(),
attr.value(SECTR2).toDouble()));
} else
lightsMap.insert(point.pos(), color);
} else if (point.type()>>16 == FOGSIG)
signalsSet.insert(point.pos()); signalsSet.insert(point.pos());
else else
break; break;
@ -245,7 +286,7 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
const QColor *color = &style.textColor(); const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid() const QColor *hColor = style.haloColor().isValid()
? &style.haloColor() : 0; ? &style.haloColor() : 0;
double rotate = angle(point.type(), point.param()); double rotate = angle(point.type(), point.attributes().value(ORIENT));
if ((!label || !fnt) && !img) if ((!label || !fnt) && !img)
continue; continue;
@ -256,9 +297,9 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
color, hColor, 0, 2, rotate); color, hColor, 0, 2, rotate);
if (item->isValid() && !item->collides(textItems)) { if (item->isValid() && !item->collides(textItems)) {
textItems.append(item); textItems.append(item);
if (lightsSet.contains(point.pos())) if (lightsMap.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->lightOffset(), lights.append(new TextPointItem(pos + _style->lightOffset(),
0, 0, _style->light(), 0, 0, 0, 0)); 0, 0, _style->light(lightsMap.value(point.pos())), 0, 0, 0, 0));
if (signalsSet.contains(point.pos())) if (signalsSet.contains(point.pos()))
lights.append(new TextPointItem(pos + _style->signalOffset(), lights.append(new TextPointItem(pos + _style->signalOffset(),
0, 0, _style->signal(), 0, 0, 0, 0)); 0, 0, _style->signal(), 0, 0, 0, 0));
@ -326,13 +367,14 @@ void RasterTile::render()
QList<MapData::Poly> polygons; QList<MapData::Poly> polygons;
QList<MapData::Point> points; QList<MapData::Point> points;
QList<TextItem*> textItems, lights; QList<TextItem*> textItems, lights;
QList<SectorLight> sectorLights;
img.setDevicePixelRatio(_ratio); img.setDevicePixelRatio(_ratio);
img.fill(Qt::transparent); img.fill(Qt::transparent);
fetchData(polygons, lines, points); fetchData(polygons, lines, points);
processPoints(points, textItems, lights); processPoints(points, textItems, lights, sectorLights);
processLines(lines, textItems); processLines(lines, textItems);
QPainter painter(&img); QPainter painter(&img);
@ -344,7 +386,9 @@ void RasterTile::render()
drawLines(&painter, lines); drawLines(&painter, lines);
drawArrows(&painter, points); drawArrows(&painter, points);
drawTextItems(&painter, lights); drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems); drawTextItems(&painter, textItems);
qDeleteAll(textItems); qDeleteAll(textItems);

View File

@ -34,6 +34,22 @@ public:
void render(); void render();
private: private:
struct SectorLight
{
SectorLight(const Coordinates pos, Style::Color color, uint visibility,
double start, double end) : pos(pos), color(color),
visibility(visibility), start(start), end(end) {}
Coordinates pos;
Style::Color color;
uint visibility;
double start;
double end;
};
typedef QMap<Coordinates, Style::Color> LightMap;
typedef QSet<Coordinates> SignalSet;
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines, void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines,
QList<MapData::Point> &points); QList<MapData::Point> &points);
QPointF ll2xy(const Coordinates &c) const QPointF ll2xy(const Coordinates &c) const
@ -44,7 +60,8 @@ private:
QPolygonF tsslptArrow(const QPointF &p, qreal angle) const; QPolygonF tsslptArrow(const QPointF &p, qreal angle) const;
QPointF centroid(const QVector<Coordinates> &polygon) const; QPointF centroid(const QVector<Coordinates> &polygon) const;
void processPoints(QList<MapData::Point> &points, void processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem *> &lights); QList<TextItem*> &textItems, QList<TextItem *> &lights,
QList<SectorLight> &sectorLights);
void processLines(const QList<MapData::Line> &lines, void processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
void drawBitmapPath(QPainter *painter, const QImage &img, void drawBitmapPath(QPainter *painter, const QImage &img,
@ -53,6 +70,7 @@ private:
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons); void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
void drawLines(QPainter *painter, const QList<MapData::Line> &lines); void drawLines(QPainter *painter, const QList<MapData::Line> &lines);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems); void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights);
static bool polyCb(MapData *data, void *context); static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context); static bool pointCb(MapData *data, void *context);

View File

@ -222,6 +222,14 @@ void Style::lineStyle(qreal ratio)
_lines[TYPE(PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png")); _lines[TYPE(PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png"));
_lines[TYPE(I_PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png")); _lines[TYPE(I_PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png"));
_lines[TYPE(CANALS)] = Line(QPen(QColor(0x9f, 0xc4, 0xe1), 2)); _lines[TYPE(CANALS)] = Line(QPen(QColor(0x9f, 0xc4, 0xe1), 2));
_lines[SUBTYPE(RDOCAL, 1)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 2)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 3)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
_lines[SUBTYPE(RDOCAL, 4)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1,
Qt::DashLine));
} }
void Style::pointStyle(qreal ratio) void Style::pointStyle(qreal ratio)
@ -302,7 +310,9 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(I_HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png")); _points[SUBTYPE(I_HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png"));
_points[SUBTYPE(I_HRBFAC, 9)] = Point(QImage(":/marine/shipyard.png")); _points[SUBTYPE(I_HRBFAC, 9)] = Point(QImage(":/marine/shipyard.png"));
_points[TYPE(ACHBRT)] = Point(QImage(":/marine/anchorage.png")); _points[TYPE(ACHBRT)] = Point(QImage(":/marine/anchorage.png"));
_points[TYPE(I_ACHBRT)] = Point(QImage(":/marine/anchorage.png")); _points[TYPE(ACHBRT)].setTextColor(QColor(0xeb, 0x49, 0xeb));
_points[TYPE(ACHBRT)].setHaloColor(QColor());
_points[TYPE(I_ACHBRT)] = _points[TYPE(ACHBRT)];
_points[TYPE(OFSPLF)] = Point(QImage(":/marine/platform.png")); _points[TYPE(OFSPLF)] = Point(QImage(":/marine/platform.png"));
_points[TYPE(PILPNT)] = Point(QImage(":/marine/pile.png"), Small); _points[TYPE(PILPNT)] = Point(QImage(":/marine/pile.png"), Small);
_points[SUBTYPE(MORFAC, 1)] = Point(QImage(":/marine/pile.png"), Small); _points[SUBTYPE(MORFAC, 1)] = Point(QImage(":/marine/pile.png"), Small);
@ -366,6 +376,8 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(WEDKLP, 0)] = Point(QImage(":/marine/kelp.png")); _points[SUBTYPE(WEDKLP, 0)] = Point(QImage(":/marine/kelp.png"));
_points[SUBTYPE(WEDKLP, 1)] = Point(QImage(":/marine/kelp.png")); _points[SUBTYPE(WEDKLP, 1)] = Point(QImage(":/marine/kelp.png"));
_points[TYPE(SEAARE)].setHaloColor(QColor()); _points[TYPE(SEAARE)].setHaloColor(QColor());
_points[TYPE(LNDARE)].setHaloColor(QColor());
_points[TYPE(LNDRGN)].setHaloColor(QColor());
_points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png")); _points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png"));
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"), _points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"),
@ -427,6 +439,9 @@ void Style::pointStyle(qreal ratio)
Style::Style(qreal ratio) Style::Style(qreal ratio)
{ {
_light = QImage(":/marine/light.png"); _light = QImage(":/marine/light.png");
_lightRed = QImage(":/marine/light-red.png");
_lightGreen = QImage(":/marine/light-green.png");
_lightYellow = QImage(":/marine/light-yellow.png");
_lightOffset = QPoint(11, 11); _lightOffset = QPoint(11, 11);
_signal = QImage(":/marine/fog-signal.png"); _signal = QImage(":/marine/fog-signal.png");
_signalOffset = QPoint(-9, 9); _signalOffset = QPoint(-9, 9);
@ -477,3 +492,37 @@ const QFont *Style::font(Style::FontSize size) const
return &_normal; return &_normal;
} }
} }
const QImage *Style::light(Color color) const
{
switch (color) {
case Red:
return &_lightRed;
case Green:
return &_lightGreen;
case White:
case Yellow:
case Amber:
case Orange:
return &_lightYellow;
default:
return &_light;
}
}
QColor Style::color(Style::Color c)
{
switch (c) {
case Red:
return Qt::red;
case Green:
return Qt::green;
case White:
case Yellow:
case Amber:
case Orange:
return Qt::yellow;
default:
return Qt::magenta;
}
}

View File

@ -89,6 +89,11 @@ public:
QPoint _offset; QPoint _offset;
}; };
enum Color {
Unknown, White, Black, Red, Green, Blue, Yellow, Gray,
Brown, Amber, Violet, Orange, Magenta, Pink
};
Style(qreal ratio); Style(qreal ratio);
const Line &line(uint type) const; const Line &line(uint type) const;
@ -97,11 +102,13 @@ public:
const QVector<uint> &drawOrder() const {return _drawOrder;} const QVector<uint> &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size) const; const QFont *font(Style::FontSize size) const;
const QImage *light() const {return &_light;} const QImage *light(Color color) const;
const QImage *signal() const {return &_signal;} const QImage *signal() const {return &_signal;}
const QPoint &lightOffset() const {return _lightOffset;} const QPoint &lightOffset() const {return _lightOffset;}
const QPoint &signalOffset() const {return _signalOffset;} const QPoint &signalOffset() const {return _signalOffset;}
static QColor color(Color c);
private: private:
void polygonStyle(); void polygonStyle();
void lineStyle(qreal ratio); void lineStyle(qreal ratio);
@ -114,7 +121,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */ /* Fonts and images must be initialized after QGuiApplication! */
QFont _small, _normal, _large; QFont _small, _normal, _large;
QImage _light, _signal; QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
QPoint _lightOffset, _signalOffset; QPoint _lightOffset, _signalOffset;
}; };