diff --git a/gpxsee.pro b/gpxsee.pro
index 9c512cca..4b279f37 100644
--- a/gpxsee.pro
+++ b/gpxsee.pro
@@ -118,6 +118,7 @@ HEADERS += src/common/config.h \
src/data/gpsdumpparser.h \
src/data/style.h \
src/data/twonavparser.h \
+ src/map/IMG/lights.h \
src/map/downloader.h \
src/map/demloader.h \
src/map/ENC/attributes.h \
diff --git a/gpxsee.qrc b/gpxsee.qrc
index b75d8f19..8eca235c 100644
--- a/gpxsee.qrc
+++ b/gpxsee.qrc
@@ -193,6 +193,10 @@
icons/map/marine/overfalls.png
icons/map/marine/boarding-place.png
icons/map/marine/light.png
+ icons/map/marine/light-red.png
+ icons/map/marine/light-green.png
+ icons/map/marine/light-yellow.png
+ icons/map/marine/light-white.png
icons/map/marine/building.png
icons/map/marine/fog-signal.png
icons/map/marine/construction.png
diff --git a/icons/map/marine/anchorage.png b/icons/map/marine/anchorage.png
index 9b8f2de6..e87bb9f5 100644
Binary files a/icons/map/marine/anchorage.png and b/icons/map/marine/anchorage.png differ
diff --git a/icons/map/marine/anchoring-prohibited.png b/icons/map/marine/anchoring-prohibited.png
index b17d2317..3463fa39 100644
Binary files a/icons/map/marine/anchoring-prohibited.png and b/icons/map/marine/anchoring-prohibited.png differ
diff --git a/icons/map/marine/light-green.png b/icons/map/marine/light-green.png
new file mode 100644
index 00000000..af48f5d1
Binary files /dev/null and b/icons/map/marine/light-green.png differ
diff --git a/icons/map/marine/light-red.png b/icons/map/marine/light-red.png
new file mode 100644
index 00000000..199b7ece
Binary files /dev/null and b/icons/map/marine/light-red.png differ
diff --git a/icons/map/marine/light-white.png b/icons/map/marine/light-white.png
new file mode 100644
index 00000000..a0e2d062
Binary files /dev/null and b/icons/map/marine/light-white.png differ
diff --git a/icons/map/marine/light-yellow.png b/icons/map/marine/light-yellow.png
new file mode 100644
index 00000000..4b7ca018
Binary files /dev/null and b/icons/map/marine/light-yellow.png differ
diff --git a/icons/map/marine/pipeline.png b/icons/map/marine/pipeline.png
index 23072601..55ff9b58 100644
Binary files a/icons/map/marine/pipeline.png and b/icons/map/marine/pipeline.png differ
diff --git a/src/map/ENC/attributes.h b/src/map/ENC/attributes.h
index c2f7bf3b..01ee9b91 100644
--- a/src/map/ENC/attributes.h
+++ b/src/map/ENC/attributes.h
@@ -6,6 +6,7 @@
#define CATDIS 21
#define CATHAF 30
#define CATLMK 35
+#define CATLIT 37
#define CATMFA 38
#define CATMOR 40
#define CATTRK 54
@@ -16,16 +17,21 @@
#define CATWAT 69
#define CATWED 70
#define CATWRK 71
+#define COLOUR 75
#define COMCHA 77
#define CURVEL 84
#define DRVAL1 87
#define ELEVAT 90
#define FUNCTN 94
+#define LITVIS 108
#define OBJNAM 116
#define ORIENT 117
#define RESTRN 131
+#define SECTR1 136
+#define SECTR2 137
#define TRAFIC 172
#define VALDCO 174
+#define VALNMR 178
#define VERCLR 181
#define WATLEV 187
diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp
index 79fd75f6..41c594e2 100644
--- a/src/map/ENC/mapdata.cpp
+++ b/src/map/ENC/mapdata.cpp
@@ -173,19 +173,31 @@ static bool polygonCb(const MapData::Poly *polygon, void *context)
static bool polygonPointCb(const MapData::Poly *polygon, void *context)
{
QList *points = (QList*)context;
- uint baseType = polygon->type()>>16;
+ uint type = polygon->type();
+ uint baseType = type>>16;
- if (!polygon->label().isEmpty() || baseType == TSSLPT || baseType == RCTLPT
- || baseType == I_TRNBSN
- || polygon->type() == SUBTYPE(ACHARE, 2)
- || polygon->type() == SUBTYPE(ACHARE, 3)
- || polygon->type() == SUBTYPE(ACHARE, 9)
- || polygon->type() == SUBTYPE(I_ACHARE, 2)
- || polygon->type() == SUBTYPE(I_ACHARE, 3)
- || polygon->type() == SUBTYPE(I_ACHARE, 9)
- || polygon->type() == SUBTYPE(I_BERTHS, 6))
- points->append(MapData::Point(polygon->type(), polygon->bounds().center(),
- polygon->label(), polygon->param()));
+ if (baseType == TSSLPT || baseType == RCTLPT || baseType == I_TRNBSN
+ || baseType == BRIDGE || baseType == I_BRIDGE || baseType == BUAARE
+ || baseType == RESARE || baseType == I_RESARE || baseType == LNDARE
+ || baseType == LNDRGN
+ || type == SUBTYPE(ACHARE, 2) || type == SUBTYPE(ACHARE, 3)
+ || type == SUBTYPE(ACHARE, 9) || type == SUBTYPE(I_ACHARE, 2)
+ || type == SUBTYPE(I_ACHARE, 3) || type == SUBTYPE(I_ACHARE, 9)
+ || type == SUBTYPE(I_BERTHS, 6))
+ points->append(MapData::Point(baseType, polygon->bounds().center(),
+ polygon->attributes(), polygon->HUNI()));
+
+ return true;
+}
+
+static bool linePointCb(const MapData::Line *line, void *context)
+{
+ QList *points = (QList*)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;
}
@@ -207,10 +219,8 @@ static Coordinates point(const ISO8211::Record &r, uint 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)
return 0;
else if (minDepth < 2)
@@ -275,72 +285,145 @@ static QString weed(uint type)
}
}
-MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
- const QVector ¶ms) : _type(type), _pos(c), _label(label)
+MapData::Point::Point(uint type, const Coordinates &c, const QString &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()) {
- _label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0));
- _type = SUBTYPE(I_DISMAR, type & 0xFF);
- } else if ((type>>16 == I_RDOCAL || type>>16 == RDOCAL) && params.size() > 1) {
- if (!params.at(1).isEmpty())
- _label = QString("VHF ") + QString::fromLatin1(params.at(1));
- _param = QVariant(params.at(0).toDouble());
- } else if (type>>16 == CURENT && params.size() > 1) {
- if (!params.at(1).isEmpty())
- _label = QString::fromLatin1(params.at(1))
- + QString::fromUtf8("\xE2\x80\x89kt");
- _param = QVariant(params.at(0).toDouble());
- } else if (type>>16 == I_SISTAT || type>>16 == SISTAT) {
+MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr,
+ uint HUNI) : _pos(c), _attr(attr)
+{
+ uint subtype = 0;
+
+ if (type == HRBFAC)
+ subtype = CATHAF;
+ else if (type == I_HRBFAC)
+ subtype = I_CATHAF;
+ else if (type == LNDMRK)
+ subtype = CATLMK;
+ else if (type == WRECKS)
+ 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;
+
+ QList list(_attr.value(subtype).split(','));
+ std::sort(list.begin(), list.end());
+ _type = SUBTYPE(type, list.first().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())
- _label = sistat(type & 0xFF);
- _type = TYPE(SISTAT);
- } else if (type>>16 == WEDKLP) {
+ _label = weed(_type & 0xFF);
+ } else if (type == LNDELV) {
if (_label.isEmpty())
- _label = weed(type & 0xFF);
- } else if (type>>16 == LNDELV && params.size()) {
- if (_label.isEmpty())
- _label = QString::fromLatin1(params.at(0))
+ _label = QString::fromLatin1(_attr.value(ELEVAT))
+ QString::fromUtf8("\xE2\x80\x89m");
else
- _label += "\n(" + QString::fromLatin1(params.at(0))
+ _label += "\n(" + QString::fromLatin1(_attr.value(ELEVAT))
+ "\xE2\x80\x89m)";
- } else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size())
- _param = QVariant(params.at(0).toDouble());
-}
-
-MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
- const QVariant ¶m) : _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 ¶ms, 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();
+ } else if (type == BRIDGE || type == I_BRIDGE) {
+ double clr = _attr.value(VERCLR).toDouble();
if (clr > 0) {
_label = QString::fromUtf8("\xE2\x86\x95") + UNIT_SPACE
+ 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 &path,
- const QString &label, const QVector ¶ms)
- : _type(type), _path(path), _label(label)
+ const Attributes &attr) : _path(path), _attr(attr)
{
- if ((type == TYPE(DEPCNT) || type == TYPE(LNDELV)) && params.size())
- _label = QString::fromLatin1(params.at(0));
+ uint subtype = 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
@@ -581,169 +664,46 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
return path;
}
-MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
+MapData::Attributes MapData::attributes(const ISO8211::Record &r)
{
- QString label;
- QVector params(2);
- uint subtype = 0;
+ Attributes attr;
const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF");
if (!(ATTF && ATTF->data().at(0).size() == 2))
- return Attr();
+ return attr;
for (int i = 0; i < ATTF->data().size(); i++) {
const QVector &av = ATTF->data().at(i);
- uint key = av.at(0).toUInt();
-
- 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();
+ attr.insert(av.at(0).toUInt(), av.at(1).toByteArray());
}
- return Attr(subtype, label, params);
-}
-
-MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
-{
- QString label;
- QVector 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 &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 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 &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);
+ return attr;
}
MapData::Point *MapData::pointObject(const Sounding &s)
{
- return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth),
- QVector());
+ return new Point(SOUNDG, s.c, QString::number(s.depth));
}
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));
- Attr attr(pointAttr(r, OBJL));
-
- return (c.isNull() ? 0 : new Point(SUBTYPE(OBJL,attr.subtype()), c,
- attr.label(), attr.params()));
+ return (c.isNull() ? 0 : new Point(OBJL, c, attributes(r), HUNI));
}
MapData::Line *MapData::lineObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL)
{
QVector path(lineGeometry(r, vc, ve, COMF));
- Attr attr(lineAttr(r, OBJL));
-
- return (path.isEmpty() ? 0 : new Line(SUBTYPE(OBJL, attr.subtype()), path,
- attr.label(), attr.params()));
+ return (path.isEmpty() ? 0 : new Line(OBJL, path, attributes(r)));
}
MapData::Poly *MapData::polyObject(const ISO8211::Record &r,
const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI)
{
Polygon path(polyGeometry(r, vc, ve, COMF));
- Attr attr(polyAttr(r, OBJL));
-
- return (path.isEmpty() ? 0 : new Poly(SUBTYPE(OBJL, attr.subtype()), path,
- attr.label(), attr.params(), HUNI));
+ return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI));
}
bool MapData::processRecord(const ISO8211::Record &record,
@@ -828,7 +788,7 @@ MapData::MapData(const QString &path)
_points.Insert(min, max, point);
}
} else {
- if ((point = pointObject(r, vi, vc, COMF, OBJL))) {
+ if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) {
pointBounds(point->pos(), min, max);
_points.Insert(min, max, point);
} else
@@ -875,6 +835,7 @@ void MapData::points(const RectC &rect, QList *points) const
rectcBounds(rect, min, max);
_points.Search(min, max, pointCb, points);
_areas.Search(min, max, polygonPointCb, points);
+ _lines.Search(min, max, linePointCb, points);
}
void MapData::lines(const RectC &rect, QList *lines) const
diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h
index 9dc46d33..92e1b137 100644
--- a/src/map/ENC/mapdata.h
+++ b/src/map/ENC/mapdata.h
@@ -11,51 +11,51 @@ namespace ENC {
class MapData
{
public:
+ typedef QMap Attributes;
+
class Poly {
public:
- Poly(uint type, const Polygon &path, const QString &label,
- const QVector ¶ms, uint HUNI);
+ Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
- const QString &label() const {return _label;}
- const QVariant ¶m() const {return _param;}
+ const Attributes &attributes() const {return _attr;}
+ uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
- QString _label;
- QVariant _param;
+ Attributes _attr;
+ uint _HUNI;
};
class Line {
public:
- Line(uint type, const QVector &path, const QString &label,
- const QVector ¶ms);
+ Line(uint type, const QVector &path, const Attributes &attr);
RectC bounds() const;
const QVector &path() const {return _path;}
uint type() const {return _type;}
const QString &label() const {return _label;}
+ const Attributes &attributes() const {return _attr;}
private:
uint _type;
QVector _path;
QString _label;
+ Attributes _attr;
};
class Point {
public:
- Point(uint type, const Coordinates &c, const QString &label,
- const QVector ¶ms);
- Point(uint type, const Coordinates &c, const QString &label,
- const QVariant ¶m);
+ Point(uint type, const Coordinates &c, const Attributes &attr, uint HUNI);
+ Point(uint type, const Coordinates &s, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
- const QVariant ¶m() const {return _param;}
+ const Attributes &attributes() const {return _attr;}
bool operator<(const Point &other) const
{return _id < other._id;}
@@ -65,7 +65,7 @@ public:
Coordinates _pos;
QString _label;
quint64 _id;
- QVariant _param;
+ Attributes _attr;
};
MapData(const QString &path);
@@ -76,23 +76,6 @@ public:
void points(const RectC &rect, QList *points) const;
private:
- class Attr {
- public:
- Attr() : _subtype(0) {}
- Attr(uint subtype, const QString &label,
- const QVector ¶ms)
- : _subtype(subtype), _label(label), _params(params) {}
-
- unsigned subtype() const {return _subtype;}
- const QString &label() const {return _label;}
- const QVector ¶ms() const {return _params;}
-
- private:
- unsigned _subtype;
- QString _label;
- QVector _params;
- };
-
struct Sounding {
Sounding() : depth(NAN) {}
Sounding(const Coordinates &c, double depth) : c(c), depth(depth) {}
@@ -117,12 +100,10 @@ private:
const RecordMap &vc, const RecordMap &ve, uint COMF);
static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
const RecordMap &ve, uint COMF);
- static Attr pointAttr(const ISO8211::Record &r, uint OBJL);
- static Attr lineAttr(const ISO8211::Record &r, uint OBJL);
- static Attr polyAttr(const ISO8211::Record &r, uint OBJL);
+ static Attributes attributes(const ISO8211::Record &r);
static Point *pointObject(const Sounding &s);
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,
const RecordMap &ve, uint COMF, uint OBJL);
static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc,
diff --git a/src/map/ENC/objects.h b/src/map/ENC/objects.h
index 580a5bf6..8f1aa498 100644
--- a/src/map/ENC/objects.h
+++ b/src/map/ENC/objects.h
@@ -51,6 +51,7 @@
#define LAKARE 69
#define LNDARE 71
#define LNDELV 72
+#define LNDRGN 73
#define LNDMRK 74
#define LIGHTS 75
#define LOKBSN 79
diff --git a/src/map/ENC/rastertile.cpp b/src/map/ENC/rastertile.cpp
index 8d2ac9f2..fe84dc3c 100644
--- a/src/map/ENC/rastertile.cpp
+++ b/src/map/ENC/rastertile.cpp
@@ -5,6 +5,7 @@
#include "map/textpointitem.h"
#include "map/rectd.h"
#include "objects.h"
+#include "attributes.h"
#include "style.h"
#include "rastertile.h"
@@ -12,8 +13,7 @@ using namespace ENC;
#define TEXT_EXTENT 160
#define TSSLPT_SIZE 24
-
-typedef QSet PointSet;
+#define RANGE_FACTOR 4
static const float C1 = 0.866025f; /* sqrt(3)/2 */
static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb);
@@ -138,21 +138,21 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type)
}
void RasterTile::drawArrows(QPainter *painter,
- const QList &points)
+ const QList &points) const
{
for (int i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
- deg2rad(point.param().toDouble())));
+ deg2rad(point.attributes().value(ORIENT).toDouble())));
drawArrow(painter, polygon, point.type());
}
}
}
void RasterTile::drawPolygons(QPainter *painter,
- const QList &polygons)
+ const QList &polygons) const
{
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
@@ -184,7 +184,7 @@ void RasterTile::drawPolygons(QPainter *painter,
}
}
-void RasterTile::drawLines(QPainter *painter, const QList &lines)
+void RasterTile::drawLines(QPainter *painter, const QList &lines) const
{
painter->setBrush(Qt::NoBrush);
@@ -202,7 +202,7 @@ void RasterTile::drawLines(QPainter *painter, const QList &lines)
}
void RasterTile::drawTextItems(QPainter *painter,
- const QList &textItems)
+ const QList &textItems) const
{
QRectF rect(_rect);
@@ -213,10 +213,56 @@ void RasterTile::drawTextItems(QPainter *painter,
}
}
-void RasterTile::processPoints(QList &points,
- QList &textItems, QList &lights)
+static QRectF lightRect(const QPointF &pos, double range)
{
- PointSet lightsSet, signalsSet;
+ return QRectF(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR,
+ 2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR);
+}
+
+void RasterTile::drawSectorLights(QPainter *painter,
+ const QList &lights) const
+{
+ for (int i = 0; i < lights.size(); i++) {
+ const SectorLight &l = lights.at(i);
+ QPointF pos(ll2xy(l.pos));
+ QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range));
+ double a1 = -(l.end + 90);
+ double a2 = -(l.start + 90);
+ if (a1 > a2)
+ a2 += 360;
+ double as = (a2 - a1);
+ if (as == 0)
+ as = 360;
+
+ if (l.visibility == 3 || l.visibility >= 6)
+ painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
+ else {
+ painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
+ painter->drawArc(rect, a1 * 16, as * 16);
+ painter->setPen(QPen(Style::color(l.color), 4, Qt::SolidLine,
+ Qt::FlatCap));
+ }
+
+ painter->drawArc(rect, a1 * 16, as * 16);
+
+ if (a2 - a1 != 0) {
+ QLineF ln(pos, QPointF(pos.x() + rect.width(), 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 &points,
+ QList &textItems, QList &lights,
+ QList §orLights)
+{
+ LightMap lightsMap;
+ SignalSet signalsSet;
+ QSet slMap;
int i;
std::sort(points.begin(), points.end());
@@ -224,9 +270,22 @@ void RasterTile::processPoints(QList &points,
/* Lights & Signals */
for (i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
- if (point.type()>>16 == LIGHTS)
- lightsSet.insert(point.pos());
- else if (point.type()>>16 == FOGSIG)
+
+ if (point.type()>>16 == LIGHTS) {
+ const MapData::Attributes &attr = point.attributes();
+ Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
+ double range = attr.value(VALNMR).toDouble();
+
+ if (attr.contains(SECTR1)
+ || (range >= 6 && !(point.type() & 0xFFFF))) {
+ sectorLights.append(SectorLight(point.pos(), color,
+ attr.value(LITVIS).toUInt(), range,
+ attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble()));
+ slMap.insert(point.pos());
+ qDebug() << attr;
+ } else
+ lightsMap.insert(point.pos(), color);
+ } else if (point.type()>>16 == FOGSIG)
signalsSet.insert(point.pos());
else
break;
@@ -245,7 +304,7 @@ void RasterTile::processPoints(QList &points,
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
? &style.haloColor() : 0;
- double rotate = angle(point.type(), point.param());
+ double rotate = angle(point.type(), point.attributes().value(ORIENT));
if ((!label || !fnt) && !img)
continue;
@@ -254,11 +313,12 @@ void RasterTile::processPoints(QList &points,
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
color, hColor, 0, 2, rotate);
- if (item->isValid() && !item->collides(textItems)) {
+ if (item->isValid() && (slMap.contains(point.pos())
+ || !item->collides(textItems))) {
textItems.append(item);
- if (lightsSet.contains(point.pos()))
+ if (lightsMap.contains(point.pos()))
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()))
lights.append(new TextPointItem(pos + _style->signalOffset(),
0, 0, _style->signal(), 0, 0, 0, 0));
@@ -326,13 +386,14 @@ void RasterTile::render()
QList polygons;
QList points;
QList textItems, lights;
+ QList sectorLights;
img.setDevicePixelRatio(_ratio);
img.fill(Qt::transparent);
fetchData(polygons, lines, points);
- processPoints(points, textItems, lights);
+ processPoints(points, textItems, lights, sectorLights);
processLines(lines, textItems);
QPainter painter(&img);
@@ -344,7 +405,9 @@ void RasterTile::render()
drawLines(&painter, lines);
drawArrows(&painter, points);
+
drawTextItems(&painter, lights);
+ drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
diff --git a/src/map/ENC/rastertile.h b/src/map/ENC/rastertile.h
index 2d17a6dd..259ca72b 100644
--- a/src/map/ENC/rastertile.h
+++ b/src/map/ENC/rastertile.h
@@ -34,6 +34,23 @@ public:
void render();
private:
+ struct SectorLight
+ {
+ SectorLight(const Coordinates &pos, Style::Color color, uint visibility,
+ double range, double start, double end) : pos(pos), color(color),
+ visibility(visibility), range(range), start(start), end(end) {}
+
+ Coordinates pos;
+ Style::Color color;
+ uint visibility;
+ double range;
+ double start;
+ double end;
+ };
+
+ typedef QMap LightMap;
+ typedef QSet SignalSet;
+
void fetchData(QList &polygons, QList &lines,
QList &points);
QPointF ll2xy(const Coordinates &c) const
@@ -44,15 +61,15 @@ private:
QPolygonF tsslptArrow(const QPointF &p, qreal angle) const;
QPointF centroid(const QVector &polygon) const;
void processPoints(QList &points,
- QList &textItems, QList &lights);
+ QList &textItems, QList &lights,
+ QList §orLights);
void processLines(const QList &lines,
QList &textItems);
- void drawBitmapPath(QPainter *painter, const QImage &img,
- const Polygon &polygon);
- void drawArrows(QPainter *painter, const QList &points);
- void drawPolygons(QPainter *painter, const QList &polygons);
- void drawLines(QPainter *painter, const QList &lines);
- void drawTextItems(QPainter *painter, const QList &textItems);
+ void drawArrows(QPainter *painter, const QList &points) const;
+ void drawPolygons(QPainter *painter, const QList &polygons) const;
+ void drawLines(QPainter *painter, const QList &lines) const;
+ void drawTextItems(QPainter *painter, const QList &textItems) const;
+ void drawSectorLights(QPainter *painter, const QList &lights) const;
static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context);
diff --git a/src/map/ENC/style.cpp b/src/map/ENC/style.cpp
index 1f94eb2f..f39631c3 100644
--- a/src/map/ENC/style.cpp
+++ b/src/map/ENC/style.cpp
@@ -222,6 +222,14 @@ void Style::lineStyle(qreal ratio)
_lines[TYPE(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[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)
@@ -302,7 +310,9 @@ void Style::pointStyle(qreal ratio)
_points[SUBTYPE(I_HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png"));
_points[SUBTYPE(I_HRBFAC, 9)] = Point(QImage(":/marine/shipyard.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(PILPNT)] = 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, 1)] = Point(QImage(":/marine/kelp.png"));
_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[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"),
@@ -427,6 +439,9 @@ void Style::pointStyle(qreal ratio)
Style::Style(qreal ratio)
{
_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);
_signal = QImage(":/marine/fog-signal.png");
_signalOffset = QPoint(-9, 9);
@@ -477,3 +492,37 @@ const QFont *Style::font(Style::FontSize size) const
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;
+ }
+}
diff --git a/src/map/ENC/style.h b/src/map/ENC/style.h
index ef62d38e..9d6edf7c 100644
--- a/src/map/ENC/style.h
+++ b/src/map/ENC/style.h
@@ -89,6 +89,11 @@ public:
QPoint _offset;
};
+ enum Color {
+ Unknown, White, Black, Red, Green, Blue, Yellow, Gray,
+ Brown, Amber, Violet, Orange, Magenta, Pink
+ };
+
Style(qreal ratio);
const Line &line(uint type) const;
@@ -97,11 +102,13 @@ public:
const QVector &drawOrder() const {return _drawOrder;}
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 QPoint &lightOffset() const {return _lightOffset;}
const QPoint &signalOffset() const {return _signalOffset;}
+ static QColor color(Color c);
+
private:
void polygonStyle();
void lineStyle(qreal ratio);
@@ -114,7 +121,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */
QFont _small, _normal, _large;
- QImage _light, _signal;
+ QImage _light, _lightRed, _lightGreen, _lightYellow, _signal;
QPoint _lightOffset, _signalOffset;
};
diff --git a/src/map/IMG/lights.h b/src/map/IMG/lights.h
new file mode 100644
index 00000000..c722f73e
--- /dev/null
+++ b/src/map/IMG/lights.h
@@ -0,0 +1,51 @@
+#ifndef IMG_LIGHTS_H
+#define IMG_LIGHTS_H
+
+#include
+#include
+
+namespace IMG {
+
+class Lights
+{
+public:
+ enum Color {None, Red, Green, White, Blue, Yellow, Violet, Amber};
+
+ struct Sector
+ {
+ Sector() : color(None), angle(0), range(0) {}
+ Sector(Color color, quint32 angle, quint32 range)
+ : color(color), angle(angle), range(range) {}
+
+ Color color;
+ quint32 angle;
+ quint32 range;
+ };
+
+ Lights() : color(None), range(0) {}
+ bool isSectorLight() const {return ((color && range) || !sectors.isEmpty());}
+
+ Color color;
+ quint32 range;
+ QVector sectors;
+};
+
+}
+
+#ifndef QT_NO_DEBUG
+inline QDebug operator<<(QDebug dbg, const IMG::Lights::Sector §or)
+{
+ dbg.nospace() << "Sector(" << sector.color << ", " << sector.angle
+ << ", " << sector.range << ")";
+ return dbg.space();
+}
+
+inline QDebug operator<<(QDebug dbg, const IMG::Lights &lights)
+{
+ dbg.nospace() << "Lights(" << lights.color << ", " << lights.range << ", "
+ << lights.sectors << ")";
+ return dbg.space();
+}
+#endif // QT_NO_DEBUG
+
+#endif // IMG_LIGHTS_H
diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h
index a1cd688f..4f591e98 100644
--- a/src/map/IMG/mapdata.h
+++ b/src/map/IMG/mapdata.h
@@ -14,6 +14,7 @@
#include "map/matrix.h"
#include "label.h"
#include "raster.h"
+#include "lights.h"
#include "zoom.h"
namespace IMG {
@@ -51,11 +52,11 @@ public:
enum Flags {
NoFlag = 0,
ClassLabel = 1,
- Light = 2
};
Coordinates coordinates;
Label label;
+ Lights lights;
quint64 id;
quint32 type;
quint32 flags;
diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp
index be67893b..515065fd 100644
--- a/src/map/IMG/rastertile.cpp
+++ b/src/map/IMG/rastertile.cpp
@@ -18,13 +18,13 @@ using namespace IMG;
#define TEXT_EXTENT 160
#define ICON_PADDING 2
+#define RANGE_FACTOR 4
+#define ROAD 0
+#define WATER 1
#define AREA(rect) \
(rect.size().width() * rect.size().height())
-#define ROAD 0
-#define WATER 1
-
static const QColor textColor(Qt::black);
static const QColor haloColor(Qt::white);
static const QColor shieldColor(Qt::white);
@@ -226,6 +226,67 @@ void RasterTile::drawTextItems(QPainter *painter,
}
}
+static QRect lightRect(const QPoint &pos, quint32 range)
+{
+ return QRect(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR,
+ 2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR);
+}
+
+void RasterTile::drawSectorLights(QPainter *painter,
+ const QList &lights) const
+{
+ for (int i = 0; i < lights.size(); i++) {
+ const MapData::Point *p = lights.at(i);
+ QPoint pos(p->coordinates.lon(), p->coordinates.lat());
+
+ if (p->lights.sectors.size()) {
+ for (int j = 0; j < p->lights.sectors.size(); j++) {
+ const Lights::Sector &start = p->lights.sectors.at(j);
+ const Lights::Sector &end = (j == p->lights.sectors.size() - 1)
+ ? p->lights.sectors.at(0) : p->lights.sectors.at(j+1);
+
+ if (start.color) {
+ double a1 = -(end.angle / 10.0 + 90.0);
+ double a2 = -(start.angle / 10.0 + 90.0);
+ if (a1 > a2)
+ a2 += 360;
+ double as = (a2 - a1);
+ if (as == 0)
+ as = 360;
+
+ QRect rect(lightRect(pos, start.range ? start.range : 6));
+
+ painter->setPen(QPen(Qt::black, 6, Qt::SolidLine,
+ Qt::FlatCap));
+ painter->drawArc(rect, a1 * 16, as * 16);
+ painter->setPen(QPen(Style::color(start.color), 4,
+ Qt::SolidLine, Qt::FlatCap));
+ painter->drawArc(rect, a1 * 16, as * 16);
+
+ if (a2 - a1 != 0) {
+ QLineF ln(pos, QPointF(pos.x() + rect.width(), pos.y()));
+ ln.setAngle(a1);
+ painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
+ painter->drawLine(ln);
+ ln.setAngle(a2);
+ painter->drawLine(ln);
+ }
+ }
+ }
+ } else {
+ if (p->lights.color && p->lights.range) {
+ QRect rect(lightRect(pos, p->lights.range));
+
+ painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
+ painter->drawArc(rect, 0, 360 * 16);
+ painter->setPen(QPen(Style::color(p->lights.color), 4,
+ Qt::SolidLine, Qt::FlatCap));
+ painter->drawArc(rect, 0, 360 * 16);
+ }
+ }
+ }
+}
+
static void removeDuplicitLabel(QList &labels, const QString &text,
const QRectF &tileRect)
{
@@ -398,7 +459,7 @@ void RasterTile::processShields(const QList &lines,
}
void RasterTile::processPoints(QList &points,
- QList &textItems)
+ QList &textItems, QList &lights)
{
std::sort(points.begin(), points.end());
@@ -408,6 +469,9 @@ void RasterTile::processPoints(QList &points,
const Style::Point &ps = style->point(point.type);
bool poi = Style::isPOI(point.type);
+ if (point.lights.isSectorLight())
+ lights.append(&point);
+
const QString *label = point.label.text().isEmpty()
? 0 : &(point.label.text());
const QImage *img = ps.img().isNull() ? 0 : &ps.img();
@@ -428,11 +492,12 @@ void RasterTile::processPoints(QList &points,
TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img,
color, hcolor, 0, ICON_PADDING);
- if (item->isValid() && !item->collides(textItems)) {
+ if (item->isValid() && (point.lights.isSectorLight()
+ || !item->collides(textItems))) {
textItems.append(item);
- if (Style::isLight(point.type) || point.flags & MapData::Point::Light)
+ if (point.lights.color && !point.lights.isSectorLight())
textItems.append(new TextPointItem(pos + style->lightOffset(),
- 0, 0, style->light(), 0, 0, 0, 0));
+ 0, 0, style->light(point.lights.color), 0, 0, 0, 0));
} else
delete item;
}
@@ -521,6 +586,7 @@ void RasterTile::render()
QList lines;
QList points;
QList textItems;
+ QList lights;
QImage arrows[2];
arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio);
@@ -531,7 +597,7 @@ void RasterTile::render()
ll2xy(lines);
ll2xy(points);
- processPoints(points, textItems);
+ processPoints(points, textItems, lights);
processPolygons(polygons, textItems);
processLines(lines, textItems, arrows);
@@ -546,6 +612,7 @@ void RasterTile::render()
drawPolygons(&painter, polygons);
drawHillShading(&painter);
drawLines(&painter, lines);
+ drawSectorLights(&painter, lights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
diff --git a/src/map/IMG/rastertile.h b/src/map/IMG/rastertile.h
index c394a841..84c29052 100644
--- a/src/map/IMG/rastertile.h
+++ b/src/map/IMG/rastertile.h
@@ -34,7 +34,8 @@ public:
private:
typedef RTree DEMTRee;
- struct ElevationCTX {
+ struct ElevationCTX
+ {
ElevationCTX(const DEMTRee &tree, const Coordinates &c, double &ele)
: tree(tree), c(c), ele(ele) {}
@@ -42,7 +43,8 @@ private:
const Coordinates &c;
double &ele;
};
- struct EdgeCTX {
+ struct EdgeCTX
+ {
EdgeCTX(const Coordinates &c, double &ele) : c(c), ele(ele) {}
const Coordinates &c;
@@ -62,13 +64,14 @@ private:
void drawLines(QPainter *painter, const QList &lines) const;
void drawTextItems(QPainter *painter, const QList &textItems) const;
void drawHillShading(QPainter *painter) const;
+ void drawSectorLights(QPainter *painter, const QList &lights) const;
void processPolygons(const QList &polygons,
QList &textItems);
void processLines(QList &lines, QList &textItems,
const QImage (&arrows)[2]);
- void processPoints(QList &points,
- QList &textItems);
+ void processPoints(QList &points, QList &textItems,
+ QList &lights);
void processShields(const QList &lines,
QList &textItems);
void processStreetNames(const QList &lines,
diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp
index ef629710..06760059 100644
--- a/src/map/IMG/rgnfile.cpp
+++ b/src/map/IMG/rgnfile.cpp
@@ -107,7 +107,8 @@ bool RGNFile::readObstructionInfo(Handle &hdl, quint8 flags, quint32 size,
return true;
}
-bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const
+bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, quint32 size,
+ MapData::Point *point) const
{
quint16 val;
quint8 lc;
@@ -115,7 +116,7 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con
if ((flags & 0xe0) != 0xe0)
return true;
- if (!readUInt16(hdl, val))
+ if (!(size >= 2 && readUInt16(hdl, val)))
return false;
lc = (val >> 10) & 0x0f;
@@ -123,7 +124,105 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con
lc = (val >> 6) & 7;
if (lc)
- point->flags |= MapData::Point::Light;
+ point->lights.color = (Lights::Color)lc;
+
+ return true;
+}
+
+bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size,
+ MapData::Point *point) const
+{
+ quint16 flags1;
+ quint8 flags2;
+ quint32 unused;
+
+ if (!(size >= 3 && readUInt16(hdl, flags1) && readUInt8(hdl, flags2)))
+ return false;
+ size -= 3;
+ if (flags2 >> 6) {
+ if (!(size >= (flags2 >> 6) && readVUInt32(hdl, (flags2 >> 6), unused)))
+ return false;
+ size -= (flags2 >> 6);
+ }
+ if (flags2 >> 2 & 3) {
+ if (!(size >= (flags2 >> 2 & 3)
+ && readVUInt32(hdl, (flags2 >> 2 & 3), unused)))
+ return false;
+ size -= (flags2 >> 2 & 3);
+ }
+ if (flags1 & 0xc0) {
+ if (flags1 & 0x80) {
+ if (!(size >= 1 && readUInt8(hdl, unused)))
+ return false;
+ unused |= ((flags1 & 0x40) << 2);
+ size--;
+ } else {
+ if (!(size >= 2 && readUInt16(hdl, unused)))
+ return false;
+ size -= 2;
+ }
+ }
+ if (flags & 2) {
+ if (!(size >= 3 && readUInt24(hdl, unused)))
+ return false;
+ size -= 3;
+ }
+ if (flags & 4) {
+ if (!(size >= 3 && readUInt24(hdl, unused)))
+ return false;
+ size -= 3;
+ }
+ if (flags & 8) {
+ if (!(size >= 3 && readUInt24(hdl, unused)))
+ return false;
+ size -= 3;
+ }
+ if (flags1 & 0x200) {
+ if (!(size >= 2 && readUInt16(hdl, unused)))
+ return false;
+ size -= 2;
+ }
+ if (flags1 & 0x400) {
+ if (!(size >= 1 && readUInt8(hdl, unused)))
+ return false;
+ size--;
+ }
+ if (flags1 & 0x800) {
+ quint16 la;
+ quint8 cf, range = 0;
+
+ do {
+ if (!(size >= 2 && readUInt16(hdl, la)))
+ return false;
+ size -= 2;
+
+ cf = la >> 8;
+ Lights::Color c = (Lights::Color)(cf >> 4 & 7);
+ if (c) {
+ if (!(size >= 1 && readUInt8(hdl, range)))
+ return false;
+ size--;
+ }
+ point->lights.sectors.append(Lights::Sector(c, la & 0xfff, range));
+ } while (!(cf >> 7));
+ } else {
+ quint8 v1, v2, range;
+
+ if (!(size >= 1 && readUInt8(hdl, v1)))
+ return false;
+ size--;
+
+ range = v1 & 0x1f;
+ if ((v1 & 0x1f) == 0x1f) {
+ if (!(size >= 1 && readUInt8(hdl, v2)))
+ return false;
+ size--;
+ range += v2;
+ }
+
+ point->lights.color = (Lights::Color)(v1 >> 5);
+ point->lights.range = range;
+ }
return true;
}
@@ -183,7 +282,9 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
if (point && Style::isObstructionPoint(point->type))
readObstructionInfo(hdl, flags, rs, point);
if (point && Style::isBuoy(point->type))
- readBuoyInfo(hdl, flags, point);
+ readBuoyInfo(hdl, flags, rs, point);
+ if (point && Style::isLight(point->type))
+ readLightInfo(hdl, flags, rs, point);
return seek(hdl, off + rs);
}
diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h
index 7040250c..fc739010 100644
--- a/src/map/IMG/rgnfile.h
+++ b/src/map/IMG/rgnfile.h
@@ -64,7 +64,10 @@ private:
MapData::Point *point) const;
bool readObstructionInfo(Handle &hdl, quint8 flags, quint32 size,
MapData::Point *point) const;
- bool readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const;
+ bool readBuoyInfo(Handle &hdl, quint8 flags, quint32 size,
+ MapData::Point *point) const;
+ bool readLightInfo(Handle &hdl, quint8 flags, quint32 size,
+ MapData::Point *point) const;
bool readLabel(Handle &hdl, LBLFile *lbl, Handle &lblHdl,
quint8 flags, quint32 size, MapData::Point *point) const;
diff --git a/src/map/IMG/style.cpp b/src/map/IMG/style.cpp
index 7014d2e6..1c215dce 100644
--- a/src/map/IMG/style.cpp
+++ b/src/map/IMG/style.cpp
@@ -1319,6 +1319,10 @@ Style::Style(qreal ratio, SubFile *typ)
_extraSmall = pixelSizeFont(10);
_light = QImage(":/marine/light.png");
+ _lightRed = QImage(":/marine/light-red.png");
+ _lightGreen = QImage(":/marine/light-green.png");
+ _lightYellow = QImage(":/marine/light-yellow.png");
+ _lightWhite = QImage(":/marine/light-white.png");
_lightOffset = QPoint(11, 11);
defaultLineStyle(ratio);
@@ -1373,6 +1377,40 @@ const QFont *Style::font(Style::FontSize size, Style::FontSize defaultSize) cons
}
}
+const QImage *Style::light(Lights::Color color) const
+{
+ switch (color) {
+ case Lights::Red:
+ return &_lightRed;
+ case Lights::Green:
+ return &_lightGreen;
+ case Lights::White:
+ return &_lightWhite;
+ case Lights::Yellow:
+ case Lights::Amber:
+ return &_lightYellow;
+ default:
+ return &_light;
+ }
+}
+
+QColor Style::color(Lights::Color c)
+{
+ switch (c) {
+ case Lights::Red:
+ return Qt::red;
+ case Lights::Green:
+ return Qt::green;
+ case Lights::White:
+ return Qt::white;
+ case Lights::Yellow:
+ case Lights::Amber:
+ return Qt::yellow;
+ default:
+ return Qt::magenta;
+ }
+}
+
#ifndef QT_NO_DEBUG
static QString penColor(const QPen &pen)
{
diff --git a/src/map/IMG/style.h b/src/map/IMG/style.h
index 88fae052..a3f21fad 100644
--- a/src/map/IMG/style.h
+++ b/src/map/IMG/style.h
@@ -5,6 +5,7 @@
#include
#include
#include
+#include "lights.h"
#include "subfile.h"
#define TYPE(t) ((t)<<8)
@@ -112,8 +113,7 @@ public:
const QList &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size, Style::FontSize defaultSize
= Style::Normal) const;
-
- const QImage *light() const {return &_light;}
+ const QImage *light(Lights::Color color) const;
const QPoint &lightOffset() const {return _lightOffset;}
static bool isPOI(quint32 type)
@@ -157,6 +157,8 @@ public:
static bool isMarina(quint32 type)
{return type == 0x10703;}
+ static QColor color(Lights::Color c);
+
private:
struct Section {
quint32 offset;
@@ -203,7 +205,7 @@ private:
/* Fonts and images must be initialized after QGuiApplication! */
QFont _large, _normal, _small, _extraSmall;
- QImage _light;
+ QImage _light, _lightRed, _lightGreen, _lightYellow, _lightWhite;
QPoint _lightOffset;
};