Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/SymbologyImpl/symbol_extension_renderer.cpp
T
2026-08-13 18:33:10 +02:00

418 lines
11 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @RDE_HEADER@
* Class ExtensionRenderer
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "symbol_extension_renderer.h"
#include "sidc_codec.h"
// ESRI
// Qt
#include <QPainter>
#include <iostream>
const double g_factor = 0.95;
namespace AdvancedSymbology
{
QImage ExtensionRenderer::createFullImage(int sizeL, const QColor &fillColor)
{
const int fullSizeW = sizeL * 1.7; // FRIEND 1.5 L
const int fullSizeH = sizeL * 1.7; // try and error: '1.7';
// N. Thoden, 17.03.2020:
// Increase height to 2.2 to avoid FeintDummy (and mobility?) exceeds upper edge.
// But unfortunately then the map_object_custom_view has small icons - :-(
// Stay at 1.7
QImage fullImage(fullSizeW, fullSizeH, QImage::Format_ARGB32);
if (fillColor.isValid())
fullImage.fill(fillColor);
else
fullImage.fill(Qt::transparent);
// for debugging :
if (0)
{
QPainter painter(&fullImage);
QPen pen(Qt::black);
pen.setWidth(2.0);
painter.setPen(pen);
painter.drawRect(fullImage.rect());
}
// : for debugging
return fullImage;
}
void ExtensionRenderer::renderMarking(QImage &fullImage, const QColor &color)
{
QPainter painter(&fullImage);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QRect smallerRect(0, 0,
fullImage.width()*g_factor, fullImage.width()*g_factor); // we know, that the fullImage has more height, than width
const QPoint offset(((fullImage.width() - smallerRect.width()) / 2),
((fullImage.height() - smallerRect.height()) / 2));
smallerRect.moveTo(offset);
painter.setPen(QPen(Qt::NoPen)); // rect with no outter line
// maybe: QColor colorWithoutAlpha = color; colorWithoutAlpha.setAlpha(255);
painter.setBrush(QBrush(color, Qt::Dense5Pattern)); // fillPattern (Dense4Pattern .. Dense6Pattern)
painter.drawRect(smallerRect);
painter.end();
}
// hotSpotOfCoreImage - not be finished
QPoint hotSpotOfCoreImage(const QImage &coreImage,
const QString &sidc)
{
int hqFdTf = QString(sidc[7]).toInt();
if ((hqFdTf < 1) || ((hqFdTf > 7)))
return QPoint();
// int identity = QString(sidc[3]).toInt();
// bool taskForce = hqFdTf & 4; // mask
// bool headquarters = hqFdTf & 2; // mask
// bool feintDummy = hqFdTf & 1; // mask
/*
*Identity
Pending, ///< 0
Unknown, ///< 1
AssumedFriend, ///< 2
Friend, ///< 3
Neutral, ///< 4
SuspectJoker, ///< 5
HostileFaker ///< 6
*/
// set x value:
QPoint hotSpot = coreImage.rect().center();
// set y value:
// do not honor the frame (unknown/hostile vs. friend/neutral)
// accept a small error to ease the calculation:
// move hotSpot to bottom -> /
// move hotSpot to top -> *
switch (hqFdTf)
{
case 1:
case 5:
hotSpot.ry() *= 1.3;
break;
case 2:
hotSpot.ry() /= 1.7;
break;
case 3:
case 4:
// empty (it´s not worth)
break;
case 6:
case 7:
case 8:
break;
} // switch
return hotSpot;
}
QVector<QColor> ExtensionRenderer::identityToColor(const QString &sidc)
{
// The following color constants are taken from ArcGis Qt-SDK 10.2.5
const QString &rawSidc = SidcCodec::decodeRawSidc(sidc);
QVector<QColor> colorVec;
colorVec.reserve(2);
if (rawSidc.length() >= 4)
{
const QChar pos2 = rawSidc[1]; // according Mil2525Charlie
const QChar ident = rawSidc[3]; // according Mil2525Delta
// Unknown
if (ident == QLatin1Char('0') ||
ident == QLatin1Char('1') ||
pos2 == QLatin1Char('U') ||
pos2 == QLatin1Char('P') ||
pos2 == QLatin1Char('G') ||
pos2 == QLatin1Char('W')
)
{
colorVec.append(QColor(255, 255, 128));
colorVec.append(QColor(255, 255, 0)); // 10012500002108000000@Mil2525D: color = QColor(255, 255, 0);
// secondary:
colorVec.append(QColor(239, 239, 15)); // SchadMat: 10012500003210000000@MilAPP6D: color = QColor(239, 239, 15) = some kind of yellow
}
// Friend
else if (ident == QLatin1Char('2') ||
ident == QLatin1Char('3') ||
pos2 == QLatin1Char('F') ||
pos2 == QLatin1Char('A') ||
pos2 == QLatin1Char('M') ||
pos2 == QLatin1Char('D')
)
{
colorVec.append(QColor(128, 224, 255));
// secondary:
colorVec.append(QColor(0, 0, 0)); // SchadMat: 10032500003210000000@MilAPP6D: color = QColor(0, 0, 0) = black
}
// Neutral
else if (ident == QLatin1Char('4') ||
pos2 == QLatin1Char('N') ||
pos2 == QLatin1Char('L')
)
{
colorVec.append(QColor(170, 255, 170));
// secondary:
colorVec.append(QColor(0, 255, 0)); // SchadMat: 10042500003210000000@MilAPP6D: color = QColor(0, 0, 0) = some kind of light green
colorVec.append(QColor(85, 255, 0)); // MedVaclandezone?: 10042500003211000000@MilAPP6D: color = QColor(0, 0, 0) = some kind of light green
}
// Hostile
else if (ident == QLatin1Char('5') ||
ident == QLatin1Char('6') ||
pos2 == QLatin1Char('H') ||
pos2 == QLatin1Char('S')
)
{
colorVec.append(QColor(255, 128, 128));
// secondary:
colorVec.append(QColor(255, 0, 0)); // SchadMat: 10062500003210000000@MilAPP6D: color = QColor(255, 0, 0) = red
}
} // if (rawSidc.length() >= 2)
return colorVec;
}
bool ExtensionRenderer::replaceColor(QImage &img,
const QRgb &oldColor,
const QRgb &newColor)
{
#ifdef REPLACE_COLOR_DEBUG
std::cerr << " oldColor=" << oldColor << " newColor=" << newColor << std::endl;
#endif // REPLACE_COLOR_DEBUG
bool modified = false;
if (img.format() != QImage::Format_RGB32 &&
img.format() != QImage::Format_ARGB32)
{
img = img.convertToFormat(QImage::Format_ARGB32);
modified = true;
}
if (oldColor != newColor)
{
int xmax = img.width();
int ymax = img.height();
for (int x = 0; x < xmax; ++x)
{
for (int y = 0; y < ymax; ++y)
{
const QPoint curPixel(x, y);
const QRgb &pixel = img.pixel(curPixel);
if (pixel == oldColor)
{
img.setPixel(curPixel, newColor);
modified = true;
}
} // for
} // for
}
return modified;
}
void ExtensionRenderer::mergeCoreImageIntoFullImage(QImage &fullImage,
const QImage &coreImage)
{
QPainter painter(&fullImage);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QPoint offset((fullImage.width() - coreImage.width()) / 2,
(fullImage.height() - coreImage.height()) / 2);
QRect r = coreImage.rect();
r.moveTo(offset);
painter.drawImage(r, coreImage, coreImage.rect());
painter.end();
}
void ExtensionRenderer::renderInjuryAddSymbols(QImage &fullImage,
const Injury &injury,
const QColor &injuryColor,
const AdditionalSymbolTypeCont &additionalSymbols,
const QColor &mainColor)
{
QPainter painter(&fullImage);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
int width = fullImage.size().width();
// scaled and centered rect;
QRect smallerRect(0, 0,
fullImage.width()*g_factor, fullImage.width()*g_factor); // we know, that the fullImage has more height, than width
const QPoint offset(((fullImage.width() - smallerRect.width()) / 2),
((fullImage.height() - smallerRect.height()) / 2));
smallerRect.moveTo(offset);
//
// handle additionalSymbolType
//
{
int penWidth = width / 25;
for (AdditionalSymbolType additionalSymbolType : additionalSymbols)
{
double dimensionX = smallerRect.size().width(); // small
double dimensionY = fullImage.size().height(); // big
//
// First switch
//
QColor col = Qt::red;
switch (additionalSymbolType)
{
case AdditionalSymbolType::Manipulation:
col = Qt::black;
dimensionY -= penWidth * 2.5;
break;
case AdditionalSymbolType::NoPosition:
col = Qt::red;
dimensionY -= penWidth * 1.5;
break;
case AdditionalSymbolType::BiteError:
col = Qt::yellow;
dimensionY -= penWidth * 0.5;
break;
case AdditionalSymbolType::NbcProtection:
col = mainColor;
break;
} //switch (additionalSymbolType)
//
// Second switch
//
switch (additionalSymbolType)
{
case AdditionalSymbolType::Manipulation:
{
QPen pen(col);
pen.setWidth(penWidth);
double stepWidth = dimensionX / 6.0;
for (int i = 0; i < 6; ++i)
{
if (i % 2)
pen.setColor(Qt::white);
else
pen.setColor(col);
painter.setPen(pen);
painter.drawLine(QPointF(smallerRect.left() + stepWidth * i, dimensionY),
QPointF(smallerRect.left() + stepWidth * (i + 1), dimensionY));
}
}
break;
case AdditionalSymbolType::BiteError:
case AdditionalSymbolType::NoPosition:
{
QPen pen(col);
pen.setWidth(penWidth);
painter.setPen(pen);
painter.drawLine(QPointF(smallerRect.left(), dimensionY),
QPointF(smallerRect.right(), dimensionY));
}
break;
case AdditionalSymbolType::NbcProtection:
{
int y = (penWidth / 2.0) + (width * 0.01);
QPen pen(col);
pen.setWidth(penWidth);
painter.setPen(pen);
painter.drawLine(QPointF(smallerRect.left(), y),
QPointF(smallerRect.center().x() - (width * 0.1), y));
}
} // switch
} // for
} // additionalSymbolType
//
// handle injury
//
{
int penWidth = width / 20;
QPen pen(injuryColor);
pen.setWidth(penWidth);
painter.setPen(pen);
// handle injury {Hit, MobilityKill, WeaponKill, TotalKill}
switch (injury)
{
case AdvancedSymbology::Injury::Hit:
{
QPoint left(smallerRect.left(), fullImage.height() / 2);
QPoint right(smallerRect.right(), fullImage.height() / 2);
painter.drawLine(left, right);
}
break;
case AdvancedSymbology::Injury::MobilityKill:
painter.drawLine(smallerRect.topLeft(), smallerRect.bottomRight());
break;
case AdvancedSymbology::Injury::WeaponKill:
painter.drawLine(smallerRect.bottomLeft(), smallerRect.topRight());
break;
case AdvancedSymbology::Injury::TotalKill:
painter.drawLine(smallerRect.topLeft(), smallerRect.bottomRight());
painter.drawLine(smallerRect.bottomLeft(), smallerRect.topRight());
break;
case AdvancedSymbology::Injury::NoInjury:
break;
} // switch
} // injury
painter.end();
}
} // namespace AdvancedSymbology