464 lines
18 KiB
C++
Executable File
464 lines
18 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Interface-Implementation of EsriDictionaryProcessorMil2525D
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
// Own
|
|
#include "esri_dictionary_processor_mil2525d.h"
|
|
|
|
|
|
// ESRI
|
|
|
|
|
|
// Qt
|
|
#include <QThread>
|
|
|
|
|
|
namespace AdvancedSymbology
|
|
{
|
|
|
|
EsriDictionaryProcessorMil2525D::EsriDictionaryProcessorMil2525D()
|
|
: BaseClass(AdvancedSymbology::SymbologyType::MIL2525D)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " ThreadId=" << QThread::currentThreadId();
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
EsriDictionaryProcessorMil2525D::~EsriDictionaryProcessorMil2525D()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
this->cancel();
|
|
this->waitForFinished();
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void EsriDictionaryProcessorMil2525D::cancel()
|
|
{
|
|
BaseClass::cancel();
|
|
// add specific here:
|
|
}
|
|
|
|
void EsriDictionaryProcessorMil2525D::waitForFinished()
|
|
{
|
|
BaseClass::waitForFinished();
|
|
// add specific here:
|
|
}
|
|
|
|
|
|
bool EsriDictionaryProcessorMil2525D::searchResultIsValid(const QHash<QString, int> &key8LookupTable,
|
|
const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem,
|
|
QString *toBeRemovedFromName)
|
|
{
|
|
const QString &originalKey = resultItem.key();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " originalKey='" << originalKey << "'";
|
|
|
|
// check symbolClass: (to reduce empty keys, check symboClass first)
|
|
int symbolClass = resultItem.symbolClass().toInt();
|
|
if ((symbolClass == 6) || // symbolClass ( 6) == TextSymbol
|
|
(symbolClass == 10) // symbolClass (10) == MaplexLabelPlacement
|
|
)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " symbolClass does not match "
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// check if empty: [V100.0, ! V100.1]
|
|
//
|
|
#ifdef CHECK_HAS_EMPTY_KEY
|
|
if (originalKey.isEmpty())
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " empty key, "
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
#endif // CHECK_HAS_EMPTY_KEY
|
|
|
|
//
|
|
// size (25270100 || 25270100_4) [V100.0, V100.1]
|
|
//
|
|
const int keySize = originalKey.size();
|
|
if (!((keySize == 8) || (keySize == 10)))
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " keySize does not match,"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
|
|
|
|
//
|
|
// isFrame (key like '0_110_1c') [V100.0, V100.1]
|
|
//
|
|
if (originalKey.at(1) == QLatin1Char('_'))
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " isFrame,"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// isCharlie (key like '46120203_C') [V100.0, V100.1]
|
|
//
|
|
if ((keySize == 10) && (originalKey.rightRef(2).compare(QLatin1String("_C")) == 0))
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " isCharlie,"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// reduce key to base (e.g. 25270100_4 -> 25270100) [V100.0, V100.1]
|
|
//
|
|
const QString &key8 = originalKey.left(8);
|
|
|
|
bool ok = false;
|
|
key8.toInt(&ok); // check for being an integer
|
|
if (!ok)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " chars, "
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false;
|
|
}
|
|
|
|
// V100.0: For these the key exists twice! (SymbolClass '3' and '5')
|
|
// -> prefer item with SymbolClass '3'
|
|
static const QSet<QString> listOfKnownDoubleEntries({QStringLiteral("25140103"),
|
|
QStringLiteral("25140606"),
|
|
QStringLiteral("25140607"),
|
|
QStringLiteral("25151407"),
|
|
QStringLiteral("25151408"),
|
|
QStringLiteral("25140104"),
|
|
QStringLiteral("25140102"),
|
|
QStringLiteral("25150101"),
|
|
QStringLiteral("25150102"),
|
|
QStringLiteral("25150103"),
|
|
QStringLiteral("25150104"),
|
|
QStringLiteral("25151802"),
|
|
QStringLiteral("25200500"),
|
|
QStringLiteral("25200600"),
|
|
QStringLiteral("25241403"),
|
|
QStringLiteral("25270703"),
|
|
QStringLiteral("25270704"),
|
|
QStringLiteral("25200400"),
|
|
QStringLiteral("25272100"),
|
|
});
|
|
|
|
if (listOfKnownDoubleEntries.contains(key8))
|
|
{
|
|
const QString &symClass = resultItem.symbolClass();
|
|
if (!symClass.compare(QLatin1String("3")))
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " listOfKnownDoubleEntries"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'"
|
|
<< " symbolClass='" << symClass << "'";
|
|
return false; // use other/proper with better SymbolClass instead
|
|
}
|
|
}
|
|
|
|
//
|
|
// use key8 instead of key10 [V100.0, V100.1]
|
|
//
|
|
if (keySize == 10)
|
|
{
|
|
//
|
|
// there are entries with postfix (_1) and AND proper key8
|
|
// (e.g. '25271800_3' ; ... ; and proper 25271800:
|
|
//
|
|
bool useOtherKey8 = key8LookupTable.contains(key8);
|
|
|
|
if (useOtherKey8)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " useOtherKey8_a"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false; // use other/proper key8 item instead
|
|
}
|
|
|
|
//
|
|
// there are entries with postfix (_1) and AND NO proper key8
|
|
// (e.g. '10120100_0' ; '10120100_1' ; '10120100_2' ; '10120100_3' ; but no '10120100'
|
|
// 10120100 = Movement And Maneuver ; Air Assult with Organic Lift - FullFrame
|
|
//
|
|
// Most of the times these are the FULL_FRAME symbols. (except "Maneuver Lines : Line of Contact" = 25140200_6)
|
|
//
|
|
// use neutral item instead
|
|
//
|
|
const QString &name = resultItem.name();
|
|
if (name.contains(QStringLiteral("Neutral")))
|
|
{
|
|
if (toBeRemovedFromName)
|
|
*toBeRemovedFromName = QStringLiteral("Neutral");
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " useOtherKey8_bb"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
return false; // wait for Neutral item
|
|
}
|
|
|
|
} // if (keySize == 10)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool EsriDictionaryProcessorMil2525D::processBaseSymbolCodeToPropertyTable()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
if (m_searchResultList.isEmpty())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_searchResultList.isEmpty";
|
|
return false;
|
|
}
|
|
|
|
QHash<QString, int> key8LookupTable;
|
|
for (int i = 0; i < m_searchResultList.size(); ++i)
|
|
{
|
|
const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem = m_searchResultList.at(i);
|
|
if (resultItem.key().size() == 8)
|
|
key8LookupTable[resultItem.key()] = i;
|
|
}
|
|
|
|
int resultItemCounter = 0;
|
|
int gctStringEmptyCounter = 0;
|
|
for (const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem : qAsConst(m_searchResultList))
|
|
{
|
|
|
|
// canceled?
|
|
// 2017-09-07, Qt5.9, N. Thoden
|
|
// A default initialized QFuture seems to have an inconsistent state:
|
|
// -> isStarted=1 <---!!!
|
|
// -> isRunning=0
|
|
// -> isCanceled=1 <---!!!
|
|
// so check isCanceled() && isRunning()
|
|
// 2017-10-09, Qt5.9.1, N.Thoden
|
|
// Problöem still arises, so perform at a least a couple:
|
|
if (m_baseSymbolCodeToSymbolPropertyTableWatcher.isCanceled() && m_baseSymbolCodeToSymbolPropertyTableWatcher.isRunning() &&
|
|
(resultItemCounter >= 10))
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_baseSymbolCodeToSymbolPropertyTableWatcher.isCanceled";
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_baseSymbolCodeToSymbolPropertyTableWatcher.isStarted=" << m_baseSymbolCodeToSymbolPropertyTableWatcher.isStarted();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_baseSymbolCodeToSymbolPropertyTableWatcher.isRunning=" << m_baseSymbolCodeToSymbolPropertyTableWatcher.isRunning();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_baseSymbolCodeToSymbolPropertyTableWatcher.isCanceled=" << m_baseSymbolCodeToSymbolPropertyTableWatcher.isCanceled();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_baseSymbolCodeToSymbolPropertyTableWatcher.isFinished=" << m_baseSymbolCodeToSymbolPropertyTableWatcher.isFinished();
|
|
return false;
|
|
}
|
|
|
|
|
|
if (resultItemCounter == 0)
|
|
INFO_LOG(m_logger) << LOGFUNCTION << " counter=" << resultItemCounter;
|
|
|
|
++resultItemCounter;
|
|
|
|
if ((resultItemCounter % 500) == 0)
|
|
INFO_LOG(m_logger) << LOGFUNCTION << " counter=" << resultItemCounter;
|
|
|
|
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.key ='" << resultItem.key() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.name ='" << resultItem.name() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.category ='" << resultItem.category() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.symbolClass ='" << resultItem.symbolClass() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.tags ='" << resultItem.tags().join(QLatin1String(";")) << "'";
|
|
|
|
bool isValid = searchResultIsValid(key8LookupTable, resultItem);
|
|
|
|
if (!isValid)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION
|
|
<< " continue:: not valid "
|
|
<< " key='" << resultItem.key() << "'"
|
|
<< " name='" << resultItem.name() << "'";
|
|
continue;
|
|
}
|
|
|
|
const QString &originalKey = resultItem.key();
|
|
const QString &key8 = originalKey.left(8);
|
|
|
|
if (m_baseSymbolCodeToSymbolPropertyTable.contains(key8))
|
|
{
|
|
FATAL_LOG(m_logger) << LOGFUNCTION
|
|
<< " continue:: already EXISTS!!!"
|
|
<< " key8='" << key8 << "'"
|
|
<< " originalKey='" << originalKey << "'";
|
|
continue;
|
|
}
|
|
|
|
SymbolProperties symProps;
|
|
symProps.setKey(key8);
|
|
symProps.setName(resultItem.name());
|
|
symProps.setCategory(resultItem.category());
|
|
symProps.setSymbolClass(resultItem.symbolClass());
|
|
symProps.setTags(resultItem.tags());
|
|
symProps.setOriginalKey(originalKey);
|
|
symProps.setSidc(SidcCodec::encodeBaseSymbolCode(m_baseSymbolCodeToSymbolPropertyTable.symbologyType(), key8));
|
|
// retrieve GeometryType
|
|
const QString cat = resultItem.category();
|
|
const QVector<QStringRef> &slCategory = cat.splitRef(QLatin1Char(':'));
|
|
if (!slCategory.isEmpty())
|
|
{
|
|
const QStringRef &geometryStr = slCategory.last().trimmed();
|
|
bool isPoint = geometryStr.compare(QLatin1String("Point"), Qt::CaseInsensitive) == 0;
|
|
bool isMainIcon = geometryStr.compare(QLatin1String("Main Icon"), Qt::CaseInsensitive) == 0;
|
|
bool isLine = geometryStr.compare(QLatin1String("Line"), Qt::CaseInsensitive) == 0;
|
|
bool isArea = geometryStr.compare(QLatin1String("Area"), Qt::CaseInsensitive) == 0;
|
|
|
|
if (isPoint || isMainIcon)
|
|
symProps.setGeometryType(GeometryType::Point);
|
|
else if (isLine)
|
|
symProps.setGeometryType(GeometryType::Polyline);
|
|
else if (isArea)
|
|
symProps.setGeometryType(GeometryType::Polygon);
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " XXXXXXXXX GeometryType:"
|
|
<< " key8='" << key8 << "'"
|
|
<< " originalKey='" << originalKey << "'"
|
|
<< "' slLast='" << slCategory.last().toString() << "'"
|
|
<< " geoType= " << symProps.geometryType();
|
|
|
|
// check for gct_-String:
|
|
if (symProps.geometryType() == GeometryType::Polyline ||
|
|
symProps.geometryType() == GeometryType::Polygon)
|
|
{
|
|
const QString gctString = symProps.gctString();
|
|
if (gctString.isEmpty())
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " gctString empty: key8='" << key8 << "'"
|
|
<< " geoType= " << symProps.geometryType()
|
|
<< " tags=" << resultItem.tags().join(QLatin1String(";"));
|
|
++gctStringEmptyCounter;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
m_baseSymbolCodeToSymbolPropertyTable[key8] = symProps;
|
|
|
|
// For modelNG
|
|
m_searchResultListValid.append(resultItem);
|
|
} // for
|
|
|
|
m_baseSymbolCodeToSymbolPropertyTableFilled = true;
|
|
NOTICE_LOG(m_logger) << LOGFUNCTION << " ##### resultItemCounter=" << resultItemCounter
|
|
<< " m_baseSymbolCodeToSymbolPropertyTable.size=" << m_baseSymbolCodeToSymbolPropertyTable.size()
|
|
<< " gctStringEmptyCounter=" << gctStringEmptyCounter
|
|
<< " threadId: " << QThread::currentThreadId();
|
|
emit baseSymbolCodeToPropertyTableDone();
|
|
|
|
|
|
checkIfAllAreDone(); // will potentially emit signal 'allIsDone'
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
bool EsriDictionaryProcessorMil2525D::processModifierTable()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
if (m_searchResultList.isEmpty())
|
|
return false;
|
|
|
|
|
|
int counter = 0;
|
|
for (const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem : qAsConst(m_searchResultList))
|
|
{
|
|
++counter;
|
|
|
|
// canceled?
|
|
if (m_modifierTableWatcher.isCanceled() && m_modifierTableWatcher.isRunning())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_modifierTableWatcher.isCanceled";
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_modifierTableWatcher.isStarted=" << m_modifierTableWatcher.isStarted();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_modifierTableWatcher.isRunning=" << m_modifierTableWatcher.isRunning();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_modifierTableWatcher.isCanceled=" << m_modifierTableWatcher.isCanceled();
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " m_modifierTableWatcher.isFinished=" << m_modifierTableWatcher.isFinished();
|
|
return false;
|
|
}
|
|
|
|
const QString &originalKey = resultItem.key();
|
|
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.key ='" << originalKey << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.name ='" << resultItem.name() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.category ='" << resultItem.category() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.symbolClass ='" << resultItem.symbolClass() << "'";
|
|
// INFO_LOG(m_logger) << LOGFUNCTION << " resultItem.tags ='" << resultItem.tags().join(QLatin1String(";")) << "'";
|
|
|
|
if (originalKey.length() == 5) // ToDo: check contraint?
|
|
{
|
|
bool isDigit = false;
|
|
originalKey.toInt(&isDigit); // check for being an integer
|
|
|
|
if (isDigit)
|
|
{
|
|
const QString &resultItemName = resultItem.name(); // store result item name locally to guaranty following splitRef
|
|
const QVector<QStringRef> &sl = resultItemName.splitRef(QLatin1String(" : ")); // otherwise ("resultItem.name().splitRef(...)") unpredictable results are possible
|
|
|
|
// log multiple keys:
|
|
if (m_modifierTable.contains(originalKey))
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " originalKey already in cont: key='" << originalKey << "'" << " resultItem.name() ='" << resultItem.name() << "'";
|
|
|
|
ModifierData modData;
|
|
|
|
modData.m_modifierKey = originalKey;
|
|
|
|
SidcDefinitions::SymbolSet symbolSetEnum = static_cast<SidcDefinitions::SymbolSet>(originalKey.midRef(0, 2).toUInt());
|
|
|
|
if (!SidcDefinitions::symbolSets().contains(symbolSetEnum))
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " Unknown symbol set code found, symbol set code = '" << symbolSetEnum << "'"
|
|
<< " originalKey = '" << originalKey << "'";
|
|
symbolSetEnum = SidcDefinitions::SymbolSet::Unknown;
|
|
}
|
|
|
|
modData.m_symbolSet = symbolSetEnum;
|
|
modData.m_modifierSector = originalKey.midRef(4, 1).toUInt();
|
|
modData.m_modifierValue = originalKey.midRef(2, 2).toUInt();
|
|
modData.m_modifierName = (sl.size() == 2) ? sl.last().toString() : resultItem.name();
|
|
|
|
m_modifierTable[originalKey] = modData;
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " originalKey ='" << originalKey << "'" << " sector = " << modData.m_modifierSector << " modifierName ='" << modData.m_modifierName << "'";
|
|
}
|
|
}
|
|
|
|
} // for
|
|
|
|
m_modifierTableFilled = true;
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " ##### counter=" << counter
|
|
<< " m_modifierTable.size=" << m_modifierTable.size()
|
|
<< " threadId: " << QThread::currentThreadId();
|
|
|
|
emit modifierTableDone();
|
|
checkIfAllAreDone(); // will potentially emit signal 'allIsDone'
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
|
|
} // namespace AdvancedSymbology
|
|
|