1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 06:43:22 +02:00

Various ENC render style enhancements

This commit is contained in:
Martin Tůma 2022-12-08 00:29:39 +01:00
parent ff2dd6cdec
commit d33716e3af
10 changed files with 147 additions and 81 deletions

View File

@ -191,6 +191,7 @@
<file alias="cable-area-line.png">icons/map/marine/cable-area-line.png</file>
<file alias="pipeline-area-line.png">icons/map/marine/pipeline-area-line.png</file>
<file alias="windmotor.png">icons/map/marine/windmotor.png</file>
<file alias="gauge.png">icons/map/marine/gauge.png</file>
</qresource>
<!-- Mapsforge rendertheme -->

BIN
icons/map/marine/gauge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

View File

@ -11,6 +11,7 @@
#define CATREA 56
#define CATSCF 65
#define CATWRK 71
#define COMCHA 77
#define DRVAL1 87
#define ELEVAT 90
#define FUNCTN 94
@ -22,6 +23,8 @@
#define I_CATACH 17000
#define I_RESTRN 17004
#define I_CATHAF 17008
#define I_RDOCAL 17017
#define I_WTWDIS 17064
#define I_HUNITS 17103

View File

@ -49,18 +49,20 @@ static QMap<uint,uint> orderMapInit()
map.insert(TYPE(OBSTRN), 24);
map.insert(TYPE(WRECKS), 25);
map.insert(TYPE(UWTROC), 26);
map.insert(TYPE(I_TRNBSN), 27);
map.insert(TYPE(HRBFAC), 28);
map.insert(TYPE(PILPNT), 29);
map.insert(TYPE(ACHBRT), 30);
map.insert(TYPE(I_ACHBRT), 30);
map.insert(TYPE(CRANES), 31);
map.insert(TYPE(I_CRANES), 31);
map.insert(TYPE(LNDMRK), 32);
map.insert(TYPE(SILTNK), 33);
map.insert(TYPE(LNDELV), 34);
map.insert(TYPE(SMCFAC), 35);
map.insert(TYPE(BUISGL), 36);
map.insert(TYPE(I_RDOCAL), 27);
map.insert(TYPE(I_TRNBSN), 28);
map.insert(TYPE(HRBFAC), 29);
map.insert(TYPE(PILPNT), 30);
map.insert(TYPE(ACHBRT), 31);
map.insert(TYPE(I_ACHBRT), 31);
map.insert(TYPE(CRANES), 32);
map.insert(TYPE(I_CRANES), 32);
map.insert(TYPE(LNDMRK), 33);
map.insert(TYPE(SILTNK), 34);
map.insert(TYPE(LNDELV), 35);
map.insert(TYPE(SMCFAC), 36);
map.insert(TYPE(BUISGL), 37);
map.insert(TYPE(I_WTWGAG), 38);
map.insert(TYPE(I_DISMAR), 0xFFFFFFFE);
map.insert(TYPE(SOUNDG), 0xFFFFFFFF);
@ -214,34 +216,36 @@ static QString hUnits(uint type)
}
MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
const QByteArray &param) : _type(type), _pos(c), _label(label)
const QVector<QByteArray> &params) : _type(type), _pos(c), _label(label)
{
uint hash = (uint)qHash(QPair<double,double>(c.lon(), c.lat()));
_id = ((quint64)order(type))<<32 | hash;
if ((type & 0xFFFF0000) == TYPE(I_DISMAR)) {
_label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(param);
if (type>>16 == I_DISMAR) {
_label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0));
_type = SUBTYPE(I_DISMAR, type & 0xFF);
} else if (type == TYPE(I_RDOCAL)) {
if (!params.at(1).isEmpty())
_label = QString("VHF ") + QString::fromLatin1(params.at(1));
_param = QVariant(params.at(0).toDouble());
}
}
MapData::Poly::Poly(uint type, const Polygon &path, const QByteArray &param)
: _type(type), _path(path)
MapData::Poly::Poly(uint type, const Polygon &path,
const QVector<QByteArray> &params) : _type(type), _path(path)
{
if (type == TYPE(DEPARE))
_type = SUBTYPE(DEPARE, depthLevel(param));
else if (type == TYPE(TSSLPT)) {
double angle = param.toDouble();
_type = SUBTYPE(TSSLPT, (uint)(angle * 10));
}
_type = SUBTYPE(DEPARE, depthLevel(params.at(0)));
else if (type == TYPE(TSSLPT))
_param = QVariant(params.at(0).toDouble());
}
MapData::Line::Line(uint type, const QVector<Coordinates> &path,
const QString &label, const QByteArray &param) : _type(type), _path(path),
_label(label)
const QString &label, const QVector<QByteArray> &params)
: _type(type), _path(path), _label(label)
{
if (type == TYPE(DEPCNT) || type == TYPE(LNDELV))
_label = QString::fromLatin1(param);
_label = QString::fromLatin1(params.at(0));
}
RectC MapData::Line::bounds() const
@ -477,7 +481,7 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc,
MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QByteArray param;
QVector<QByteArray> params(2);
uint subtype = 0;
const ISO8211::Field *ATTF = r.field("ATTF");
@ -492,6 +496,7 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
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)
@ -505,17 +510,20 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
else if (OBJL == I_DISMAR && key == I_HUNITS)
subtype |= av.at(1).toByteArray().toUInt() << 8;
if (OBJL == I_DISMAR && key == I_WTWDIS)
param = av.at(1).toByteArray();
if ((OBJL == I_DISMAR && key == I_WTWDIS)
|| (OBJL == I_RDOCAL && key == ORIENT))
params[0] = av.at(1).toByteArray();
if (OBJL == I_RDOCAL && key == COMCHA)
params[1] = av.at(1).toByteArray();
}
return Attr(subtype, label, param);
return Attr(subtype, label, params);
}
MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QByteArray param;
QVector<QByteArray> params(1);
uint subtype = 0;
const ISO8211::Field *ATTF = r.field("ATTF");
@ -534,16 +542,16 @@ MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL)
if ((OBJL == DEPCNT && key == VALDCO)
|| (OBJL == LNDELV && key == ELEVAT))
param = av.at(1).toByteArray();
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, param);
return Attr(subtype, label, params);
}
MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL)
{
QString label;
QByteArray param;
QVector<QByteArray> params(1);
uint subtype = 0;
const ISO8211::Field *ATTF = r.field("ATTF");
@ -570,15 +578,16 @@ MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL)
if ((OBJL == TSSLPT && key == ORIENT)
|| (OBJL == DEPARE && key == DRVAL1))
param = av.at(1).toByteArray();
params[0] = av.at(1).toByteArray();
}
return Attr(subtype, label, param);
return Attr(subtype, label, params);
}
MapData::Point *MapData::pointObject(const Sounding &s)
{
return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth), QByteArray());
return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth),
QVector<QByteArray>());
}
MapData::Point *MapData::pointObject(const ISO8211::Record &r,
@ -588,7 +597,7 @@ MapData::Point *MapData::pointObject(const ISO8211::Record &r,
Attr attr(pointAttr(r, OBJL));
return (c.isNull() ? 0 : new Point(SUBTYPE(OBJL,attr.subtype()), c,
attr.label(), attr.param()));
attr.label(), attr.params()));
}
MapData::Line *MapData::lineObject(const ISO8211::Record &r,
@ -598,7 +607,7 @@ MapData::Line *MapData::lineObject(const ISO8211::Record &r,
Attr attr(lineAttr(r, OBJL));
return (path.isEmpty() ? 0 : new Line(SUBTYPE(OBJL, attr.subtype()), path,
attr.label(), attr.param()));
attr.label(), attr.params()));
}
MapData::Poly *MapData::polyObject(const ISO8211::Record &r,
@ -608,7 +617,7 @@ MapData::Poly *MapData::polyObject(const ISO8211::Record &r,
Attr attr(polyAttr(r, OBJL));
return (path.isEmpty() ? 0 : new Poly(SUBTYPE(OBJL, attr.subtype()), path,
attr.param()));
attr.params()));
}
bool MapData::processRecord(const ISO8211::Record &record,

View File

@ -15,21 +15,23 @@ class MapData
public:
class Poly {
public:
Poly(uint type, const Polygon &path, const QByteArray &param);
Poly(uint type, const Polygon &path, const QVector<QByteArray> &params);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
const QVariant &param() const {return _param;}
private:
uint _type;
Polygon _path;
QVariant _param;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const QString &label,
const QByteArray &param);
const QVector<QByteArray> &params);
RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;}
@ -45,11 +47,12 @@ public:
class Point {
public:
Point(uint type, const Coordinates &c, const QString &label,
const QByteArray &param);
const QVector<QByteArray> &params);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const QVariant &param() const {return _param;}
bool operator<(const Point &other) const
{return _id < other._id;}
@ -59,6 +62,7 @@ public:
Coordinates _pos;
QString _label;
quint64 _id;
QVariant _param;
};
MapData(const QString &path);
@ -116,17 +120,18 @@ private:
class Attr {
public:
Attr() : _subtype(0) {}
Attr(uint subtype, const QString &label, const QByteArray &param)
: _subtype(subtype), _label(label), _param(param) {}
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 QByteArray &param() const {return _param;}
const QVector<QByteArray> &params() const {return _params;}
private:
unsigned _subtype;
QString _label;
QByteArray _param;
QVector<QByteArray> _params;
};
struct Sounding {

View File

@ -91,7 +91,9 @@
#define I_BRIDGE 17011
#define I_CBLOHD 17012
#define I_FERYRT 17013
#define I_HRBFAC 17015
#define I_LOKBSN 17016
#define I_RDOCAL 17017
#define I_HULKES 17020
#define I_PONTON 17021
#define I_PIPOHD 17024
@ -104,5 +106,6 @@
#define I_WTWAXS 17051
#define I_TERMNL 17064
#define I_TRNBSN 17065
#define I_WTWGAG 17067
#endif // ENC_OBJECTS_H

View File

@ -10,7 +10,8 @@
using namespace ENC;
#define ICON_PADDING 2
#define ARROW_SIZE 0.005
#define TSSLPT_SIZE 0.005 /* ll */
#define RDOCAL_SIZE 12 /* px */
const float C1 = 0.866025f; /* sqrt(3)/2 */
@ -84,6 +85,39 @@ static Coordinates centroid(const QVector<Coordinates> &polygon)
return Coordinates(cx * factor, cy * factor);
}
static QImage *rdocalArrow(qreal angle)
{
QImage *img = new QImage(RDOCAL_SIZE*2, RDOCAL_SIZE*2,
QImage::Format_ARGB32_Premultiplied);
img->fill(Qt::transparent);
QPainter p(img);
p.setPen(QPen(QColor("#eb49eb"), 1));
QPointF arrow[3];
arrow[0] = QPointF(img->width()/2, img->height()/2);
arrow[1] = arrow[0] + QPointF(qSin(angle - M_PI/3) * RDOCAL_SIZE,
qCos(angle - M_PI/3) * RDOCAL_SIZE);
arrow[2] = arrow[0] + QPointF(qSin(angle - M_PI + M_PI/3) * RDOCAL_SIZE,
qCos(angle - M_PI + M_PI/3) * RDOCAL_SIZE);
QLineF l(arrow[1], arrow[2]);
QPointF pt(l.pointAt(0.5));
p.translate(arrow[0] - pt);
p.drawPolyline(QPolygonF() << arrow[1] << arrow[0] << arrow[2]);
p.drawEllipse(pt, RDOCAL_SIZE/2, RDOCAL_SIZE/2);
return img;
}
static QImage *image(uint type, const QVariant &param)
{
if (type>>16 == I_RDOCAL)
return rdocalArrow(deg2rad(90 - param.toDouble()));
else
return 0;
}
QPainterPath RasterTile::painterPath(const Polygon &polygon) const
{
QPainterPath path;
@ -110,24 +144,24 @@ QPolygonF RasterTile::polyline(const QVector<Coordinates> &path) const
return polygon;
}
QPolygonF RasterTile::arrow(const Coordinates &c, qreal angle) const
QPolygonF RasterTile::tsslptArrow(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);
t[1] = Coordinates(t[0].lon() - qCos(angle - M_PI/3) * TSSLPT_SIZE,
t[0].lat() - qSin(angle - M_PI/3) * TSSLPT_SIZE);
t[2] = Coordinates(t[0].lon() - qCos(angle - M_PI + M_PI/3) * TSSLPT_SIZE,
t[0].lat() - qSin(angle - M_PI + M_PI/3) * TSSLPT_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));
r[2] = Coordinates(r[0].lon() - C1 * TSSLPT_SIZE * qCos(angle - M_PI/2),
r[0].lat() - C1 * TSSLPT_SIZE * qSin(angle - M_PI/2));
r[3] = Coordinates(r[1].lon() - C1 * TSSLPT_SIZE * qCos(angle - M_PI/2),
r[1].lat() - C1 * TSSLPT_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]);
@ -137,16 +171,15 @@ QPolygonF RasterTile::arrow(const Coordinates &c, qreal angle) const
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)));
QPolygonF polygon(tsslptArrow(centroid(poly->path().first()),
deg2rad(180 - poly->param().toDouble())));
painter->setPen(QPen(QColor("#eb49eb"), 1));
painter->setBrush(QBrush("#80eb49eb"));
painter->drawPolygon(polygon);
}
}
@ -227,7 +260,8 @@ void RasterTile::processPolygons(QList<TextItem*> &textItems)
}
}
void RasterTile::processPoints(QList<TextItem*> &textItems)
void RasterTile::processPoints(QList<TextItem*> &textItems,
QList<QImage*> &images)
{
const Style &s = style();
@ -238,21 +272,27 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
const Style::Point &style = s.point(point->type());
const QString *label = point->label().isEmpty() ? 0 : &(point->label());
const QImage *img = style.img().isNull() ? 0 : &style.img();
QImage *rimg = style.img().isNull()
? image(point->type(), point->param()) : 0;
const QImage *img = style.img().isNull() ? rimg : &style.img();
const QFont *fnt = font(style.textFontSize());
const QColor *color = &style.textColor();
const QColor *hColor = (Style::isSounding(point->type())
|| Style::isDistanceMark(point->type())) ? 0 : &haloColor;
const QColor *hColor = style.haloColor().isValid()
? &style.haloColor() : 0;
if ((!label || !fnt) && !img)
continue;
TextPointItem *item = new TextPointItem(ll2xy(point->pos()).toPoint(),
label, fnt, img, color, hColor, 0, ICON_PADDING);
if (item->isValid() && !item->collides(textItems))
if (item->isValid() && !item->collides(textItems)) {
textItems.append(item);
else
if (rimg)
images.append(rimg);
} else {
delete item;
delete rimg;
}
}
}
@ -284,12 +324,13 @@ void RasterTile::processLines(QList<TextItem*> &textItems)
void RasterTile::render()
{
QList<TextItem*> textItems;
QList<QImage*> images;
_pixmap.setDevicePixelRatio(_ratio);
_pixmap.fill(Qt::transparent);
processPolygons(textItems);
processPoints(textItems);
processPoints(textItems, images);
processLines(textItems);
QPainter painter(&_pixmap);
@ -304,6 +345,7 @@ void RasterTile::render()
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
qDeleteAll(images);
//painter.setPen(Qt::red);
//painter.setBrush(Qt::NoBrush);

View File

@ -32,8 +32,8 @@ 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);
QPolygonF tsslptArrow(const Coordinates &c, qreal angle) const;
void processPoints(QList<TextItem*> &textItems, QList<QImage*> &images);
void processLines(QList<TextItem*> &textItems);
void processPolygons(QList<TextItem*> &textItems);
void drawBitmapPath(QPainter *painter, const QImage &img,

View File

@ -174,6 +174,7 @@ void Style::pointStyle()
_points[SUBTYPE(BUAARE, 6)].setTextFontSize(Small);
_points[SUBTYPE(BUAARE, 0)].setTextFontSize(Small);
_points[TYPE(SOUNDG)].setTextFontSize(Small);
_points[TYPE(SOUNDG)].setHaloColor(QColor());
_points[TYPE(LIGHTS)] = Point(QImage(":/marine/light-major.png"), Small);
_points[TYPE(BOYCAR)] = Point(QImage(":/marine/buoy.png"), Small);
_points[TYPE(BOYINB)] = Point(QImage(":/marine/buoy.png"), Small);
@ -226,16 +227,19 @@ void Style::pointStyle()
_points[SUBTYPE(I_DISMAR, 1)] = Point(QImage(":/marine/distance-mark.png"));
_points[SUBTYPE(I_DISMAR, 1)].setTextColor(QColor("#ffffff"));
_points[SUBTYPE(I_DISMAR, 1)].setTextFontSize(Small);
_points[SUBTYPE(I_DISMAR, 1)].setHaloColor(QColor());
_points[SUBTYPE(I_DISMAR, 2)] = Point(QImage(":/marine/distance-mark-land.png"));
_points[SUBTYPE(I_DISMAR, 2)].setTextFontSize(Small);
_points[SUBTYPE(I_DISMAR, 3)] = Point(QImage(":/marine/distance-mark-land.png"));
_points[SUBTYPE(I_DISMAR, 3)].setTextFontSize(Small);
_points[SUBTYPE(I_DISMAR, 2)].setHaloColor(QColor());
_points[SUBTYPE(I_DISMAR, 3)] = _points[SUBTYPE(I_DISMAR, 2)];
_points[TYPE(CGUSTA)] = Point(QImage(":/marine/coast-guard.png"));
_points[TYPE(RDOSTA)] = Point(QImage(":/marine/radio.png"));
_points[TYPE(RADSTA)] = Point(QImage(":/marine/radar.png"));
_points[TYPE(RTPBCN)] = Point(QImage(":/marine/radar-transponder.png"));
_points[TYPE(SILTNK)] = Point(QImage(":/marine/silo.png"));
_points[TYPE(I_TRNBSN)] = Point(QImage(":/marine/turning-basin.png"));
_points[TYPE(I_WTWGAG)] = Point(QImage(":/marine/gauge.png"));
_points[TYPE(I_RDOCAL)].setTextColor(QColor("#eb49eb"));
_points[SUBTYPE(SMCFAC, 7)] = Point(QImage(":/POI/restaurant-11.png"));
_points[SUBTYPE(SMCFAC, 11)] = Point(QImage(":/POI/pharmacy-11.png"));

View File

@ -68,19 +68,23 @@ public:
class Point {
public:
Point() : _textColor(Qt::black), _textFontSize(Normal) {}
Point() : _textColor(Qt::black), _haloColor(Qt::white),
_textFontSize(Normal) {}
Point(const QImage &img, FontSize fontSize = Normal)
: _textColor(Qt::black), _textFontSize(fontSize), _img(img) {}
: _textColor(Qt::black), _haloColor(Qt::white),
_textFontSize(fontSize), _img(img) {}
void setTextColor(const QColor &color) {_textColor = color;}
void setHaloColor(const QColor &color) {_haloColor = color;}
void setTextFontSize(FontSize size) {_textFontSize = size;}
const QColor &textColor() const {return _textColor;}
const QColor &haloColor() const {return _haloColor;}
FontSize textFontSize() const {return _textFontSize;}
const QImage &img() const {return _img;}
private:
QColor _textColor;
QColor _textColor, _haloColor;
FontSize _textFontSize;
QImage _img;
};
@ -92,11 +96,6 @@ public:
const Point &point(uint type) const;
const QVector<uint> &drawOrder() const {return _drawOrder;}
static bool isSounding(uint type)
{return type == TYPE(SOUNDG);}
static bool isDistanceMark(uint type)
{return (type & 0xFFFF0000) == TYPE(I_DISMAR);}
private:
void polygonStyle();
void lineStyle();