/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #include "icons.h" #include "polygons.h" #include #include #include #include #include #include #include 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 &datas, int width, const QColor &bgcolor = Qt::transparent) { if (datas.isEmpty() || datas.first().poly.isEmpty()) return {}; QPolygonF polyUtm; QVector 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 ¤tTime, 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 singleExplosions = Polygons::explosionAreaSingleExplosions(ea); QVector 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 &segments, int size) { QPolygonF gesamtPolygon = Polygons::mineArea(segments, area.width, area.density, area.isCenterLine); const QVector minePositions = Polygons::minePositions(area, segments); QVector 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 &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