Files
qt5-legatus-legacy/Lts/Services/AreaEffectSimulation/Utils/icons.cpp
T
2026-08-13 18:33:10 +02:00

209 lines
6.7 KiB
C++
Executable File

/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
*/
#include "icons.h"
#include "polygons.h"
#include <AreaEffectSimulation/aes.hpp>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QGuiApplication>
#include <QIcon>
#include <QPainter>
#include <QPixmap>
#include <QTransform>
namespace AreaEffectSimulation
{
namespace Icons
{
// Todo: Remove
const int NEBEL = 1;
struct PolygonData
{
QPolygonF poly;
QColor color;
Qt::BrushStyle fillPattern = Qt::NoBrush;
PolygonData() = default;
PolygonData(const QPolygonF &_poly,
const QColor &_color,
const Qt::BrushStyle &_fillPattern)
: poly(_poly)
, color(_color)
, fillPattern(_fillPattern)
{}
};
static QPixmap pixmapFromPolygons(const QVector<PolygonData> &datas,
int width,
const QColor &bgcolor = Qt::transparent)
{
if (datas.isEmpty() || datas.first().poly.isEmpty())
return {};
QPolygonF polyUtm;
QVector<QPolygonF> polysUtm;
polysUtm.reserve(datas.size() * 10);
int zone = LtsCoordTrans::UtmCoordinate::fromGeographic(datas.first().poly.first()).zone;
for (const PolygonData &data : datas)
{
polyUtm.clear();
for (const QPointF &point : qAsConst(data.poly))
{
LtsCoordTrans::UtmCoordinate pointUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(point, zone);
polyUtm << QPointF(pointUtm.x, pointUtm.y);
}
polysUtm << polyUtm;
}
QPolygonF bounding;
bounding.reserve(4 * datas.size());
// Does not matter, how the total polygon looks as we just need the bounding rect.
// << is cheaper than .united()
for (const QPolygonF &polyUtmLocal : qAsConst(polysUtm))
bounding << polyUtmLocal;
// center to center / Todo:: Does it always work?
const QTransform mTrans(QTransform::fromTranslate(-bounding.boundingRect().bottomLeft().x(), -bounding.boundingRect().bottomLeft().y()));
const auto dpr = qApp->devicePixelRatio();
width *= dpr;
qreal w = bounding.boundingRect().width();
qreal h = bounding.boundingRect().height();
double scale = w > h ? width / w : width / h;
w *= scale;
h *= scale;
scale *= 0.96; // Leave 4% border (i.e. 2% each side)
const QTransform mScale(QTransform::fromScale(scale, -scale));
const QTransform mTransSmall(QTransform::fromTranslate(0.02 * width + (width - w) / 2, 0.02 * width + (width - h) / 2));
QPixmap pix(width, width);
pix.setDevicePixelRatio(dpr);
pix.fill(bgcolor);
QPainter p(&pix);
int i = 0;
for (const PolygonData &d : qAsConst(datas))
{
QPolygonF mPoly = mTrans.map(polysUtm.at(i++));
mPoly = mScale.map(mPoly);
mPoly = mTransSmall.map(mPoly);
p.setBrush(QBrush(d.color, d.fillPattern));
p.setPen(QPen(p.brush(), 2));
p.drawPolygon(mPoly);
}
p.end();
return pix;
}
static QPixmap pixmapFromPolygon(const QPolygonF &poly,
const QColor &color,
const Qt::BrushStyle &fillPattern,
const int width,
const QColor &bgcolor = Qt::transparent)
{
return pixmapFromPolygons({PolygonData(poly, color, fillPattern)}, width, bgcolor);
}
QIcon nContamination(const Database::AesNContamination &awf, int size)
{
const QPolygonF poly = Polygons::nContamination(awf);
return QIcon(pixmapFromPolygon(poly, Qt::yellow, Qt::Dense4Pattern, size, QColor(0, 0, 0, 128)));
}
QIcon bcContamination(const Database::AesBCContamination &cwf,
ProjectDataManagement::VolatilityType volatilityType,
double expansionFactor,
const QDateTime &currentTime,
int size)
{
const QPolygonF poly = Polygons::bcContamination(cwf, volatilityType, expansionFactor, currentTime);
return QIcon(pixmapFromPolygon(poly, Qt::yellow, Qt::Dense4Pattern, size, QColor(0, 0, 0, 128)));
}
QIcon explosionSingle(const Database::AesExplosionSingle &es, double chargeRadius, int size)
{
QPolygonF poly = Polygons::explosionSingle(es, chargeRadius);
// Todo!
QColor color = (es.chargeTypeId == NEBEL) ? Qt::lightGray : Qt::yellow;
QColor bgrnd = Qt::transparent;
if (es.chargeTypeId != NEBEL) // Nebel / Smoke
{
color = Qt::red; // Todo: Teamcolor! teams->color(ef.partei_id);
bgrnd = QColor(0, 0, 0, 128);
}
return QIcon(pixmapFromPolygon(poly, color, Qt::Dense4Pattern, size, bgrnd));
}
QIcon explosionArea(const Database::AesExplosionArea &ea, int size)
{
// Todo!
QColor color = (ea.chargeTypeId == NEBEL) ? Qt::lightGray : Qt::yellow;
QColor bgrnd = Qt::transparent;
if (ea.chargeTypeId != NEBEL) // Nebel / Smoke
{
color = Qt::red; // Todo: Teamcolor! teams->color(ff.partei_id);
bgrnd = QColor(0, 0, 0, 128);
}
QPolygonF area = Polygons::explosionArea(ea);
return QIcon(pixmapFromPolygon(area, color, Qt::Dense4Pattern, size, bgrnd));
}
QIcon explosionAreaSingleExplosions(const Database::AesExplosionArea &ea, int size)
{
// Todo!
QColor color = (ea.chargeTypeId == NEBEL) ? Qt::lightGray : Qt::yellow;
if (ea.chargeTypeId != NEBEL) // Nebel / Smoke
color = Qt::red; // Todo: Teamcolor! teams->color(ea.partei_id);
const QVector<QPointF> singleExplosions = Polygons::explosionAreaSingleExplosions(ea);
QVector<PolygonData> datas;
datas.reserve(singleExplosions.size() + 1);
datas << PolygonData(Polygons::explosionArea(ea), color, Qt::Dense4Pattern);
for (const QPointF &explosion : singleExplosions)
{
/* TODO
if (explosion.time() < QDateTime::currentMSecsSinceEpoch())
datas << PolygonData(Polygons::circle(explosion.position(), 5), Qt::yellow, Qt::Dense4Pattern);
else
*/
datas << PolygonData(Polygons::circle(explosion, 5), Qt::green, Qt::Dense4Pattern);
}
return QIcon(pixmapFromPolygons(datas, size));
}
QIcon mineArea(const Database::AesMineArea &area, const QVector<Database::AesMineAreaSegment> &segments, int size)
{
QPolygonF gesamtPolygon = Polygons::mineArea(segments, area.width, area.density, area.isCenterLine);
const QVector<QPointF> minePositions = Polygons::minePositions(area, segments);
QVector<PolygonData> datas;
datas.reserve(minePositions.size() + 1);
datas << PolygonData(gesamtPolygon, Qt::green, Qt::Dense4Pattern);
for (const QPointF minePos : minePositions)
datas << PolygonData(Polygons::circle(minePos, 5), Qt::red, Qt::Dense4Pattern);
return QIcon(pixmapFromPolygons(datas, size));
}
QIcon mineCorridor(const QVector<Database::AesMineCorridorSegment> &segments, int width, int size)
{
const QPolygonF poly = Polygons::mineCorridor(segments, width);
return QIcon(pixmapFromPolygon(poly, Qt::yellow, Qt::Dense4Pattern, size, QColor(0, 0, 0, 128)));
}
} // Namespace
} // Namespace