418 lines
11 KiB
C++
Executable File
418 lines
11 KiB
C++
Executable File
/**
|
||
* @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
|