1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-22 18:20:49 +01:00

Improved marine lights presentation

This commit is contained in:
Martin Tůma 2025-02-19 19:26:14 +01:00
parent 9f1808274f
commit 0896b54831
2 changed files with 98 additions and 30 deletions

View File

@ -19,13 +19,37 @@ using namespace IMG;
#define TEXT_EXTENT 160 #define TEXT_EXTENT 160
#define ICON_PADDING 2 #define ICON_PADDING 2
#define RANGE_FACTOR 4 #define RANGE_FACTOR 4
#define RANGE_MIN 6
#define ROAD 0 #define ROAD 0
#define WATER 1 #define WATER 1
#define AREA(rect) \ #define AREA(rect) \
(rect.size().width() * rect.size().height()) (rect.size().width() * rect.size().height())
struct Sector
{
Sector(Light::Color color, quint32 start, quint32 end)
: color(color), start(start), end(end) {}
bool operator==(const Sector &other) const
{
return (color == other.color && start == other.start && end == other.end);
}
bool operator<(const Sector &other) const
{
if (color == other.color) {
if (start == other.start)
return end < other.end;
else
return start < other.start;
} else
return color < other.color;
}
Light::Color color;
quint32 start;
quint32 end;
};
static const QColor textColor(Qt::black); static const QColor textColor(Qt::black);
static const QColor haloColor(Qt::white); static const QColor haloColor(Qt::white);
static const QColor shieldColor(Qt::white); static const QColor shieldColor(Qt::white);
@ -239,6 +263,7 @@ void RasterTile::drawSectorLights(QPainter *painter,
for (int i = 0; i < lights.size(); i++) { for (int i = 0; i < lights.size(); i++) {
const MapData::Point *p = lights.at(i); const MapData::Point *p = lights.at(i);
QPoint pos(p->coordinates.lon(), p->coordinates.lat()); QPoint pos(p->coordinates.lon(), p->coordinates.lat());
QMap<Sector, quint32> rangeMap;
for (int j = 0; j < p->lights.size(); j++) { for (int j = 0; j < p->lights.size(); j++) {
const Light &l = p->lights.at(j); const Light &l = p->lights.at(j);
@ -248,8 +273,16 @@ void RasterTile::drawSectorLights(QPainter *painter,
const Light::Sector &start = l.sectors().at(k); const Light::Sector &start = l.sectors().at(k);
const Light::Sector &end = (k == l.sectors().size() - 1) const Light::Sector &end = (k == l.sectors().size() - 1)
? l.sectors().at(0) : l.sectors().at(k+1); ? l.sectors().at(0) : l.sectors().at(k+1);
quint32 angle = end.angle() - start.angle();
if (start.color() && (angle || start.range())) {
quint32 range = start.range() ? start.range() : 6;
Sector s(start.color(), start.angle(), end.angle());
if (rangeMap.value(s) >= range)
continue;
else
rangeMap.insert(s, range);
if (start.color()) {
double a1 = -(end.angle() / 10.0 + 90.0); double a1 = -(end.angle() / 10.0 + 90.0);
double a2 = -(start.angle() / 10.0 + 90.0); double a2 = -(start.angle() / 10.0 + 90.0);
if (a1 > a2) if (a1 > a2)
@ -258,9 +291,7 @@ void RasterTile::drawSectorLights(QPainter *painter,
if (as == 0) if (as == 0)
as = 360; as = 360;
QRect rect(lightRect(pos, start.range() QRect rect(lightRect(pos, range));
? start.range() : RANGE_MIN));
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, painter->setPen(QPen(Qt::black, 6, Qt::SolidLine,
Qt::FlatCap)); Qt::FlatCap));
painter->drawArc(rect, a1 * 16, as * 16); painter->drawArc(rect, a1 * 16, as * 16);
@ -268,7 +299,7 @@ void RasterTile::drawSectorLights(QPainter *painter,
Qt::SolidLine, Qt::FlatCap)); Qt::SolidLine, Qt::FlatCap));
painter->drawArc(rect, a1 * 16, as * 16); painter->drawArc(rect, a1 * 16, as * 16);
if (a2 - a1 != 0) { if (angle) {
QLineF ln(pos, QPointF(pos.x() + rect.width(), QLineF ln(pos, QPointF(pos.x() + rect.width(),
pos.y())); pos.y()));
ln.setAngle(a1); ln.setAngle(a1);
@ -279,9 +310,14 @@ void RasterTile::drawSectorLights(QPainter *painter,
} }
} }
} }
} else if (l.range() > RANGE_MIN) { } else if (l.color() && l.range()) {
QRect rect(lightRect(pos, l.range())); Sector s(l.color(), 0, 3600);
if (rangeMap.value(s) >= l.range())
continue;
else
rangeMap.insert(s, l.range());
QRect rect(lightRect(pos, l.range()));
painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap)); painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap));
painter->drawArc(rect, 0, 360 * 16); painter->drawArc(rect, 0, 360 * 16);
painter->setPen(QPen(Style::color(l.color()), 4, Qt::SolidLine, painter->setPen(QPen(Style::color(l.color()), 4, Qt::SolidLine,
@ -463,19 +499,47 @@ void RasterTile::processShields(const QList<MapData::Poly> &lines,
} }
} }
static bool showAsSector(const QVector<Light> &lights) static bool sectorLight(const QVector<Light> &lights)
{ {
for (int i = 0; i < lights.size(); i++) { for (int i = 0; i < lights.size(); i++) {
const Light &l = lights.at(i); const Light &l = lights.at(i);
if ((l.color() && l.range() > RANGE_MIN) || !l.sectors().isEmpty()) if (l.color() && l.range())
return true; return true;
for (int j = 0; j < l.sectors().size(); j++) {
const Light::Sector &start = l.sectors().at(j);
const Light::Sector &end = (j == l.sectors().size() - 1)
? l.sectors().at(0) : l.sectors().at(j+1);
quint32 angle = end.angle() - start.angle();
if (start.color() && (angle || start.range()))
return true;
}
} }
return false; return false;
} }
static Light::Color ordinaryLight(const QVector<Light> &lights)
{
for (int i = 0; i < lights.size(); i++) {
const Light &l = lights.at(i);
if (l.color() && !l.range())
return l.color();
for (int j = 0; j < l.sectors().size(); j++) {
const Light::Sector &start = l.sectors().at(j);
const Light::Sector &end = (j == l.sectors().size() - 1)
? l.sectors().at(0) : l.sectors().at(j+1);
quint32 angle = end.angle() - start.angle();
if (start.color() && !angle && !start.range())
return start.color();
}
}
return Light::None;
}
void RasterTile::processPoints(QList<MapData::Point> &points, void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<const MapData::Point*> &lights) QList<TextItem*> &textItems, QList<TextItem *> &lights,
QList<const MapData::Point*> &sectorLights)
{ {
std::sort(points.begin(), points.end()); std::sort(points.begin(), points.end());
@ -484,10 +548,10 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
const Style *style = _data->style(); const Style *style = _data->style();
const Style::Point &ps = style->point(point.type); const Style::Point &ps = style->point(point.type);
bool poi = Style::isPOI(point.type); bool poi = Style::isPOI(point.type);
bool sl = showAsSector(point.lights); bool sl = sectorLight(point.lights);
if (sl) if (sl)
lights.append(&point); sectorLights.append(&point);
const QString *label = point.label.text().isEmpty() const QString *label = point.label.text().isEmpty()
? 0 : &(point.label.text()); ? 0 : &(point.label.text());
@ -511,17 +575,15 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
color, hcolor, 0, ICON_PADDING); color, hcolor, 0, ICON_PADDING);
if (item->isValid() && (sl || !item->collides(textItems))) { if (item->isValid() && (sl || !item->collides(textItems))) {
textItems.append(item); textItems.append(item);
for (int j = 0; j < point.lights.size(); j++) { Light::Color color = ordinaryLight(point.lights);
const Light &l = point.lights.at(j); if (color)
if (l.color() && l.range() <= RANGE_MIN) { lights.append(new TextPointItem(pos + style->lightOffset(),
textItems.append(new TextPointItem(pos + style->lightOffset(), 0, 0, style->light(color), 0, 0, 0, 0));
0, 0, style->light(l.color()), 0, 0, 0, 0));
break;
}
}
} else } else
delete item; delete item;
} }
} }
void RasterTile::fetchData(QList<MapData::Poly> &polygons, void RasterTile::fetchData(QList<MapData::Poly> &polygons,
@ -606,8 +668,8 @@ void RasterTile::render()
QList<MapData::Poly> polygons; QList<MapData::Poly> polygons;
QList<MapData::Poly> lines; QList<MapData::Poly> lines;
QList<MapData::Point> points; QList<MapData::Point> points;
QList<TextItem*> textItems; QList<TextItem*> textItems, lights;
QList<const MapData::Point*> lights; QList<const MapData::Point*> sectorLights;
QImage arrows[2]; QImage arrows[2];
arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio); arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio);
@ -618,7 +680,7 @@ void RasterTile::render()
ll2xy(lines); ll2xy(lines);
ll2xy(points); ll2xy(points);
processPoints(points, textItems, lights); processPoints(points, textItems, lights, sectorLights);
processPolygons(polygons, textItems); processPolygons(polygons, textItems);
processLines(lines, textItems, arrows); processLines(lines, textItems, arrows);
@ -633,9 +695,11 @@ void RasterTile::render()
drawPolygons(&painter, polygons); drawPolygons(&painter, polygons);
drawHillShading(&painter); drawHillShading(&painter);
drawLines(&painter, lines); drawLines(&painter, lines);
drawSectorLights(&painter, lights); drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems); drawTextItems(&painter, textItems);
qDeleteAll(lights);
qDeleteAll(textItems); qDeleteAll(textItems);
//painter.setPen(Qt::red); //painter.setPen(Qt::red);

View File

@ -60,18 +60,22 @@ private:
void ll2xy(QList<MapData::Poly> &polys) const; void ll2xy(QList<MapData::Poly> &polys) const;
void ll2xy(QList<MapData::Point> &points) const; void ll2xy(QList<MapData::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const; void drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<MapData::Poly> &lines) const; void drawLines(QPainter *painter, const QList<MapData::Poly> &lines) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const; void drawTextItems(QPainter *painter,
const QList<TextItem*> &textItems) const;
void drawHillShading(QPainter *painter) const; void drawHillShading(QPainter *painter) const;
void drawSectorLights(QPainter *painter, const QList<const MapData::Point*> &lights) const; void drawSectorLights(QPainter *painter,
const QList<const MapData::Point*> &lights) const;
void processPolygons(const QList<MapData::Poly> &polygons, void processPolygons(const QList<MapData::Poly> &polygons,
QList<TextItem *> &textItems); QList<TextItem *> &textItems);
void processLines(QList<MapData::Poly> &lines, QList<TextItem*> &textItems, void processLines(QList<MapData::Poly> &lines, QList<TextItem*> &textItems,
const QImage (&arrows)[2]); const QImage (&arrows)[2]);
void processPoints(QList<MapData::Point> &points, QList<TextItem*> &textItems, void processPoints(QList<MapData::Point> &points,
QList<const MapData::Point *> &lights); QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<const MapData::Point*> &sectorLights);
void processShields(const QList<MapData::Poly> &lines, void processShields(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
void processStreetNames(const QList<MapData::Poly> &lines, void processStreetNames(const QList<MapData::Poly> &lines,