Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/UnitTests/unit_test.cpp
T

3638 lines
140 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@
* Unittest
* $Id$
* $HeadURL$
* $Author$
*/
#include "unit_test.h"
#include <QtTest/QTest>
#include <QtTest/QSignalSpy>
#include <QWeakPointer>
#include <nglapplication/nglapplication.h>
#include <ngltools/ngltools_filesystem.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <Map/bounding_box.h>
#include <Map/object_factory.h>
#include <MapImpl/map_impl.h>
#include <MapImpl/map_layer.h>
#include <MapImpl/layer_factory_impl.h>
#include <MapImpl/object_container_impl.h>
#include <MapObjectsImpl/participant_impl.h>
#include <MapObjectsImpl/biological_agent_impl.h>
#include <MapObjectsImpl/building_outline_impl.h>
#include <MapObjectsImpl/danger_area_impl.h>
#include <Map/map_settings.h>
#include <MapImpl/coordinate_translation.h>
#include <MathUtils/matrix2d.h>
#include <Utils/movement_track.h>
#include <Utils/movement_track_manager.h>
//#include <Common/id_handler.h>
#include <Common/simple_value.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <SymbologyImpl/symbol_dictionary_impl.h>
#include <Symbology/symbol_properties.h>
#include <Symbology/sidc_codec.h>
#include <Symbology/sidc_builder.h>
#include <Symbology/symbol_result.h>
#include <Symbology/bulk_renderer.h>
#include <CoordinateFormatter.h>
#include <GeometryEngine.h>
#include <LinearUnit.h>
#include <PolylineBuilder.h>
#include <QPainter>
#include <QTimer>
#include <QUuid>
#include <QJsonDocument>
#include <iostream>
#include <GeometryEngine.h>
#include <PolygonBuilder.h>
bool CheckSignal::isConnected(quint64 &msec)
{
QElapsedTimer timeClock;
timeClock.start();
bool isConnected = isSignalConnected(QMetaMethod::fromSignal(&CheckSignal::mySignal));
msec = timeClock.elapsed();
return isConnected;
}
//-------------------------------------------------------------------------------------------------------
// Helper class 'IdGeneratorCounting'
//-------------------------------------------------------------------------------------------------------
class IdGeneratorCounting : public SituationMap::IdGenerator
{
public:
IdGeneratorCounting() : SituationMap::IdGenerator()
{
++counter;
}
~IdGeneratorCounting()
{
--counter;
}
static ulong getCounter()
{
return counter;
}
private:
static ulong counter;
};
ulong IdGeneratorCounting::counter = 0;
//-------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
NGLApplication app(argc, argv);
app.createLogger("SituationMapUnitTest", "log4cxxSituationMapUnitTest.props");
AdvancedSymbology::SymbologyType symbologyType = AdvancedSymbology::SymbologyType::MIL2525C;
if (argc < 2)
{
// usage:
std::cout << argv[0]
<< std::endl
<< " usage: append 'mil' | 'app' to argumentlist" << std::endl
<< " e.g " << argv[0] << " [QTest options] [testfunction] none" << std::endl
<< " e.g " << argv[0] << " [QTest options] [testfunction] mil2525D" << std::endl
<< " e.g " << argv[0] << " [QTest options] [testfunction] mil2525C" << std::endl
<< " e.g " << argv[0] << " [QTest options] [testfunction] app6b" << std::endl
<< " e.g " << argv[0] << " [QTest options] [testfunction] app6d" << std::endl
<< std::endl;
return -1;
}
const QString strSymType = app.arguments().constLast(); // the last argument
if (strSymType.compare(QLatin1String("none"), Qt::CaseInsensitive) == 0)
symbologyType = AdvancedSymbology::SymbologyType::None;
else if (strSymType.compare(QLatin1String("mil2525D"), Qt::CaseInsensitive) == 0)
symbologyType = AdvancedSymbology::SymbologyType::MIL2525D;
else if (strSymType.compare(QLatin1String("mil2525C"), Qt::CaseInsensitive) == 0)
symbologyType = AdvancedSymbology::SymbologyType::MIL2525C;
else if (strSymType.compare(QLatin1String("app6b"), Qt::CaseInsensitive) == 0)
symbologyType = AdvancedSymbology::SymbologyType::APP6B;
else if (strSymType.compare(QLatin1String("app6d"), Qt::CaseInsensitive) == 0)
symbologyType = AdvancedSymbology::SymbologyType::APP6D;
argc -= 1; // remove last argument for QTest::qExec
SituationMap::LayerFactoryImpl::setForceCreationOfGraphicsOverlay(false); // false => createLayerOnDemand
QSharedPointer<SitMapUnitTest> tc = QSharedPointer<SitMapUnitTest>(new SitMapUnitTest(symbologyType));
int retCode = QTest::qExec(tc.data(), argc, argv);
return retCode;
}
class SitMapUnitTest::Private
{
public:
Private()
: m_symbologyType(AdvancedSymbology::SymbologyType::MIL2525C)
{
// m_uniqueIdHandler = new SituationMap::IdHandler(m_initReserve,m_blockSize);
}
~Private() = default;
// std::unique_ptr<SituationMap::IdHandler> m_uniqueIdHandler;
AdvancedSymbology::SymbologyType m_symbologyType;
}; // class Private
//-----------------------------------------------------------------------------
class Foo
{
public:
virtual ~Foo() = default;
static Foo *createFoo()
{
return new Foo();
}
Foo(const Foo &) = delete; // if needed, put as private
Foo &operator=(const Foo &) = delete; // if needed, put as private
Foo(Foo &&) = delete; // if needed, put as private
Foo &operator=(Foo &&) = delete; // if needed, put as private
private:
Foo() {}
};
class baseClass
{
public:
virtual ~baseClass() = default;
baseClass(const baseClass &) = delete;
baseClass &operator=(const baseClass &) = delete;
baseClass(baseClass &&) = delete;
baseClass &operator=(baseClass &&) = delete;
virtual void doSomething() = 0;
protected:
baseClass() {}
};
class subClass : public baseClass
{
public:
~subClass() = default;
static subClass *create()
{
return new subClass();
}
void doSomething() override { }
private:
subClass() = default;
};
SitMapUnitTest::SitMapUnitTest(AdvancedSymbology::SymbologyType symbologyType)
: m_logger(SituationMap::getLogger("SitMapUnitTest"))
, m_d(new Private)
{
m_d->m_symbologyType = symbologyType;
NOTICE_LOG(m_logger) << "Running test with symbologyType " << m_d->m_symbologyType;
}
SitMapUnitTest::~SitMapUnitTest()
{
NOTICE_LOG(m_logger) << "Finished running test with symbologyType " << m_d->m_symbologyType;
}
void SitMapUnitTest::checkLogging()
{
SituationMap::LOGGER_T myLogger = SituationMap::getLogger("LoggingTest.Chan1");
FATAL_LOG(myLogger) << LOGFUNCTION << " myLogger.getLoggerName() -> " << myLogger.getLoggerName();
DEBUG_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan1) DEBUG-MSG" ;
INFO_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan1) INFO-MSG" ;
WARNING_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan1) WARNING-MSG" ;
ERROR_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan1) ERROR-MSG" ;
FATAL_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan1) FATAL-MSG" ;
FATAL_LOG(myLogger) << LOGFUNCTION << " ------------";
{
SituationMap::LOGGER_T myLogger = SituationMap::getLogger("LoggingTest.Chan2");
FATAL_LOG(myLogger) << LOGFUNCTION << " myLogger.getLoggerName() -> " << myLogger.getLoggerName();
DEBUG_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan2) DEBUG-MSG" ;
INFO_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan2) INFO-MSG" ;
WARNING_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan2) WARNING-MSG" ;
ERROR_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan2) ERROR-MSG" ;
FATAL_LOG(myLogger) << LOGFUNCTION << " (LoggingTest.Chan2) FATAL-MSG" ;
}
FATAL_LOG(myLogger) << LOGFUNCTION << " ------------" ;
// update logger-obj
SituationMap::LOGGER_T myLogger2 = SituationMap::getLogger("LoggingTest.Chan2");
FATAL_LOG(myLogger2) << LOGFUNCTION << " myLogger.getLoggerName() -> " << myLogger2.getLoggerName() ;
DEBUG_LOG(myLogger2) << LOGFUNCTION << " (LoggingTest.Chan2) DEBUG-MSG" ;
INFO_LOG(myLogger2) << LOGFUNCTION << " (LoggingTest.Chan2) INFO-MSG" ;
WARNING_LOG(myLogger2) << LOGFUNCTION << " (LoggingTest.Chan2) WARNING-MSG" ;
ERROR_LOG(myLogger2) << LOGFUNCTION << " (LoggingTest.Chan2) ERROR-MSG" ;
FATAL_LOG(myLogger2) << LOGFUNCTION << " (LoggingTest.Chan2) FATAL-MSG" ;
}
struct shm_punkt_rt
{
shm_punkt_rt(double x = 0, double y = 0)
{
p[0] = x; // Ost
p[1] = y; // Nord
}
double p[2];
};
void SitMapUnitTest::checkQRect()
{
QRectF rect;
QVERIFY2((rect.isEmpty() == true), "isEmpty: failed");
QVERIFY2((rect.isValid() == false), "isValid: failed");
rect = QRectF(100, 100, 40, 60);
QVERIFY2((rect.isEmpty() == false), "isEmpty: failed");
QVERIFY2((rect.isValid() == true), "isValid: failed");
QVERIFY2(rect.width() == 40, "center: failed");
QVERIFY2(rect.height() == 60, "center: failed");
qDebug() << " rect.center()" << rect.center();
QVERIFY2(((rect.center() - QPoint(120, 130)).manhattanLength() <= 2), "center: failed");
QVERIFY2(rect.top() == 100, "top: failed"); // <-----
QVERIFY2(rect.bottom() == 160, "bottom: failed"); // <-----
QVERIFY2(rect.topLeft() == QPointF(100, 100), "topLeft: failed"); // <-----
qDebug() << " rect.topRight()" << rect.topRight();
QVERIFY2(rect.topRight() == QPointF(140, 100), "topLeft: failed"); // <-----
}
void SitMapUnitTest::checkQListQVector()
{
std::vector<shm_punkt_rt> refPoints;
int refSize = 1000000;
refPoints.reserve(refSize);
for (int i = 0; i < refSize; ++i)
refPoints.emplace_back(i, 100.1 * i);
// check within 2*5:
QList<QPointF> qContL; // do NOT modify, QList is used to compare with QVector (a couple of lines later)
QVector<QPointF> qContV;
for (int i = 0; i < 10; ++i)
{
if (i % 2 == 0)
{
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
qContL.clear();
qContL.reserve(refSize);
for (const shm_punkt_rt &item : refPoints)
qContL.append(QPointF(item.p[0], item.p[1]));
INFO_LOG(m_logger) << LOGFUNCTION
<< " QList<QPointF> -> "
<< timer.elapsed() << "ms";
}
else
{
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
qContV.clear();
qContV.reserve(refSize);
for (const shm_punkt_rt &item : refPoints)
qContV.append(QPointF(item.p[0], item.p[1]));
INFO_LOG(m_logger) << LOGFUNCTION
<< " QVector<QPointF> -> "
<< timer.elapsed() << "ms";
}
}
}
void SitMapUnitTest::checkQWeakPointer()
{
QWeakPointer<SituationMap::TextStyle> ts_weak; // TextStyle does NOT inherent from QObject
QVERIFY2((ts_weak.isNull() == true), "isNull: failed");
{
QSharedPointer<SituationMap::TextStyle> ts_shared(new SituationMap::TextStyle());
ts_weak = ts_shared; // 'connected' weak and shared
QVERIFY2((ts_weak.isNull() == false), "isNull: failed");
} // shared will delete object
QVERIFY2((ts_weak.isNull() == true), "isNull: failed"); // weak 'knows' the deletion :-)
// // you should continue like this:
// QSharedPointer<SituationMap::TextStyle> ts_shared2 = ts_weak.toStrongRef();
// if (ts_shared2)
// {
// ts_shared2->doSomething();
// } else {
// // error, object down not exists anymore
// }
}
void SitMapUnitTest::checkFactoryCreationContraints()
{
// Links: http://stackoverflow.com/questions/124880/is-it-possible-to-prevent-stack-allocation-of-an-object-and-only-allow-it-to-be
// Links: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Requiring_or_Prohibiting_Heap-based_Objects
//
// Foo
//
// creation on stack:
// Foo f; // will not compile, ctor is private
// creation on heap:
// Foo *f_ptr1 = new Foo(); // will not compile, ctor is private
Foo *f_ptr2 = Foo::createFoo();
delete f_ptr2;
//
// subClass
//
// creation on stack:
// subClass sC; // will not compile, ctor is private
// creation on heap:
// subClass *sC_ptr1 = new subClass(); // will not compile, ctor is private
subClass *sC_ptr2 = subClass::create();
delete sC_ptr2;
}
//-------------------------------------------------------------------------------------------------------
/*
void SitMapUnitTest::checkIdHandlerCreate()
{
quint32 usedIdCount = m_d->m_uniqueIdHandler->countUsedIds();
QVERIFY2( (usedIdCount == 0), "Check IdHandler initial value failed, wrong id count" );
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " used id count before test = "
<< usedIdCount
;
// create one object
SituationMap::IdHandler::AccessableId * myPtr = new SituationMap::IdHandler::AccessableId();
SituationMap::IdHandler::UniqueMapId myId = m_d->m_uniqueIdHandler->createId( myPtr );
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " created id = "
<< myId
<< " obj address = "
<< myPtr
;
// check count of ids, myId and accessId function
QVERIFY2( ((usedIdCount+1) == m_d->m_uniqueIdHandler->countUsedIds()), "Check IdHandler create failed, wrong id count" );
QVERIFY2( SituationMap::IdHandler::isIdValid(myId) , "Check IdHandler create failed, bad id" );
QVERIFY2( (m_d->m_uniqueIdHandler->accessId(myId) == myPtr) , "Check IdHandler create failed, pointer mismatch" );
// check invalid access
myPtr = m_d->m_uniqueIdHandler->accessId( SituationMap::IdHandler::UniqueMapId(-2) );
QVERIFY2( (myPtr == nullptr) , "Check IdHandler create failed, invalid access doesn_t return nullptr" );
}
void SitMapUnitTest::checkIdHandlerFree()
{
quint32 usedIdCount = m_d->m_uniqueIdHandler->countUsedIds();
SituationMap::IdHandler::AccessableId * myPtr = new SituationMap::IdHandler::AccessableId();
SituationMap::IdHandler::UniqueMapId myId = m_d->m_uniqueIdHandler->createId( myPtr );
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " created id ="
<< myId
<< " obj address ="
<< myPtr
;
bool ok = m_d->m_uniqueIdHandler->freeId( myId );
QVERIFY2( ok, "Check IdHandler freeId failed, return value of freeId is false." );
QVERIFY2( (usedIdCount == m_d->m_uniqueIdHandler->countUsedIds()), "Check IdHandler freeId failed, wrong id count." );
QVERIFY2( (m_d->m_uniqueIdHandler->accessId(myId) == nullptr) , "Check IdHandler freeId failed, id is still in use." );
ok = m_d->m_uniqueIdHandler->freeId( SituationMap::IdHandler::BadId );
QVERIFY2(ok == false, "Check IdHandler freeId failed, return value of freeId(BadId) is not false." );
ok = m_d->m_uniqueIdHandler->freeId( SituationMap::IdHandler::UniqueMapId(-2) );
QVERIFY2(ok == false, "Check IdHandler freeId failed, return value of freeId(<not used id>) is not false." );
}
void SitMapUnitTest::checkIdHandlerReUseId()
{
quint32 usedIdCount = m_d->m_uniqueIdHandler->countUsedIds();
QList<SituationMap::IdHandler::UniqueMapId> idList;
for (unsigned int idx = usedIdCount; idx < m_initReserve; ++idx)
{
idList += m_d->m_uniqueIdHandler->createId( new SituationMap::IdHandler::AccessableId() );
}
bool ok = m_d->m_uniqueIdHandler->freeId( idList.first() );
QVERIFY2( ok, "Check IdHandler reUseId failed, return value of freeId is false." );
if (ok)
{
SituationMap::IdHandler::UniqueMapId id = m_d->m_uniqueIdHandler->createId( new SituationMap::IdHandler::AccessableId() );
QVERIFY2(id == idList.first(), "Check IdHandler reUseId failed, freed id has not been used again." );
}
}
void SitMapUnitTest::checkIdHandlerReserveId()
{
quint32 usedIdCount = m_d->m_uniqueIdHandler->countUsedIds();
SituationMap::IdHandler::UniqueMapId reserveId = usedIdCount + 7;
// look for a unused id
while (m_d->m_uniqueIdHandler->isIdInUse(reserveId))
{
reserveId++;
}
// first reserve should return true
bool ok = m_d->m_uniqueIdHandler->reserveId( reserveId, new SituationMap::IdHandler::AccessableId() );
QVERIFY2( ok, "Check IdHandler reserveId failed, reserveId returns false." );
if (ok)
{
// second reserve should return false
ok = m_d->m_uniqueIdHandler->reserveId( reserveId, new SituationMap::IdHandler::AccessableId() );
QVERIFY2( !ok, "Check IdHandler reserveId failed, second reserveId doesn't return false." );
for (int idx = reserveId - usedIdCount + 20; idx >= 0; --idx)
{
SituationMap::IdHandler::UniqueMapId myId = m_d->m_uniqueIdHandler->createId( new SituationMap::IdHandler::AccessableId() );
QVERIFY2( myId != reserveId, "Check IdHandler reserveId failed, createId returns reserved id." );
}
}
}
*/
void SitMapUnitTest::checkSimpleValue()
{
const int intVal = 42;
const int intValModified = 123;
// assign
SituationMap::SimpleValue<int> wrappedValue = intVal;
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
QVERIFY2((wrappedValue.value() == 42), "SimpleValue: failed");
// reset
wrappedValue.reset();
QVERIFY2((wrappedValue.changed() == false), "SimpleValue: failed");
QVERIFY2((wrappedValue.value() == 42), "SimpleValue: failed");
// access:
bool ok = false;
ok = (wrappedValue.value() == intVal);
QVERIFY2((ok), "SimpleValue: failed");
QVERIFY2((wrappedValue.changed() == false), "SimpleValue: failed");
ok = (wrappedValue.refValue() == intVal);
QVERIFY2((ok), "SimpleValue: failed");
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
ok = (wrappedValue() == intVal);
QVERIFY2((ok), "SimpleValue: failed");
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
// assign
SituationMap::SimpleValue<int> wrappedValue2 = wrappedValue;
QVERIFY2((wrappedValue2.changed() == true), "SimpleValue: failed");
wrappedValue.reset();
wrappedValue = intValModified;
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
QVERIFY2((wrappedValue.value() == intValModified), "SimpleValue: failed");
// refValue
wrappedValue.reset();
wrappedValue.refValue() = intVal;
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
QVERIFY2((wrappedValue.value() == intVal), "SimpleValue: failed");
// setChanged
wrappedValue.reset();
QVERIFY2((wrappedValue.changed() == false), "SimpleValue: failed");
wrappedValue.setChanged();
QVERIFY2((wrappedValue.changed() == true), "SimpleValue: failed");
// ok = wrappedValue == wrappedValue2; // not supported
}
void SitMapUnitTest::checkIdGenerator()
{
QSharedPointer<SituationMap::IdGenerator> idGenerator(new SituationMap::IdGenerator());
QVERIFY2((idGenerator.isNull() == false), "Check IdGenerator does not exits");
SituationMap::UniqueMapId id = idGenerator->getNextId();
QVERIFY2((id == 0), "Check IdGenerator initial value failed, wrong id");
QVERIFY2((SituationMap::IdGenerator::idIsValid(id)), "Check IdGenerator id invalid");
QVERIFY2((SituationMap::isUniqueMapIdValid(id)), "Check IdGenerator id invalid");
id = idGenerator->getNextId();
QVERIFY2((id == 1), "Check IdGenerator initial value failed, wrong id");
QVERIFY2((SituationMap::IdGenerator::idIsValid(id)), "Check IdGenerator id invalid");
QVERIFY2((SituationMap::isUniqueMapIdValid(id)), "Check IdGenerator id invalid");
id = idGenerator->getNextId();
QVERIFY2((id == 2), "Check IdGenerator initial value failed, wrong id");
QVERIFY2((SituationMap::IdGenerator::idIsValid(id)), "Check IdGenerator id invalid");
QVERIFY2((SituationMap::isUniqueMapIdValid(id)), "Check IdGenerator id invalid");
id = SituationMap::IdGenerator::INVALID_ID;
QVERIFY2((SituationMap::IdGenerator::idIsValid(id) == false), "Check INVALID_ID is NOT invalid");
QVERIFY2((SituationMap::isUniqueMapIdValid(id) == false), "Check INVALID_ID is NOT invalid");
}
//class MyBuildingOutlineImpl : public SituationMap::BuildingOutlineImpl
//{
//public:
// MyBuildingOutlineImpl(const QString &debugInfo = QString())
// : SituationMap::BuildingOutlineImpl(debugInfo)
// {}
//};
// create template to derive from XY-MapObjectImpl to overcome protected ctor:
template <typename T>
class MyMapObjectType : public T
{
public:
MyMapObjectType(const QString &debugInfo = QString())
: T(debugInfo)
{}
};
using MyParticipantImpl = MyMapObjectType<SituationMap::ParticipantImpl>;
using MyBiologicalAgentImpl = MyMapObjectType<SituationMap::BiologicalAgentImpl>;
using MyBuildingOutlineImpl = MyMapObjectType<SituationMap::BuildingOutlineImpl>;
void SitMapUnitTest::checkIdContainer()
{
QVERIFY2((IdGeneratorCounting::getCounter() == 0), "Check IdGeneratorCounting, count failed");
// SituationMap::BuildingOutlineImpl bbbbbbbbb( QLatin1String("bio2") );
{
//
// ONE IdGenerator connected to TWO ObjectContainer:
//
QSharedPointer<SituationMap::IdGenerator> idGenerator(new IdGeneratorCounting());
QVERIFY2((idGenerator.isNull() == false), "Check IdGenerator does not exits");
QVERIFY2((IdGeneratorCounting::getCounter() == 1), "Check IdGeneratorCounting, count failed");
{
//
// FIRST ObjectContainer:
//
SituationMap::ObjectContainer *container1 =
new SituationMap::ObjectContainerCTC(idGenerator);
QVERIFY2((container1), "Check ObjectContainerCTC does not exits");
qlonglong count = container1->countObjects();
QVERIFY2((count == 0), "Check ObjectContainer countObjects failed");
// create some dummyObjects:
SituationMap::RefPointer<SituationMap::Participant> part1(new MyParticipantImpl(QLatin1String("part1")));
QVERIFY2(part1.valid() == true , "create part failed");
SituationMap::RefPointer<SituationMap::BiologicalAgent> bio1(new MyBiologicalAgentImpl(QLatin1String("bio1")));
QVERIFY2(bio1.valid() == true , "create failed");
SituationMap::RefPointer<SituationMap::BiologicalAgent> bio2(new MyBiologicalAgentImpl(QLatin1String("bio2")));
QVERIFY2(bio2.valid() == true , "create failed");
SituationMap::RefPointer<SituationMap::BuildingOutline> build1(new MyBuildingOutlineImpl(QLatin1String("build1")));
QVERIFY2(build1.valid() == true , "create failed");
SituationMap::RefPointer<SituationMap::BuildingOutline> build2(new MyBuildingOutlineImpl(QLatin1String("build2")));
QVERIFY2(build2.valid() == true , "create failed");
SituationMap::RefPointer<SituationMap::BuildingOutline> build3(new MyBuildingOutlineImpl(QLatin1String("build3")));
QVERIFY2(build3.valid() == true , "create failed");
SituationMap::UniqueMapId id = SituationMap::IdGenerator::INVALID_ID;
uint i = 0;
// add to our idContainer1:
id = container1->insertObject(part1.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container1->insertObject(bio1.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container1->insertObject(bio2.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container1->insertObject(build1.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container1->insertObject(build2.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container1->insertObject(build3.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
// std::cerr << " id=" << id << std::endl;
// check countObjects
count = container1->countObjects();
QVERIFY2((count == 6), "Check IdContainer countObjects failed");
// cleanup
delete container1;
}
//
// Instantiate SECOND IdContainer with SAME IdGenerator:
//
SituationMap::ObjectContainer *container2 = new SituationMap::ObjectContainerCTC(idGenerator);
// idGenerator is reused, IdGeneratorCounting::getCounter() must stay at '1':
QVERIFY2((IdGeneratorCounting::getCounter() == 1), "Check IdGeneratorCounting, count failed");
qint32 count = container2->countObjects();
QVERIFY2((count == 0), "Check IdContainer countObjects failed");
// create some dummyObjects:
SituationMap::RefPointer<SituationMap::Participant> part1(new MyParticipantImpl(QLatin1String("part1")));
QVERIFY2(part1.valid() == true , "create part failed");
SituationMap::RefPointer<SituationMap::BiologicalAgent> bio1(new MyBiologicalAgentImpl(QLatin1String("bio1")));
QVERIFY2(bio1.valid() == true , "create failed");
SituationMap::RefPointer<SituationMap::BiologicalAgent> bio2(new MyBiologicalAgentImpl(QLatin1String("bio2")));
QVERIFY2(bio2.valid() == true , "create failed");
SituationMap::UniqueMapId id = SituationMap::IdGenerator::INVALID_ID;
// add to our idContainer2:
// idGenerator is reused and therefore the uniqueId will continue -> start with '6'
uint i = 6;
id = container2->insertObject(part1.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container2->insertObject(bio1.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
id = container2->insertObject(bio2.get());
QVERIFY2((id == i++), "Check IdContainer wrong id");
count = container2->countObjects();
QVERIFY2((count == 3), "Check IdContainer countObjects failed");
// check access methods:
QList<SituationMap::UniqueMapId> keyList = container2->getAllKeys();
QVERIFY2((keyList.count() == 3), "Check IdContainer getAllKeys failed");
QList<SituationMap::ObjectContainer::Object *> objList = container2->getAllObjects();
QVERIFY2((objList.count() == 3), "Check IdContainer getAllObjects failed");
// SitMapUnitTest: look for BiologicalAgentIMPL
// ^^^^^^^^ ^^^^
// std::type_index bioTypeIndex(typeid(SituationMap::BiologicalAgentImpl));
std::type_index bioTypeIndex(typeid(MyBiologicalAgentImpl)); // use 'MyBiologicalAgentImpl' instead of 'SituationMap::BiologicalAgentImpl' - see insertion
objList = container2->getAllObjects(bioTypeIndex);
QVERIFY2((objList.count() == 2), "Check IdContainer getAllObjects(bioTypeIndex) failed");
SituationMap::ObjectContainer::Object *access = container2->getObject(-2) ;
QVERIFY2((!access), "Check IdContainer getObject failed");
access = container2->getObject(7) ;
QVERIFY2((access), "Check IdContainer getObject failed");
// remove
bool success = container2->removeObject(7);
QVERIFY2((success), "Check IdContainer remove failed");
count = container2->countObjects();
QVERIFY2((count == 2), "Check IdContainer countObjects failed");
// clear:
container2->clear();
count = container2->countObjects();
QVERIFY2((count == 0), "Check IdContainer countObjects failed");
// cleanup;
delete container2;
}
QVERIFY2((IdGeneratorCounting::getCounter() == 0), "Check IdGeneratorCounting, count failed");
}
void SitMapUnitTest::checkIsSignalConnected()
{
{
CheckSignal cs;
connect(&cs, &CheckSignal::mySignal, this, &SitMapUnitTest::onCheckIsSignalConnected);
quint64 msec = 0;
bool isConnected = cs.isConnected(msec);
INFO_LOG(m_logger) << LOGFUNCTION << " isSignalConnected took " << msec << "[msec]";
QVERIFY2(isConnected, "isSignalConnected failed (real slot)");
}
{
CheckSignal cs;
connect(&cs, &CheckSignal::mySignal, this, [ = ]()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " mySignal recognized (lambda slot)";
});
quint64 msec = 0;
bool isConnected = cs.isConnected(msec);
INFO_LOG(m_logger) << LOGFUNCTION << " isSignalConnected took " << msec << "[msec]";
QVERIFY2(isConnected, "isSignalConnected failed (lambda slot)");
}
}
void SitMapUnitTest::onCheckIsSignalConnected()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " mySignal recognized (real slot)";
}
void SitMapUnitTest::checkMapLayer()
{
SituationMap::MapLayer first;
QVERIFY2(first.isValid() == false, "MapLayer1 isValid failed");
SituationMap::MapLayer second(QLatin1String("LayerName"),
SituationMap::LayerType::Basemap);
QVERIFY2(second.isValid() == true, "MapLayer2 isValid failed");
}
void SitMapUnitTest::checkMapLayerOrderedList()
{
SituationMap::MapLayerOrderedList mlol;
QVERIFY2(mlol.count() == 0, "MapLayerOrderedList count failed");
bool success = false;
// add, check LayerType::Undefined
success = mlol.addLayer(QLatin1String("Basemap1"), SituationMap::LayerType::Undefined);
QVERIFY2(success == false, "MapLayerOrderedList: addLayer LayerType::Undefined failed");
QVERIFY2(mlol.count() == 0, "MapLayerOrderedList count failed");
// add, check emptyName
success = mlol.addLayer(QString(), SituationMap::LayerType::Basemap);
QVERIFY2(success == false, "MapLayerOrderedList: addLayer LayerType::Undefined failed");
QVERIFY2(mlol.count() == 0, "MapLayerOrderedList count failed");
// add, check emptyName
success = mlol.addLayer(QString(), SituationMap::LayerType::Operational);
QVERIFY2(success == false, "MapLayerOrderedList: addLayer LayerType::Undefined failed");
QVERIFY2(mlol.count() == 0, "MapLayerOrderedList count failed");
//
// add first
//
success = mlol.addLayer(QLatin1String("Basemap1"), SituationMap::LayerType::Basemap);
QVERIFY2(success, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 1, "MapLayerOrderedList count failed");
// add again:
success = mlol.addLayer(QLatin1String("Basemap1"), SituationMap::LayerType::Basemap);
QVERIFY2(success == false, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 1, "MapLayerOrderedList count failed");
// add again:
success = mlol.addLayer(QLatin1String("Basemap2"), SituationMap::LayerType::Basemap);
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 2, "MapLayerOrderedList count failed");
// add again (same name, different LayerType is not allowed)
success = mlol.addLayer(QLatin1String("Basemap2"), SituationMap::LayerType::Operational);
QVERIFY2(success == false, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 2, "MapLayerOrderedList count failed");
// add again:
success = mlol.addLayer(QLatin1String("ObjectLayer3"), SituationMap::LayerType::Operational);
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 3, "MapLayerOrderedList count failed");
// add again:
success = mlol.addLayer(QLatin1String("EmergencyCall"), SituationMap::LayerType::EmergencyCall);
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 4, "MapLayerOrderedList count failed");
//
// contains
//
success = mlol.contains(QLatin1String("Basemap1"), SituationMap::LayerType::Undefined);
QVERIFY2(success == true, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("Basemap1"), SituationMap::LayerType::Basemap);
QVERIFY2(success == true, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("Basemap1"), SituationMap::LayerType::Operational);
QVERIFY2(success == false, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("ObjectLayer3"), SituationMap::LayerType::Undefined);
QVERIFY2(success == true, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("ObjectLayer3"), SituationMap::LayerType::Basemap);
QVERIFY2(success == false, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("ObjectLayer3"), SituationMap::LayerType::Operational);
QVERIFY2(success == true, "MapLayerOrderedList: contains failed");
success = mlol.contains(QLatin1String("EmergencyCall"), SituationMap::LayerType::EmergencyCall);
QVERIFY2(success == true, "MapLayerOrderedList: contains failed");
//
// getLayer
//
SituationMap::MapLayer mapLayer;
mapLayer = mlol.getLayer(QLatin1String("Basemap1"));
QVERIFY2(mapLayer.isValid() == true , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.type() == SituationMap::LayerType::Basemap , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.name().compare(QLatin1String("Basemap1")) == 0 , "MapLayerOrderedList: getLayer failed");
mapLayer = mlol.getLayer(QLatin1String("Basemap2"));
QVERIFY2(mapLayer.isValid() == true , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.type() == SituationMap::LayerType::Basemap , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.name().compare(QLatin1String("Basemap2")) == 0 , "MapLayerOrderedList: getLayer failed");
mapLayer = mlol.getLayer(QLatin1String("ObjectLayer3"));
QVERIFY2(mapLayer.isValid() == true , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.type() == SituationMap::LayerType::Operational , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.name().compare(QLatin1String("ObjectLayer3")) == 0 , "MapLayerOrderedList: getLayer failed");
mapLayer = mlol.getLayer(QLatin1String("EmergencyCall"));
QVERIFY2(mapLayer.isValid() == true , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.type() == SituationMap::LayerType::EmergencyCall , "MapLayerOrderedList: getLayer failed");
QVERIFY2(mapLayer.name().compare(QLatin1String("EmergencyCall")) == 0 , "MapLayerOrderedList: getLayer failed");
//
// layerNamesOrdered
//
QStringList slBase; slBase << QLatin1String("Basemap1") << QLatin1String("Basemap2");
QStringList slObj; slObj << QLatin1String("ObjectLayer3");
QStringList slEmer; slEmer << QLatin1String("EmergencyCall");
QStringList sl;
sl = mlol.layerNamesOrdered(SituationMap::LayerType::Basemap);
QVERIFY2(sl == slBase , "MapLayerOrderedList: layerNamesOrdered failed");
sl = mlol.layerNamesOrdered(SituationMap::LayerType::Operational);
QVERIFY2(sl == slObj , "MapLayerOrderedList: layerNamesOrdered failed");
sl = mlol.layerNamesOrdered(SituationMap::LayerType::EmergencyCall);
QVERIFY2(sl == slEmer, "MapLayerOrderedList: layerNamesOrdered failed");
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slBase + slObj + slEmer , "MapLayerOrderedList: layerNamesOrdered failed");
qDebug() << "layer11=" << mlol.layerNamesOrdered();
//
// addBasemap
//
success = mlol.addLayer(QLatin1String("newBasemapLayer"), SituationMap::LayerType::Basemap);
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 5, "MapLayerOrderedList count failed");
QStringList slOk = slBase;
slOk << QLatin1String("newBasemapLayer");
slOk << slObj << slEmer;
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slOk , "MapLayerOrderedList: layerNamesOrdered failed");
qDebug() << "layer22=" << mlol.layerNamesOrdered();
success = mlol.addLayer(QLatin1String("newObjectLayer"), SituationMap::LayerType::Operational);
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 6, "MapLayerOrderedList count failed");
slOk << QLatin1String("newObjectLayer");
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slOk , "MapLayerOrderedList: layerNamesOrdered failed");
success = mlol.addLayer(QLatin1String("newBasemapLayer2"), SituationMap::LayerType::Basemap);
qDebug() << "layer33=" << mlol.layerNamesOrdered();
QVERIFY2(success == true, "MapLayerOrderedList: addLayer failed");
QVERIFY2(mlol.count() == 7, "MapLayerOrderedList count failed");
slOk.insert(3, QLatin1String("newBasemapLayer2"));
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slOk , "MapLayerOrderedList: layerNamesOrdered failed");
QVERIFY2(mlol.layerNamesOrdered(SituationMap::LayerType::Basemap).size() == 4 , "MapLayerOrderedList: layerNamesOrdered failed");
QVERIFY2(mlol.layerNamesOrdered(SituationMap::LayerType::Operational).size() == 2 , "MapLayerOrderedList: layerNamesOrdered failed");
qDebug() << "layer44=" << mlol.layerNamesOrdered();
//
// orderTo
//
QStringList newOrder;
newOrder << QLatin1String("Basemap1")
<< QLatin1String("newObjectLayer")
<< QLatin1String("newBasemapLayer2")
<< QLatin1String("ObjectLayer3")
<< QLatin1String("newBasemapLayer")
<< QLatin1String("EmergencyCall") // <-- must be moved on top
<< QLatin1String("Basemap2")
;
success = mlol.orderLayerTo(newOrder);
QVERIFY2(success == true, "MapLayerOrderedList: orderLayerTo failed");
slOk.clear();
slOk << QLatin1String("Basemap1")
<< QLatin1String("newBasemapLayer2")
<< QLatin1String("newBasemapLayer")
<< QLatin1String("Basemap2")
<< QLatin1String("newObjectLayer")
<< QLatin1String("ObjectLayer3")
<< QLatin1String("EmergencyCall")
;
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slOk , "MapLayerOrderedList: orderLayerTo failed");
qDebug() << "layer55=" << mlol.layerNamesOrdered();
//
// orderTo with missing 'EmergencyCall'
//
{
QStringList newOrder;
newOrder << QLatin1String("Basemap1")
<< QLatin1String("newObjectLayer")
<< QLatin1String("newBasemapLayer2")
<< QLatin1String("ObjectLayer3")
<< QLatin1String("newBasemapLayer")
// << QLatin1String("EmergencyCall") // <-- must be moved on top, even if not provided!
<< QLatin1String("Basemap2")
;
success = mlol.orderLayerTo(newOrder);
QVERIFY2(success == true, "MapLayerOrderedList: orderLayerTo failed");
slOk.clear();
slOk << QLatin1String("Basemap1")
<< QLatin1String("newBasemapLayer2")
<< QLatin1String("newBasemapLayer")
<< QLatin1String("Basemap2")
<< QLatin1String("newObjectLayer")
<< QLatin1String("ObjectLayer3")
<< QLatin1String("EmergencyCall")
;
sl = mlol.layerNamesOrdered();
QVERIFY2(sl == slOk , "MapLayerOrderedList: orderLayerTo failed");
}
qDebug() << "layer66=" << mlol.layerNamesOrdered();
// take EmergencyCall into account:
}
void SitMapUnitTest::checkLayerFactory()
{
// Preperations:
bool success = false;
SituationMap::MapImpl mapImplDummy;
QVERIFY2(mapImplDummy.technicalLayerCount() == 0 , "layerFactory: technicalLayerCount failed");
SituationMap::LayerFactory &layerFac = mapImplDummy.layerFactory();
// real test
QVERIFY2(layerFac.layernames().count() == 0 , "layerFactory: creation failed");
QVERIFY2(layerFac.count() == 0 , "layerFactory: creation failed");
SituationMap::LayerParameter lp;
success = layerFac.setLayerParameter(QLatin1String("test"), lp);
QVERIFY2(success == false , "layerFactory: setLayerParameter failed");
// #layer == 0
QVERIFY2(layerFac.layernames().count() == 0 , "layerFactory: count failed");
QVERIFY2(layerFac.count() == 0 , "layerFactory: count failed");
QVERIFY2(mapImplDummy.technicalLayerCount() == 0 , "layerFactory: technicalLayerCount failed");
QVERIFY2(layerFac.layernames(SituationMap::LayerType::Basemap) .count() == 0 , "layerFactory: layernames failed");
QVERIFY2(layerFac.layernames(SituationMap::LayerType::Operational).count() == 0 , "layerFactory: layernames failed");
QVERIFY2(layerFac.layernames(SituationMap::LayerType::Rubberband) .count() == 0 , "layerFactory: layernames failed");
}
class MyMapImpl : public SituationMap::MapImpl
{
Q_OBJECT // -> include "unit_test.moc" explicit
public:
bool isReady() const override
{
return true;
}
};
void SitMapUnitTest::checkObjectFactory()
{
// Preperations:
MyMapImpl mapImplDummy;
mapImplDummy.init(SituationMap::Mode::Mode_2D); // to create MpaGraphicsView and m_graphicsOverlayListModel
SituationMap::LayerFactory &layerFac = mapImplDummy.layerFactory();
QVERIFY2(layerFac.count() == 0 , "layerFactory: count failed");
layerFac.initializeUnitTestLayer();
SituationMap::ObjectFactory &objFac = mapImplDummy.objectFactory();
std::cerr << " count " << objFac.count() << std::endl;
QVERIFY2(objFac.count() <= 0 , "objectFactory: count failed"); // IdHandler -> 0 ; IDContainer -> -1
QVERIFY2(layerFac.count() == 3 , "layerFac: count failed");
// use an LOGICAL layer (not basemap)
QStringList layernames = layerFac.layernames();
QString layername = layernames[1];
// real test
// ObjectFactory::registerMe not called yet:
SituationMap::RefPointer<SituationMap::Participant> objPtr1;
objPtr1 = objFac.create<SituationMap::Participant>(layername, QLatin1String("UnitTestId1"));
QVERIFY2(objPtr1.valid() == false , "objectFactory: create1 failed");
SituationMap::RefPointer<SituationMap::BiologicalAgent> objPtr2;
objPtr2 = objFac.create<SituationMap::BiologicalAgent>(layername, QLatin1String("UnitTestId2"));
QVERIFY2(objPtr2.valid() == false , "objectFactory: create2 failed");
SituationMap::RefPointer<SituationMap::BuildingOutline> objPtr3;
objPtr3 = objFac.create<SituationMap::BuildingOutline>(layername, QLatin1String("UnitTestId3"));
QVERIFY2(objPtr3.valid() == false , "objectFactory: create3 failed");
SituationMap::RefPointer<SituationMap::DangerArea> objPtr4;
objPtr4 = objFac.create<SituationMap::DangerArea>(layername, QLatin1String("UnitTestId4"));
QVERIFY2(objPtr4.valid() == false , "objectFactory: create4 failed");
QVERIFY2(layerFac.count() == 3 , "layerFactory: count failed");
QVERIFY2(mapImplDummy.technicalLayerCount() == 1 , "layerFactory: technicalLayerCount failed");
// ObjectFactory::registerMe
SituationMap::ObjectFactory::registerMe(typeid(SituationMap::Participant), new SituationMap::GenericObjectFactory<SituationMap::ParticipantImpl>());
SituationMap::ObjectFactory::registerMe(typeid(SituationMap::BiologicalAgent), new SituationMap::GenericObjectFactory<SituationMap::BiologicalAgentImpl>());
SituationMap::ObjectFactory::registerMe(typeid(SituationMap::BuildingOutline), new SituationMap::GenericObjectFactory<SituationMap::BuildingOutlineImpl>());
SituationMap::ObjectFactory::registerMe(typeid(SituationMap::DangerArea), new SituationMap::GenericObjectFactory<SituationMap::DangerAreaImpl>());
QVERIFY2(objFac.count() == 0 , "objectFactory: count failed");
// now technicalLayerCount == 1 (basemap)
QVERIFY2(mapImplDummy.technicalLayerCount() == 1 , "layerFactory: technicalLayerCount failed");
objPtr1 = objFac.create<SituationMap::Participant>(layername, QLatin1String("UnitTestId1"));
QVERIFY2(objPtr1.valid() == true , "objectFactory: create11 failed");
objPtr2 = objFac.create<SituationMap::BiologicalAgent>(layername, QLatin1String("UnitTestId2"));
QVERIFY2(objPtr2.valid() == true , "objectFactory: create22 failed");
objPtr3 = objFac.create<SituationMap::BuildingOutline>(layername, QLatin1String("UnitTestId3"));
QVERIFY2(objPtr3.valid() == true , "objectFactory: create33 failed");
objPtr4 = objFac.create<SituationMap::DangerArea>(layername, QLatin1String("UnitTestId4"));
QVERIFY2(objPtr4.valid() == true , "objectFactory: create44 failed");
QVERIFY2(objFac.count() == 4 , "objectFactory: count failed");
// now technicalLayerCount == 1 (basemap, layername#...)
QVERIFY2(mapImplDummy.technicalLayerCount() == 2 , "layerFactory: technicalLayerCount failed");
// check rubberbandLayer:
// method 'rubberbandLayer' is not available at the interface:
SituationMap::LayerFactoryImpl *layerFacImpl =
dynamic_cast<SituationMap::LayerFactoryImpl *>(&layerFac);
QVERIFY2(layerFacImpl , "layerFac: dynamic_cast failed");
const QString &rbLayerName = layerFacImpl->rubberbandLayer();
QVERIFY2(rbLayerName.isEmpty() == false , "layerFac: rubberbandLayer failed");
objPtr2 = objFac.create<SituationMap::BiologicalAgent>(rbLayerName, QLatin1String("RbLayerTestId1"));
QVERIFY2(objPtr2.valid() == true , "objectFactory: create111 failed");
// now technicalLayerCount == 1 (basemap, layername#..., RubberbandLayer#...)
QVERIFY2(mapImplDummy.technicalLayerCount() == 3 , "layerFactory: technicalLayerCount failed");
const QString &toolLayerName = layerFacImpl->toolLayer();
QVERIFY2(toolLayerName.isEmpty() == false , "layerFac: toolLayer failed");
objPtr3 = objFac.create<SituationMap::BuildingOutline>(toolLayerName, QLatin1String("ToolLayerTestId1"));
QVERIFY2(objPtr3.valid() == true , "objectFactory: create222 failed");
if (objPtr1.valid())
{
// test re-use an uniqueId
SituationMap::UniqueMapId uid = objPtr1->uniqueMapId();
objPtr1->removeMySelf();
objPtr1 = objFac.create<SituationMap::Participant>(uid,layername, QLatin1String("UnitTestRecreate"));
QVERIFY2(objPtr1.valid() == true, "objectFactory: re-create failed");
QVERIFY2(uid == objPtr1->uniqueMapId(), "objectFactory: re-used removed uniqueId failed");
}
//further test require GUI -> another UnitTest
}
void SitMapUnitTest::checkPickableOnInvalidUniqueMapId()
{
// Preperations:
SituationMap::MapImpl mapImplDummy;
SituationMap::LayerFactory &layerFac = mapImplDummy.layerFactory();
QVERIFY2(layerFac.count() == 0 , "LayerFactory: count failed");
// use an LOGICAL layer (not basemap)
QStringList layernames = layerFac.layernames();
// real test
SituationMap::LayerFactoryImpl *layerFacImpl =
dynamic_cast<SituationMap::LayerFactoryImpl *>(&layerFac);
QVERIFY2(layerFacImpl , "LayerFactory: layerFacImpl failed");
QSharedPointer<SituationMap::TacticalAppearance> tactApp
= QSharedPointer<SituationMap::TacticalAppearance> (
new SituationMap::TacticalAppearance(&mapImplDummy, QLatin1String("AES"), QLatin1String("debugIdUnitTest"))
);
QVERIFY2(tactApp.data() , "TacticalAppearance failed");
QVERIFY2(tactApp->uniqueMapId() == SituationMap::INVALID_MAP_ID , "uniqueMapId failed");
QVERIFY2(tactApp->pickable() == false , "pickable failed");
// must not succeed due to invalid uniqueMapId:
tactApp->setPickable(true); // must not succeed due to invalid uniqueMapId
QVERIFY2(tactApp->pickable() == false , "pickable failed");
}
void SitMapUnitTest::checkBoundingBox()
{
{
SituationMap::BoundingBox bbox(SituationMap::BoundingBox::ExtentType::Sim);
QVERIFY2(bbox.isValid() == false, "isValid failed");
}
{
SituationMap::BoundingBox bbox(SituationMap::BoundingBox::ExtentType::Pixel);
QVERIFY2(bbox.isValid() == false, "isValid failed");
}
const double zVal = 1.23456;
SituationMap::Point3D center(100, 1000, zVal);
double width = 20;
double height = 60;
SituationMap::BoundingBox bbox(SituationMap::BoundingBox::ExtentType::Sim,
center, width, height);
QVERIFY2(bbox.isValid() == true, "isValid failed");
QVERIFY2(bbox.extentType() == SituationMap::BoundingBox::ExtentType::Sim, "extentType failed");
QVERIFY2(bbox.center() == center, "center failed");
QVERIFY2(bbox.width() == width, "width failed");
QVERIFY2(bbox.height() == height, "height failed");
QVERIFY2(bbox.topLeft() == SituationMap::Point3D( 90, 1030, zVal), "topLeft failed");
QVERIFY2(bbox.topRight() == SituationMap::Point3D(110, 1030, zVal), "topLeft failed");
QVERIFY2(bbox.bottomLeft() == SituationMap::Point3D( 90, 970, zVal), "topLeft failed");
QVERIFY2(bbox.bottomRight() == SituationMap::Point3D(110, 970, zVal), "topLeft failed");
bbox.reset();
QVERIFY2(bbox.isValid() == false, "isValid failed");
QVERIFY2(bbox.extentType() == SituationMap::BoundingBox::ExtentType::Undefined, "extentType failed");
QVERIFY2(bbox.center().isNull() == true, "center failed");
QVERIFY2(bbox.width() < 0.001, "width failed");
QVERIFY2(bbox.height() < 0.001, "height failed");
}
void SitMapUnitTest::checkDistanceMeasurement()
{
Esri::ArcGISRuntime::SpatialReference sr = Esri::ArcGISRuntime::SpatialReference::wgs84();
Esri::ArcGISRuntime::Point p1 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00001 00001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
Esri::ArcGISRuntime::Point p2 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00011 00001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
QVERIFY2(p1.isEmpty() == false, "fromMgrs failed");
QVERIFY2(p1.spatialReference().wkid() == 4326, "spatialReference failed");
DEBUG_LOG(m_logger) << LOGFUNCTION << " p.x=" << p1.x() << " p.y=" << p1.y() << " p.z=" << p1.z()
<< " sr=" << p1.spatialReference().wkid();
//
// 1. checkDistanceMeasurement
//
const double distance =
Esri::ArcGISRuntime::GeometryEngine::distance(Esri::ArcGISRuntime::Point(p1.x(), p1.y(), sr),
Esri::ArcGISRuntime::Point(p2.x(), p2.y(), sr));
DEBUG_LOG(m_logger) << LOGFUNCTION << " GeometryEngine::distance() " << distance;
//
// 2. distanceGeodetic
//
const Esri::ArcGISRuntime::GeodeticDistanceResult geodeticDistance =
Esri::ArcGISRuntime::GeometryEngine::distanceGeodetic(Esri::ArcGISRuntime::Point(p1.x(), p1.y(), sr),
Esri::ArcGISRuntime::Point(p2.x(), p2.y(), sr),
Esri::ArcGISRuntime::LinearUnitId::Meters,
Esri::ArcGISRuntime::AngularUnitId::Degrees,
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
DEBUG_LOG(m_logger) << LOGFUNCTION << " GeometryEngine::distanceGeodetic() " << geodeticDistance.distance();
QVERIFY2(geodeticDistance.distance() -10.0 < 0.01, "distanceGeodetic failed");
// ====> use distanceGeodetic
}
void SitMapUnitTest::recalculateAngle()
{
// aus Transformationspunkte GUEZ, Stand 08/2018:
// (Werte sind EPSG-Code 31468)
// BN_94: x=4473185.721 ; y=5817742.350 ; Drehwinkel=149.3805
// Wir benötigen den Drehwinkel aber in Bezug auf EPSG-Code 32632.
const Esri::ArcGISRuntime::SpatialReference srcSr(31468);
const Esri::ArcGISRuntime::SpatialReference destSr(32632);
const QPointF srcPoint(4473185.721, 5817742.350); // BN_94
// const QPointF srcPoint(4472996.165, 5817720.809); // BN_152
const double srcAngleDegree = 149.3805;
// Ansatz:
// Einen zusätzlichen Hilfspunkt bestimmen (Winkel == 0.0),
// beiden Punkte in die Zielprojektion überführen,
// dann den Winkel zw. diesen projezierten Punkten bestimmen.
// Somit erhalten wir eine Differenz zum ursprünglichen Winkel
const double offset = 1.0; // meter
QPointF h1 = srcPoint;
QPointF h2 = srcPoint + QPointF(offset, 0.0); // nur x, damit Winkel 0.0 ist
qCritical() << " h1= " << h1;
qCritical() << " h2= " << h2;
// project:
Esri::ArcGISRuntime::Point esriH1 =
Esri::ArcGISRuntime::GeometryEngine::project(Esri::ArcGISRuntime::Point(h1.x(), h1.y(), 0.0, srcSr), destSr);
Esri::ArcGISRuntime::Point esriH2 =
Esri::ArcGISRuntime::GeometryEngine::project(Esri::ArcGISRuntime::Point(h2.x(), h2.y(), 0.0, srcSr), destSr);
// Winkel bestimmen:
double dX = esriH1.x() - esriH2.x();
double dY = esriH1.y() - esriH2.y();
double destAngleRad = atan(dY / dX);
double destAngleDeg = destAngleRad / M_PI * 180.0;
qCritical() << " destAngleRad= " << QString::number(destAngleRad, 'f', 6);
qCritical() << " destAngleDeg= " << QString::number(destAngleDeg, 'f', 6);
qCritical() << " srcAngle : " << QString::number(srcAngleDegree, 'f', 6);
qCritical() << " destAngle: " << QString::number(srcAngleDegree + destAngleDeg, 'f', 6);
}
void SitMapUnitTest::measureDistanceGeodetic()
{
Esri::ArcGISRuntime::SpatialReference sr = Esri::ArcGISRuntime::SpatialReference::wgs84();
Esri::ArcGISRuntime::Point p1 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00001 00001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
Esri::ArcGISRuntime::Point p2 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00011 00001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
int jMax = 1000;
QElapsedTimer timer;
timer.start();
for (int j = 0; j < jMax; ++j)
{
const Esri::ArcGISRuntime::GeodeticDistanceResult geodeticDistance =
Esri::ArcGISRuntime::GeometryEngine::distanceGeodetic(Esri::ArcGISRuntime::Point(p1.x(), p1.y(), sr),
Esri::ArcGISRuntime::Point(p2.x(), p2.y(), sr),
Esri::ArcGISRuntime::LinearUnitId::Meters,
Esri::ArcGISRuntime::AngularUnitId::Degrees,
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
if (geodeticDistance.distance() > 11)
qDebug() << " geodeticDistance: ";
}
qDebug() << " distanceGeodetic: " << jMax << " operations took " << timer.elapsed() << "ms";
}
void SitMapUnitTest::checkDensify()
{
// connect errorHandling:
connect(Esri::ArcGISRuntime::GeometryEngine::instance(), &Esri::ArcGISRuntime::GeometryEngine::errorOccurred,
this, [this](const Esri::ArcGISRuntime::Error &error)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " ---EsriError--- occured: " << error;
});
Esri::ArcGISRuntime::SpatialReference sr = Esri::ArcGISRuntime::SpatialReference::wgs84();
Esri::ArcGISRuntime::Point p1, p2;
//
// 1. densify
//
{
p1 = Esri::ArcGISRuntime::Point(8.0, 53.0, sr);
p2 = Esri::ArcGISRuntime::Point(9.0, 53.0, sr);
// create Polyline:
Esri::ArcGISRuntime::PolylineBuilder polylineBuilder(sr, this);
polylineBuilder.addPoint(p1);
polylineBuilder.addPoint(p2);
const Esri::ArcGISRuntime::Polyline &polylineIn = polylineBuilder.toPolyline();
const Esri::ArcGISRuntime::Geometry &geometryOut = Esri::ArcGISRuntime::GeometryEngine::densify(polylineIn, 0.1);
QVERIFY2(geometryOut.geometryType() == Esri::ArcGISRuntime::GeometryType::Polyline, "geometryType failed");
const Esri::ArcGISRuntime::Polyline polylineOut(geometryOut);
QVERIFY2(polylineOut.parts().size() == 1, "polylineOut.parts().size() failed");
qCritical() << "polylineOut.parts().part(0).pointCount() = " << polylineOut.parts().part(0).pointCount();
QVERIFY2(polylineOut.parts().part(0).pointCount() > 10, "polylineOut.parts().size() failed");
QVERIFY2(polylineOut.parts().part(0).pointCount() < 15, "polylineOut.parts().size() failed");
}
//
// 2. densifyGeodetic - ok?
//
{
p1 = Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00001 00001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
p2 = Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 00001 01001"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
// create Polyline:
Esri::ArcGISRuntime::PolylineBuilder polylineBuilder(sr, this);
polylineBuilder.addPoint(p1);
polylineBuilder.addPoint(p2);
const Esri::ArcGISRuntime::Polyline &polylineIn = polylineBuilder.toPolyline();
const Esri::ArcGISRuntime::Geometry &geometryOut = Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polylineIn,
100,
Esri::ArcGISRuntime::LinearUnit::meters(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
QVERIFY2(geometryOut.geometryType() == Esri::ArcGISRuntime::GeometryType::Polyline, "geometryType failed");
const Esri::ArcGISRuntime::Polyline polylineOut(geometryOut);
QVERIFY2(polylineOut.parts().size() == 1, "polylineOut.parts().size() failed");
qCritical() << "polylineOut.parts().part(0).pointCount() = " << polylineOut.parts().part(0).pointCount();
QVERIFY2(polylineOut.parts().part(0).pointCount() > 10, "polylineOut.parts().size() failed");
QVERIFY2(polylineOut.parts().part(0).pointCount() < 15, "polylineOut.parts().size() failed");
}
}
QPolygonF bufferUtmPolygon(const QPolygonF &polygonUtmIn, double distance, double maxDeviation = 1, QString *errorOut = nullptr)
{
Q_UNUSED(maxDeviation);
Esri::ArcGISRuntime::PolygonBuilder polygonBuilder(Esri::ArcGISRuntime::SpatialReference(32632));
for (const QPointF &pointUtm : std::as_const(polygonUtmIn))
polygonBuilder.addPoint(Esri::ArcGISRuntime::Point(pointUtm.x(), pointUtm.y(), 0));
const Esri::ArcGISRuntime::Geometry &esriGeometry = polygonBuilder.toGeometry();
const Esri::ArcGISRuntime::Polygon polyline =
Esri::ArcGISRuntime::GeometryEngine::buffer(esriGeometry, distance);
if (polyline.parts().isEmpty())
{
if (errorOut)
*errorOut = QStringLiteral("GeometryEngine::buffer failed (no parts");
return {};
}
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polyline.parts().part(0);
const int size = immutablePart.pointCount();
QPolygonF bufferedPoly;
bufferedPoly.reserve(size);
for (int i = 0; i < size; ++i)
{
const Esri::ArcGISRuntime::Point &esriP = immutablePart.point(i);
bufferedPoly.append(QPointF(esriP.x(), esriP.y()));
}
return bufferedPoly;
}
void SitMapUnitTest::checkBuffer()
{
// Für Gerlinde, Thema Gefährungsabstand
// Hier der Stellvertreter für das Wirkfeld:
QPolygonF wirkfeldPoly({ {0.0, 0.0}, {1000.0, 0.0}, {1000.0, 1000.0} });
NOTICE_LOG(m_logger) << LOGFUNCTION << " wirkfeldPoly.size = " << wirkfeldPoly.size();
for (auto item : std::as_const(wirkfeldPoly))
NOTICE_LOG(m_logger) << LOGFUNCTION << " wirkfeldPoly = " << item;
QString errorOut;
const QPolygonF &bufferedPoly = bufferUtmPolygon(wirkfeldPoly, 10, 1, &errorOut);
NOTICE_LOG(m_logger) << LOGFUNCTION << " bufferedPoly.size = " << bufferedPoly.size();
for (auto item : std::as_const(bufferedPoly))
NOTICE_LOG(m_logger) << LOGFUNCTION << " bufferedPoly = " << item;
}
void SitMapUnitTest::checkMovementTrack()
{
const Esri::ArcGISRuntime::SpatialReference &sr = Esri::ArcGISRuntime::SpatialReference::wgs84();
SituationMap::MovementTrack mt(4711);
bool success;
QVERIFY2(mt.size() == 0, "size failed");
QVERIFY2(mt.isActive() == true, "isActive failed");
QVERIFY2(mt.getTrack().size() == 0, "getTrack failed");
QVERIFY2(mt.getVisibleTrack(0, 999999, 999999).size() == 0, "getVisibleTrack failed");
Esri::ArcGISRuntime::Point eP1 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 10000 10000"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
SituationMap::Point3D p1(eP1.x()/180.0*M_PI, eP1.y()/180.0*M_PI, eP1.z()); // -> rad
success = mt.addPosition(p1, 1000, 1, 99999);
QVERIFY2(success, "success failed");
QVERIFY2(mt.size() == 1, "size failed");
QVERIFY2(mt.getTrack().size() == 1, "getTrack failed");
// check via maxViewAgeMsec (3rd)
QVERIFY2(mt.getVisibleTrack(2000, 999999, 999).size() == 0, "getVisibleTrack failed");
QVERIFY2(mt.getVisibleTrack(2000, 999999, 1000).size() == 1, "getVisibleTrack failed");
// check via maxAgeMsec (2rd)
QVERIFY2(mt.getTrack().size() == 1, "getTrack failed");
QVERIFY2(mt.getVisibleTrack(2000, 1000, 1000).size() == 1, "getVisibleTrack failed");
QVERIFY2(mt.getTrack().size() == 1, "getTrack failed");
QVERIFY2(mt.getVisibleTrack(2000, 999, 1000).size() == 0, "getVisibleTrack failed");
QVERIFY2(mt.getTrack().size() == 0, "getTrack failed");
Esri::ArcGISRuntime::Point eP2 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 10001 10000"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
SituationMap::Point3D p2(eP2.x()/180.0*M_PI, eP2.y()/180.0*M_PI, eP2.z()); // -> rad
Esri::ArcGISRuntime::Point eP3 =
Esri::ArcGISRuntime::CoordinateFormatter::fromMgrs(QLatin1String("32UMD 10010 10000"), sr, Esri::ArcGISRuntime::MgrsConversionMode::Automatic);
SituationMap::Point3D p3(eP3.x()/180.0*M_PI, eP3.y()/180.0*M_PI, eP3.z()); // -> rad
success = mt.addPosition(p1, 1000, 2, 99999);
QVERIFY2(success, "success failed addPosition");
QVERIFY2(mt.getTrack().size() == 1, "getTrack failed");
success = mt.addPosition(p2, 1100, 2, 99999); // p2 should NOT be added:
QVERIFY2(!success, "success failed addPosition");
QVERIFY2(mt.getTrack().size() == 1, "getTrack failed");
success = mt.addPosition(p3, 1100, 2, 99999); // p3 should be added:
QVERIFY2(success, "success failed addPosition");
QVERIFY2(mt.getTrack().size() == 2, "getTrack failed");
QJsonDocument jDoc(mt.toJsonObject());
{
// to json
// QFile saveFile(QStringLiteral("/tmp/mt.json"));
// if (!saveFile.open(QIODevice::WriteOnly)) {
// qWarning("Couldn't open mt file.");
// return;
// }
// saveFile.write(jDoc.toJson());
// qCritical() << "wrote " << QFileInfo(saveFile).absoluteFilePath();
// qCritical() << "mt.toJson()=" << jDoc.toJson();
}
{
// read json
const QJsonObject &objTemp = jDoc.object();
QSharedPointer<SituationMap::MovementTrack> newMt = SituationMap::MovementTrack::read(objTemp);
QVERIFY2(newMt->trackId() == mt.trackId(), " json: trackId failed");
QVERIFY2(newMt->isActive() == mt.isActive(), " json: isActive failed");
QVERIFY2(newMt->getTrack().size() == mt.getTrack().size(), " json: getTrack failed");
}
}
void SitMapUnitTest::checkMovementTrackManager()
{
SituationMap::MovementTrackManager mtMgr;
mtMgr.setCurrentTimeMsec(123);
QVERIFY2(mtMgr.currentTimeMsec() == 123, "currentTimeMsec failed");
mtMgr.setMaxAgeMsec(1234);
QVERIFY2(mtMgr.maxAgeMsec() == 1234, "maxAgeMsec failed");
mtMgr.setMaxViewAgeMsec(55);
QVERIFY2(mtMgr.maxViewAgeMsec() == 55, "maxViewAgeMsec failed");
mtMgr.setMaxNumberOfTracks(3);
QVERIFY2(mtMgr.maxNumberOfTracks() == 3, "maxNumberOfTracks failed");
mtMgr.setMaxNumberOfPointsPerTrack(5);
QVERIFY2(mtMgr.maxNumberOfPointsPerTrack() == 5, "maxNumberOfTracks failed");
mtMgr.setMinDistance(7);
QVERIFY2(mtMgr.minDistance() == 7, "minDistance failed");
bool success;
QVERIFY2(mtMgr.size() == 0, "size failed");
QVERIFY2(mtMgr.hasTrack(0) == false, "hasTrack failed");
QVERIFY2(mtMgr.activeTrackIds().size() == 0, "objectIdsOfActiveTracks failed");
QVERIFY2(mtMgr.activeAndVisibleTrack(0).size() == 0, "activeAndVisibleTrack failed");
// set some positions:
double lon = 0.155;
double lat = 0.926;
const SituationMap::Point3D p1(lon+0.000, lat, 0.0);
const SituationMap::Point3D p2(lon+0.001, lat, 0.0);
const SituationMap::Point3D p3(lon+0.002, lat, 0.0);
const SituationMap::Point3D p4(lon+0.003, lat, 0.0);
const SituationMap::Point3D p5(lon+0.004, lat, 0.0);
// check MaxNumberOfPointsPerTrack
{
QVERIFY2(mtMgr.maxNumberOfPointsPerTrack() == 5, "maxNumberOfTracks failed");
QVERIFY2(mtMgr.minDistance() == 7, "minDistance failed");
mtMgr.activateTrack(4711);
success = true;
success = success && mtMgr.addPosition(4711, p1, 10001);
success = success && mtMgr.addPosition(4711, p2, 10002);
success = success && mtMgr.addPosition(4711, p3, 10003);
success = success && mtMgr.addPosition(4711, p4, 10004);
success = success && mtMgr.addPosition(4711, p5, 10005);
success = success && mtMgr.addPosition(4711, p1, 10006); // maxNumberOfTracks exceeded -> pt1 removed
QVERIFY2(success == true, "addPosition failed");
QVERIFY2(mtMgr.activeAndVisibleTrack(4711).size() == 5, "activeAndVisibleTrack failed");
QVERIFY2(mtMgr.size() == 1, "size failed");
QVERIFY2(mtMgr.hasTrack(4711) == true, "hasTrack failed");
QVERIFY2(mtMgr.activeTrackIds().size() == 1, "objectIdsOfActiveTracks failed");
QVERIFY2(mtMgr.activeAndVisibleTrack(4711).size() == 5, "activeAndVisibleTrack failed");
}
// maxViewAgeMsec
{
int size = 0;
// a)
mtMgr.setCurrentTimeMsec(10006);
QVERIFY2(mtMgr.currentTimeMsec() == 10006, "currentTimeMsec failed");
mtMgr.setMaxViewAgeMsec(2);
size = mtMgr.activeAndVisibleTrack(4711).size();
QVERIFY2(size == 3, "activeAndVisibleTrack failed"); // 10006, 10005, 10004
// b) set currentTimeMsec forward
mtMgr.setCurrentTimeMsec(10008);
mtMgr.setMaxViewAgeMsec(2);
size = mtMgr.activeAndVisibleTrack(4711).size();
QVERIFY2(size == 1, "activeAndVisibleTrack failed"); // 10008, 10007, 10006
// c) set currentTimeMsec backward
mtMgr.setCurrentTimeMsec(10002);
size = mtMgr.activeAndVisibleTrack(4711).size();
QVERIFY2(size == 1, "activeAndVisibleTrack failed"); // 10002 (10001/pt1 removed)
}
// check removing of track, 1
{
QVERIFY2(mtMgr.maxNumberOfTracks() == 3, "maxNumberOfTracks failed");
mtMgr.activateTrack(4712);
QVERIFY2(mtMgr.addPosition(4712, p1, 10001) == true, "addPosition failed");
mtMgr.activateTrack(4713);
QVERIFY2(mtMgr.addPosition(4713, p1, 10001) == true, "addPosition failed");
QVERIFY2(mtMgr.size() == 3, "size failed");
QVERIFY2(mtMgr.activeTrackIds().size() == 3, "objectIdsOfActiveTracks failed");
mtMgr.activateTrack(4714);
QVERIFY2(mtMgr.addPosition(4714, p1, 10001) == true, "addPosition failed");
QVERIFY2(mtMgr.size() == 3, "size failed");
QVERIFY2(mtMgr.activeTrackIds().size() == 3, "objectIdsOfActiveTracks failed");
QVERIFY2(mtMgr.hasTrack(4711) == false, "hasTrack failed");
}
// check removing of track, 2
{
// 4712, 4713, 4714
const QVector<int> activeTracks1 = mtMgr.activeTrackIds();
QVERIFY2(activeTracks1 == QVector<int>() << 4712 << 4713 << 4714, "objectIdsOfActiveTracks failed");
mtMgr.deactivateTrack(4713);
// still 3 tracks, but just 2 active:
QVERIFY2(mtMgr.size() == 3, "size failed");
const QVector<int> activeTracks2 = mtMgr.activeTrackIds();
QVERIFY2(activeTracks2 == QVector<int>() << 4712 /*<< 4713*/ << 4714, "objectIdsOfActiveTracks failed");
// activate track 4715 -> deactived track 4713 has to be removed:
mtMgr.activateTrack(4715);
QVERIFY2(success == true, "addPosition failed");
QVERIFY2(mtMgr.size() == 3, "size failed");
// 4712, 4714, 4715
QVERIFY2(mtMgr.activeTrackIds().size() == 3, "objectIdsOfActiveTracks failed");
const QVector<int> activeTracks3 = mtMgr.activeTrackIds();
QVERIFY2(activeTracks3 == QVector<int>() << 4712 << 4714 << 4715, "objectIdsOfActiveTracks failed");
QVERIFY2(mtMgr.hasTrack(4711) == false, "hasTrack failed");
QVERIFY2(mtMgr.hasTrack(4712) == true, "hasTrack failed");
QVERIFY2(mtMgr.hasTrack(4713) == false, "hasTrack failed");
QVERIFY2(mtMgr.hasTrack(4714) == true, "hasTrack failed");
QVERIFY2(mtMgr.hasTrack(4715) == true, "hasTrack failed");
}
QVERIFY2(mtMgr.size() > 0, " json: size insufficiant");
const qint64 CURRENT_TIME_MSEC = 1516632216.0 * 1000.0; // to use qint64
mtMgr.setCurrentTimeMsec(CURRENT_TIME_MSEC);
QJsonDocument jDoc(mtMgr.toJsonObject());
{
// to json
QFile saveFile(QStringLiteral("/tmp/mtMgr.json"));
if (!saveFile.open(QIODevice::WriteOnly)) {
qWarning("Couldn't open mt file.");
return;
}
saveFile.write(jDoc.toJson());
qCritical() << "wrote " << QFileInfo(saveFile).absoluteFilePath();
qCritical() << "mtMgr.toJson()=" << jDoc.toJson();
}
{
// read json
SituationMap::MovementTrackManager newMtMgr;
const QJsonObject &objTemp = jDoc.object();
newMtMgr.read(objTemp);
QVERIFY2(newMtMgr.size() > 0, " json: size failed");
QVERIFY2(newMtMgr.size() == mtMgr.size(), " json: size failed");
qint64 diff;
diff = mtMgr.currentTimeMsec() - CURRENT_TIME_MSEC;
QVERIFY2(qFuzzyIsNull(double(diff)) == true, " json: maxAgeMsec failed");
diff = newMtMgr.currentTimeMsec() - CURRENT_TIME_MSEC;
QVERIFY2(qFuzzyIsNull(double(diff)) == true, " json: maxAgeMsec failed");
diff = newMtMgr.maxAgeMsec() - mtMgr.maxAgeMsec();
QVERIFY2(qFuzzyIsNull(double(diff)) == true, " json: maxAgeMsec failed");
diff = newMtMgr.maxViewAgeMsec() - mtMgr.maxViewAgeMsec();
QVERIFY2(qFuzzyIsNull(double(diff)) == true, " json: maxViewAgeMsec failed");
QVERIFY2(newMtMgr.maxNumberOfTracks() == mtMgr.maxNumberOfTracks(), " json: maxNumberOfTracks failed");
QVERIFY2(newMtMgr.maxNumberOfPointsPerTrack() == mtMgr.maxNumberOfPointsPerTrack(), " json: maxNumberOfPointsPerTrack failed");
QVERIFY2(newMtMgr.minDistance() == mtMgr.minDistance(), " json: minDistance failed");
const QVector<int> &activeTrackIds = newMtMgr.activeTrackIds();
for (const auto &trackId : activeTrackIds)
QVERIFY2(newMtMgr.activeAndVisibleTrack(trackId).size() == mtMgr.activeAndVisibleTrack(trackId).size(), " json: activeAndVisibleTrack failed");
}
}
void checkSidcCodecEncoded(const QString &sidc,
const QString &rawSidc,
AdvancedSymbology::SymbologyType symType,
AdvancedSymbology::SidcCodec::SidcType sidcType)
{
QVERIFY2(AdvancedSymbology::SidcCodec::isEncoded(sidc) == true, "isEncoded");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeSymbologyType(sidc) == symType, "decodeSymbologyType");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeSidcType(sidc) == sidcType, "decodeSidcType");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeRawSidc(sidc).compare(rawSidc) == 0, "decodeRawSidc");
}
void SitMapUnitTest::checkSidcCodec()
{
// M25D|CMPL|10012500002713000000
{
{
QString sidc;
sidc = QLatin1String("AP6B|CMPL|10012500002713000000");
checkSidcCodecEncoded(sidc, QLatin1String("10012500002713000000"), AdvancedSymbology::SymbologyType::APP6B, AdvancedSymbology::SidcCodec::SidcType::Complete);
sidc = QLatin1String("AP6D|CMPL|10012500002713000000");
checkSidcCodecEncoded(sidc, QLatin1String("10012500002713000000"), AdvancedSymbology::SymbologyType::APP6D, AdvancedSymbology::SidcCodec::SidcType::Complete);
sidc = QLatin1String("M25C|CMPL|10012500002713000000");
checkSidcCodecEncoded(sidc, QLatin1String("10012500002713000000"), AdvancedSymbology::SymbologyType::MIL2525C, AdvancedSymbology::SidcCodec::SidcType::Complete);
sidc = QLatin1String("M25D|CMPL|10012500002713000000");
checkSidcCodecEncoded(sidc, QLatin1String("10012500002713000000"), AdvancedSymbology::SymbologyType::MIL2525D, AdvancedSymbology::SidcCodec::SidcType::Complete);
}
{
QString temp;
temp = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(AdvancedSymbology::SymbologyType::APP6B, QLatin1String("25271300"));
QVERIFY2(temp.compare(QLatin1String("AP6B|BASE|25271300")) == 0, "encodeBaseSymbolCode");
temp = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(AdvancedSymbology::SymbologyType::APP6D, QLatin1String("25271300"));
QVERIFY2(temp.compare(QLatin1String("AP6D|BASE|25271300")) == 0, "encodeBaseSymbolCode");
temp = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(AdvancedSymbology::SymbologyType::MIL2525C, QLatin1String("25271300"));
QVERIFY2(temp.compare(QLatin1String("M25C|BASE|25271300")) == 0, "encodeBaseSymbolCode");
temp = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(AdvancedSymbology::SymbologyType::MIL2525D, QLatin1String("25271300"));
QVERIFY2(temp.compare(QLatin1String("M25D|BASE|25271300")) == 0, "encodeBaseSymbolCode");
temp = AdvancedSymbology::SidcCodec::encodeComplete(AdvancedSymbology::SymbologyType::MIL2525D, QLatin1String("10012500002713000000"));
QVERIFY2(temp.compare(QLatin1String("M25D|CMPL|10012500002713000000")) == 0, "encodeComplete");
}
}
// Fehlerfälle
{
QString sidc = QLatin1String("10012500002713000000");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeSymbologyType(sidc) == AdvancedSymbology::SymbologyType::None, "decodeSymbologyType");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeSidcType(sidc) == AdvancedSymbology::SidcCodec::SidcType::None, "decodeSidcType");
QVERIFY2(AdvancedSymbology::SidcCodec::decodeRawSidc(sidc).compare(sidc) == 0, "decodeRawSidc");
}
}
void SitMapUnitTest::checkSIDCDefinitions1()
{
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
return;
AdvancedSymbology::SymbolDictionary &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
QSignalSpy spy(&dict, &AdvancedSymbology::SymbolDictionary::loaded);
if(dict.isLoaded() == false)
{
dict.load();
if (spy.count() == 0)
spy.wait(10000);
}
QVERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
// real work:
bool success;
AdvancedSymbology::SidcDefinitions::StandardIdentity standardIdentity;
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::Pending == 0 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::Unknown == 1 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::AssumedFriend == 2 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::Friend == 3 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::Neutral == 4 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::SuspectJoker == 5 , "Identity emumValue wrong");
QVERIFY2((int)AdvancedSymbology::SidcDefinitions::Identity::HostileFaker == 6 , "Identity emumValue wrong");
// to be continued...
const QVector<AdvancedSymbology::SymbologyType> &supportedSmTypes = { AdvancedSymbology::SymbologyType::MIL2525D, AdvancedSymbology::SymbologyType::APP6D};
if (supportedSmTypes.contains(m_d->m_symbologyType))
{
QString baseSymbolCode = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(m_d->m_symbologyType, "25270100");
AdvancedSymbology::SidcBuilder sidcBuilder(&dict);
success = sidcBuilder.initFromSymbologyTypeBaseSymbolCode(m_d->m_symbologyType, baseSymbolCode);
QVERIFY2(success == true , "initFromSymbologyTypeBaseSymbolCode failed");
const QString &sidc = sidcBuilder.toSidc();
qCritical() << "sidc=" << sidc;
// 12345678901234567890
// 25 270100 // baseSymbolCode (SymbolSet + Entity)
const QString &rawSidc = AdvancedSymbology::SidcCodec::decodeRawSidc(sidc);
QVERIFY2(rawSidc.compare(QLatin1String("10012500002701000000")) == 0 , "initFromMil2525DBaseSymbolCode failed");
}
//
// test some arbitrary sidc (MIL2525D):
//
if (supportedSmTypes.contains(m_d->m_symbologyType))
{
// 1234567890
QString sidcSTR = AdvancedSymbology::SidcCodec::encodeComplete(m_d->m_symbologyType, "10051000001213030000"); // MIL2525D: 01011000001213030000 -> LandUnits, Observer, Motorized
qDebug() << "----------- " << sidcSTR;
AdvancedSymbology::SidcBuilder sidcBuilder(&dict);
success = sidcBuilder.initFromSymbologyType(m_d->m_symbologyType, sidcSTR);
QVERIFY2(success == true , "initFromSymbologyTypeBaseSymbolCode failed");
// First10
standardIdentity = sidcBuilder.standardIdentity();
QVERIFY2(standardIdentity.context == AdvancedSymbology::SidcDefinitions::Context::Reality , "standardIdentity.context failed");
QVERIFY2(standardIdentity.identity == AdvancedSymbology::SidcDefinitions::Identity::SuspectJoker , "standardIdentity.identity failed");
AdvancedSymbology::SidcDefinitions::SymbolSet symSet = sidcBuilder.symbolSet();
QVERIFY2(symSet == AdvancedSymbology::SidcDefinitions::SymbolSet::LandUnit, "symbolSet failed");
AdvancedSymbology::SidcDefinitions::Status status = sidcBuilder.status();
QVERIFY2(status == AdvancedSymbology::SidcDefinitions::Status::Present, "status failed");
QVERIFY2(sidcBuilder.headquarters() == false , "headquarters failed");
QVERIFY2(sidcBuilder.taskForce() == false , "taskForce failed");
QVERIFY2(sidcBuilder.feintDummy() == false , "feintDummy failed");
AdvancedSymbology::SidcDefinitions::AmplifierGroup amplGroup = sidcBuilder.amplifierGroup();
QVERIFY2(amplGroup == AdvancedSymbology::SidcDefinitions::AmplifierGroup::Unknown , "amplifierGroup failed");
int amplSub = sidcBuilder.amplifier2ndDigit();
QVERIFY2(amplSub == 0 , "amplifierSecondDigit failed");
// Second10
}
if (supportedSmTypes.contains(m_d->m_symbologyType))
{
// 1234567890
QString sidcSTR = AdvancedSymbology::SidcCodec::encodeComplete(m_d->m_symbologyType, "10012547231213030000");
qDebug() << "----------- " << sidcSTR;
AdvancedSymbology::SidcBuilder sidcBuilder(&dict);
success = sidcBuilder.initFromSymbologyType(m_d->m_symbologyType, sidcSTR);
QVERIFY2(success == true , "initFromSymbologyType failed");
// First10
standardIdentity = sidcBuilder.standardIdentity();
QVERIFY2(standardIdentity.context == AdvancedSymbology::SidcDefinitions::Context::Reality , "standardIdentity.context failed");
QVERIFY2(standardIdentity.identity == AdvancedSymbology::SidcDefinitions::Identity::Unknown , "standardIdentity.identity failed");
AdvancedSymbology::SidcDefinitions::SymbolSet symSet = sidcBuilder.symbolSet();
QVERIFY2(symSet == AdvancedSymbology::SidcDefinitions::SymbolSet::ControlMeasure, "symbolSet failed");
AdvancedSymbology::SidcDefinitions::Status status = sidcBuilder.status();
QVERIFY2(status == AdvancedSymbology::SidcDefinitions::Status::Present_Destroyed, "status failed");
QVERIFY2(sidcBuilder.headquarters() == true , "headquarters failed");
QVERIFY2(sidcBuilder.taskForce() == true , "taskForce failed");
QVERIFY2(sidcBuilder.feintDummy() == true , "feintDummy failed");
AdvancedSymbology::SidcDefinitions::AmplifierGroup amplGroup = sidcBuilder.amplifierGroup();
QVERIFY2(amplGroup == AdvancedSymbology::SidcDefinitions::AmplifierGroup::Echelon_DivisionAndAbove , "amplifierGroup failed");
int amplSub = sidcBuilder.amplifier2ndDigit();
QVERIFY2(amplSub == 3 , "amplifierSecondDigit failed");
// Second10
}
}
void SitMapUnitTest::checkSIDCDefinitions2()
{
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
return;
checkSymbolDictionaryLoad();
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
AdvancedSymbology::SidcDefinitions sidcDefinitions(&dict);
const QStringList &modifierKeys = sidcDefinitions.modifierKeys();
QVERIFY2(modifierKeys.isEmpty() == false , "modifierKeys failed");
QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::Activities, 1).isEmpty() == false , "modifierList failed");
// QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::Activities, 2).isEmpty() == false , "modifierList failed");
QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::Air, 1).isEmpty() == false , "modifierList failed");
QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::Air, 2).isEmpty() == false , "modifierList failed");
QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::AirMissle, 1).isEmpty() == false , "modifierList failed");
QVERIFY2(sidcDefinitions.modifierList(AdvancedSymbology::SidcDefinitions::SymbolSet::AirMissle, 2).isEmpty() == false , "modifierList failed");
// to be cont.
}
/*
void SitMapUnitTest::checkCreateSidc()
{
//
// MIL
//
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(AdvancedSymbology::SymbologyType::MIL2525C);
{
QString sidc(QLatin1String("S*G*UCD---*****")); // ('taken' from typen@sys_db)
dict.createSidc(sidc, SymbolTypes::FRIEND, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SFGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::NEUTRAL, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SNGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::UNKNOWN, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SUGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_ANTICIPATED);
// QVERIFY2( dict.contains(sidc), "contains failed"); // ANTICIPATED -> 'A' is not supported by ESRI-Dictionary yet
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGAUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---************"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGPUCD---")) == 0, "createSidc failed");
}
}
//
// APP6
//
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(AdvancedSymbology::SymbologyType::APP6B);
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::FRIEND, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SFGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::NEUTRAL, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SNGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::UNKNOWN, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SUGPUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---*****"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_ANTICIPATED);
// QVERIFY2( dict.contains(sidc), "contains failed"); // ANTICIPATED -> 'A' is not supported by ESRI-Dictionary yet
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGAUCD---")) == 0, "createSidc failed");
}
{
QString sidc(QLatin1String("S*G*UCD---************"));
dict.createSidc(sidc, SymbolTypes::ENEMY, SymbolTypes::STATE_PRESENT);
QVERIFY2(dict.contains(sidc), "contains failed");
QVERIFY2(sidc.length() == 10, "createSidc failed");
QVERIFY2(sidc.compare(QLatin1String("SHGPUCD---")) == 0, "createSidc failed");
}
}
}
*/
/*
void SitMapUnitTest::checkSymbolProperties()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
if (dict.symbologyType() == AdvancedSymbology::SymbologyType::None)
return;
// 1
{
QString sidc(QLatin1String("SUGPUSAJ--")); // SUGPUSAJ-- should exist as MIL and APP :-)
QVERIFY2(dict.contains(sidc), "contains failed");
const AdvancedSymbology::SymbolProperties &props = dict.symbolProperties(sidc);
QVERIFY2(props.sidc().compare(QLatin1String("SUGPUSAJ--")) == 0, "symbolProperties failed");
QVERIFY2(props.geometryType() == AdvancedSymbology::GeometryType::Point, "geometryType failed");
int minPoints = props.minNumberOfPoints();
QVERIFY2(minPoints == 1, "minNumberOfPoints failed");
}
// 2
{
QString sidc;
switch (m_d->m_symbologyType)
{
case AdvancedSymbology::SymbologyType::MIL2525C:
sidc = QLatin1String("GUGPOLAGM-");
break;
case AdvancedSymbology::SymbologyType::APP6B:
sidc = QLatin1String("GHTPGC----");
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
}
if (! sidc.isEmpty())
{
QVERIFY2(dict.contains(sidc), "contains failed");
const AdvancedSymbology::SymbolProperties &props = dict.symbolProperties(sidc);
QVERIFY2(props.sidc().compare(sidc) == 0, "symbolProperties failed");
QVERIFY2(props.geometryType() == AdvancedSymbology::GeometryType::Polyline, "geometryType failed");
int minPoints = props.minNumberOfPoints();
QVERIFY2(minPoints == 2, "minNumberOfPoints failed");
}
}
// 3
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::APP6B)
{
// Check if esriBug is fixed (by our own or by esri)
// Bug 1: Tank Light Recovery:
// APP6: correct: "S*G*EVATW-"
// (MIL: correct: "S*G*EVATLR"
// APP6: 10.2.6: "S*G*EVATLR" (e.g. 0695)
QString sidc(QLatin1String("SUGPEVATW-")); // SUGPEVATW-
QVERIFY2(dict.contains(sidc), "contains failed");
const AdvancedSymbology::SymbolProperties &props = dict.symbolProperties(sidc);
QVERIFY2(props.sidc().compare(sidc) == 0, "symbolProperties failed");
QVERIFY2(props.geometryType() == AdvancedSymbology::GeometryType::Point, "geometryType failed");
int minPoints = props.minNumberOfPoints();
QVERIFY2(minPoints == 1, "minNumberOfPoints failed");
// check keywords:
QStringList result = props.keywords().filter(sidc, Qt::CaseInsensitive);
QVERIFY2(result.size() == 1, "keywords failed");
}
}
*/
QImage createDummyImage()
{
int widthPixel = 100;
QImage image = QImage(widthPixel, widthPixel, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter p;
QPen pen(Qt::red);
pen.setWidth(5);
p.begin(&image);
p.setPen(pen);
p.drawLine(QPointF(0, 0), QPointF(100, 100));
p.end();
// bool success = image.save(QLatin1String("/tmp/dummy.png"));
// qWarning() << " image.save = " << success;
return image;
}
/*
bool checkAllCount(AdvancedSymbology::SymbolDictionary &dict)
{
SituationMap::LOGGER_T myLogger = SituationMap::getLogger("SitMapUnitTest");
if (dict.symbologyType() == AdvancedSymbology::SymbologyType::None)
{
// None:
if (dict.count() > 100) // 100 -> arbitrary
return false;
}
else
{
// App, Mil:
if (dict.count() <= 0)
return false;
}
// verify size of different lists:
int count = dict.count();
int sizeFindSymbolsAll = dict.findSymbols().size();
QString sidcPattern; // empty
int sizeFindSymbolsSidcPattern = dict.findSymbols(sidcPattern).size();
int sizeSidcList = dict.sidcList().size();
INFO_LOG(myLogger) << LOGFUNCTION
<< " count = " << count
<< " sizeFindSymbolsAll = " << sizeFindSymbolsAll
<< " sizeFindSymbolsSidcPattern = " << sizeFindSymbolsSidcPattern
<< " sizeSidcList = " << sizeSidcList;
bool ok = (count == sizeFindSymbolsAll)
&& (count == sizeFindSymbolsSidcPattern)
&& (count == sizeSidcList);
if (! ok)
{
ERROR_LOG(myLogger) << LOGFUNCTION
<< " count = " << count
<< " sizeFindSymbolsAll = " << sizeFindSymbolsAll
<< " sizeFindSymbolsSidcPattern = " << sizeFindSymbolsSidcPattern
<< " sizeSidcList = " << sizeSidcList;
}
return ok;
}
*/
/*
bool addOneSymbol(AdvancedSymbology::SymbolDictionary &dict)
{
SituationMap::LOGGER_T myLogger = SituationMap::getLogger("SitMapUnitTest");
Q_UNUSED(myLogger)
bool success = false;
QImage image = createDummyImage();
const QString sidc = QLatin1String("Nt-sidc");
const QString name = QLatin1String("NT-name");
QStringList keywords;
keywords << QLatin1String("NT-key1");
keywords << QLatin1String("NT-keyDuplicate") << QLatin1String("NT-keyDuplicate");
QHash<QString, QString> values;
values[QLatin1String("Category")] = QLatin1String("Other");
values[QLatin1String("SymbolID")] = sidc;
values[QLatin1String("GeometryType")] = QLatin1String("Point");
values[QLatin1String("GeometryConversionType")] = QLatin1String("GeometryConversionType-Unknown");
values[QLatin1String("StyleFile")] = QLatin1String("StyleFile-Unknown");
AdvancedSymbology::SymbolProperties props(name, keywords, values);
success = dict.addSymbol(sidc, props, image);
return success;
}
*/
void SitMapUnitTest::checkSymbolDictionaryLoad()
{
AdvancedSymbology::cleanupSymbolDictionaryInternal();
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
QSignalSpy spy(&dict, &AdvancedSymbology::SymbolDictionary::loaded);
dict.load();
QTRY_VERIFY2(dict.isLoaded(), "SymbolDictionary: isLoaded failed");
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
{
QTest::qWait(100);
QVERIFY2(spy.count() == 0, "SymbolDictionary: signalCount failed, layerOrderChanged");
}
else
{
QTRY_VERIFY2(spy.count() == 1, "SymbolDictionary: signalCount failed, layerOrderChanged");
}
// get cached Dictionary:
qWarning() << "get cached Dictionary";
{
// -> immediately loaded
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
QVERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
}
/*
int count = dict.count();
bool dictChanged = false;
// lambda
connect(&dict, &AdvancedSymbology::SymbolDictionary::changed, [&]()
{
dictChanged = true;
});
//
// Initial Check
//
bool countOk = checkAllCount(dict);
QVERIFY2((countOk == true), "at least one count failed");
//
// add new symbol an check:
//
{
bool addSym = addOneSymbol(dict);
QVERIFY2((addSym == true), "addSymbol failed");
QVERIFY2((dictChanged == true), "dictChanged signal not emitted");
countOk = checkAllCount(dict);
QVERIFY2((countOk == true), "at least one count failed");
QVERIFY2(dict.count() == (count + 1), "count failed");
}
*/
}
void SitMapUnitTest::checkSymbolDictionaryLoadSymbolXml()
{
AdvancedSymbology::cleanupSymbolDictionaryInternal();
AdvancedSymbology::SymbolDictionary &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
bool ok;
AdvancedSymbology::SymbolProperties symProps;
ok = dict.insertXmlTestSymbol(symProps);
QVERIFY2(ok, "insert xml test symbol failed.");
ok = dict.insertXmlComplexTestSymbol(symProps);
QVERIFY2(ok, "insert xml test complex symbol failed.");
QVERIFY2( (dict.xmlSymbolCount() == 2), "count of xml symbols has wrong value - should be 2" );
const QString &sidc = AdvancedSymbology::SidcCodec::encodeCivilXml(QString::number(4711));
dict.removeXmlSymbol(sidc);
dict.removeXmlSymbol(4711);
QVERIFY2( (dict.xmlSymbolCount() == 1), "count of xml symbols has wrong value after removeXmlSymbol() - should be 1" );
dict.clearXmlSymbols();
QVERIFY2( (dict.xmlSymbolCount() == 0), "count of xml symbols is not zero after clearXmlSymbols()" );
} // void SitMapUnitTest::checkSymbolDictionaryLoadSymbolXml()
void SitMapUnitTest::checkSymbolDictionaryConsistency()
{
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
return;
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// get access to esriDict:
AdvancedSymbology::SymbolDictionaryImpl &dictImpl = static_cast<AdvancedSymbology::SymbolDictionaryImpl &>(dict);
Esri::ArcGISRuntime::DictionarySymbolStyle *esriDict = const_cast<Esri::ArcGISRuntime::DictionarySymbolStyle*>(dictImpl.getEsriSymbolDictionary());
QHash<QString, AdvancedSymbology::SymbolProperties> baseSymbolCodeToSymbolPropertyTable;
// Use QFuture-based async API
Esri::ArcGISRuntime::SymbolStyleSearchParameters sssp;
QFuture<Esri::ArcGISRuntime::SymbolStyleSearchResultListModel*> future = esriDict->searchSymbolsAsync(sssp);
// Wait for completion
QFutureWatcher<Esri::ArcGISRuntime::SymbolStyleSearchResultListModel*> watcher;
watcher.setFuture(future);
watcher.waitForFinished();
Esri::ArcGISRuntime::SymbolStyleSearchResultListModel *searchResults = future.result();
INFO_LOG(m_logger) << LOGFUNCTION << " proceessing...";
//
// process all results and store them in member:
//
const QList<Esri::ArcGISRuntime::SymbolStyleSearchResult> &resultList =
searchResults->searchResults();
int symbolClass;
for (const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem : resultList)
{
// 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(";")) << "'";
const QString &originalKey = resultItem.key();
// to reduce empty keys:
symbolClass = resultItem.symbolClass().toInt();
if ( (symbolClass == 6) || // symbolClass ( 6) == TextSymbol
(symbolClass == 10) // symbolClass (10) == MaplexLabelPlacement
)
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: symbolClass does not match "
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
if (originalKey.isEmpty())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: empty key, "
<< " name='" << resultItem.name() << "'";
continue;
}
//
// size (25270100 || 25270100_4)
//
const int keySize = originalKey.size();
if ( ! ((keySize == 8) || (keySize == 10)) )
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: keySize does not match "
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
//
// isFrame (key like '0_110_1c')
//
if ( QStringRef(&originalKey, 1, 1).compare(QLatin1String("_"))==0 )
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: isFrame "
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
//
// isCharlie (key like '46120203_C')
//
if ( (keySize == 10) && (originalKey.rightRef(2).compare(QLatin1String("_C"))==0) )
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: isCharlie"
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
const QString &key = originalKey;
//
// just digits:
//
bool ok = false;
const QStringRef &key8 = originalKey.leftRef(8);
key8.toInt(&ok);
if (! ok)
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: chars"
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
//
// special (46110304_X)
//
if ( (keySize == 10) && (originalKey.rightRef(2).compare(QLatin1String("_X"))==0) )
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " continue:: is _X"
<< " originalKey='" << originalKey << "'"
<< " name='" << resultItem.name() << "'";
continue;
}
AdvancedSymbology::SymbolProperties symProps;
symProps.setKey (key);
symProps.setSidc (AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(m_d->m_symbologyType,key8));
symProps.setName (resultItem.name());
symProps.setCategory (resultItem.category());
symProps.setSymbolClass(resultItem.symbolClass());
symProps.setTags (resultItem.tags());
baseSymbolCodeToSymbolPropertyTable[originalKey] = symProps;
} // Q_FOREACH
FATAL_LOG(m_logger) << LOGFUNCTION << " baseSymbolCodeToSymbolPropertyTable.size=" << baseSymbolCodeToSymbolPropertyTable.size();
QStringList noKey8Entries;
QStringList noKey8EntriesOfUnknown;
QStringList propsDiffer;
for (const AdvancedSymbology::SymbolProperties &symPropItem : std::as_const(baseSymbolCodeToSymbolPropertyTable))
{
const QString &curKey = symPropItem.key();
// INFO_LOG(m_logger) << LOGFUNCTION << " curKey ='" << curKey << "'";
const QString &key8 = curKey.left(8);
// check 1a:
// are there entries with postfix (_1, _2, _3) but not without??
bool noKey8EntriesFlag = false;
// 25270100_1 but not 25270100 ?
// (e.g. '10120100_0' ; '10120100_1' ; '10120100_2' ; '10120100_3' ; but no '10120100'
// 10120100 = Movement And Maneuver ; Air Assult with Organic Lift - FullFrame
// These are the FULL_FRAME symbols. (except "Maneuver Lines : Line of Contact" = 25140200_6)
//
// Exception: "Maneuver Lines : Line of Contact" = 25140200_6, _4, _3, _1)
if (curKey.size() == 10)
{
if (! baseSymbolCodeToSymbolPropertyTable.contains(key8))
{
noKey8Entries.append(curKey);
noKey8EntriesFlag = true;
}
} // if (curKey.size() == 10)
// check 1b
if (noKey8EntriesFlag &&
symPropItem.name().contains(QLatin1String("Unknown")))
{
noKey8EntriesOfUnknown.append(curKey);
}
// check 2:
AdvancedSymbology::SymbolProperties curSymProps = baseSymbolCodeToSymbolPropertyTable[curKey];
{
QStringList sl = curSymProps.name().split(QLatin1Char(':'));
sl.removeOne(QLatin1String("Friend"));
sl.removeOne(QLatin1String("Friendly"));
sl.removeOne(QLatin1String("Hostile"));
sl.removeOne(QLatin1String("Neutral"));
sl.removeOne(QLatin1String("Unknown"));
curSymProps.setName(sl.join(QLatin1Char(':')));
}
if (baseSymbolCodeToSymbolPropertyTable.contains(key8))
{
AdvancedSymbology::SymbolProperties symPropsKey8 = baseSymbolCodeToSymbolPropertyTable[key8];
QStringList sl = symPropsKey8.name().split(QLatin1Char(':'));
sl.removeOne(QLatin1String("Friend"));
sl.removeOne(QLatin1String("Friendly"));
sl.removeOne(QLatin1String("Hostile"));
sl.removeOne(QLatin1String("Neutral"));
sl.removeOne(QLatin1String("Unknown"));
symPropsKey8.setName(sl.join(QLatin1Char(':')));
DEBUG_LOG(m_logger) << LOGFUNCTION << " key8=" << key8 << " curSymProps.name = " << curSymProps.name();
DEBUG_LOG(m_logger) << LOGFUNCTION << " key8=" << key8 << " symPropsKey8.name = " << symPropsKey8.name();
bool ok =
// (curSymProps.name() == symPropsKey8.name()) &&
// (curSymProps.category() == symPropsKey8.category()) &&
// // (curSymProps.symbolClass() == symPropsKey8.symbolClass()) && // do not compare SymbolClass
(curSymProps.tags() == symPropsKey8.tags());
// (curSymProps.geometryType() == symPropsKey8.geometryType());
if (! ok)
{
propsDiffer.append(curKey);
}
}
} // Q_FOREACH
DEBUG_LOG(m_logger) << LOGFUNCTION << " noKey8Entries.size = " << noKey8Entries.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " noKey8Entries = " << noKey8Entries.join(QLatin1String(" ; "));
DEBUG_LOG(m_logger) << LOGFUNCTION << " noKey8EntriesOfUnknown.size = " << noKey8EntriesOfUnknown.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " noKey8EntriesOfUnknown = " << noKey8EntriesOfUnknown.join(QLatin1String(" ; "));
DEBUG_LOG(m_logger) << LOGFUNCTION << " propsDiffer.size = " << propsDiffer.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " propsDiffer = " << propsDiffer.join(QLatin1String(" ; "));
// dump differ:
for (const auto &curKey : propsDiffer)
{
AdvancedSymbology::SymbolProperties curSymProps = baseSymbolCodeToSymbolPropertyTable[curKey];
const QString &key8 = curKey.left(8);
AdvancedSymbology::SymbolProperties symPropsKey8 = baseSymbolCodeToSymbolPropertyTable[key8];
DEBUG_LOG(m_logger) << LOGFUNCTION << " curSymProps " << curSymProps.tags().join(QLatin1String(" @ "));
DEBUG_LOG(m_logger) << LOGFUNCTION << " symPropsKey8 " << symPropsKey8.tags().join(QLatin1String(" @ "));
}
}
void SitMapUnitTest::checkSymbolDictionaryFetchSymbol()
{
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
{
const QString sidc = AdvancedSymbology::SidcCodec::encodeComplete(AdvancedSymbology::SymbologyType::MIL2525D, "10042500002701000000"); // baseSymbolCode = 25 270100
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
QVERIFY2((symbolResultWatcher.resultIsValid() == false), "SymbolDictionary: resultIsValid failed");
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
const QUuid &taskId1 = symbolResultWatcher.symbolResult()->taskId();
QVERIFY2((taskId1.isNull() == false), "SymbolDictionary: taskId failed");
// inspect result:
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polygon), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
}
// find different: (PointSymbol)
{
const QString sidc = AdvancedSymbology::SidcCodec::encodeComplete( AdvancedSymbology::SymbologyType::MIL2525D,"10031500001110000000"); // baseSymbolCode = 15 111000 Missle Launcher
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
const QUuid &taskId2 = symbolResultWatcher.symbolResult()->taskId();
QVERIFY2((taskId2.isNull() == false), "SymbolDictionary: taskId failed");
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
}
}
}
void SitMapUnitTest::checkSymbolDictionaryFetchSymbol2()
{
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
if (m_d->m_symbologyType != AdvancedSymbology::SymbologyType::MIL2525D)
{
return;
}
// find some PointSymbols:
int counter = 0;
const QStringList sidcs = AdvancedSymbology::listOfPointSidcs_Internal();
for (const auto &sidc : sidcs)
{
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
const QUuid &taskId2 = symbolResultWatcher.symbolResult()->taskId();
QVERIFY2((taskId2.isNull() == false), "SymbolDictionary: taskId failed");
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
++counter;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter=" << counter;
}
void SitMapUnitTest::checkSymbolDictionaryFetchSymbolAll()
{
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// add ExtraSymbols:
const QString extraSymbolDir(QLatin1String(":/advancedSymbology/CivilSymbols"));
dict.addEtsSymbols(extraSymbolDir);
// fetch all Extra symbols:
int counter = 0;
const QStringList extraSymbolSidcs = dict.etsSymbols();
qCritical() << " extraSymbolSidcs.size = " << extraSymbolSidcs.size();
for (const auto &sidc : extraSymbolSidcs)
{
AdvancedSymbology::SymbolResultWatcher *symbolResultWatcher = new AdvancedSymbology::SymbolResultWatcher(this);
connect(symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, [sidc, &counter, symbolResultWatcher]()
{
// lambda:
// qCritical() << " sidc=" << sidc;
QVERIFY2((symbolResultWatcher->resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher->symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
// Note: TaskId is null (esri not needed)
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = symbolResultWatcher->symbolResult();
QVERIFY2((symResult), "SymbolDictionary: symResult failed");
QVERIFY2((symResult->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
QVERIFY2((symResult->symbolImage().image().size().isEmpty() == false), "SymbolDictionary: symbolImage failed");
++counter;
});
if (1) {
symbolResultWatcher->setSymbolResult(dict.fetchSymbol(sidc));
}
if (0) {
symbolResultWatcher->setSymbolResult(dict.findPreview(sidc));
}
if (0) {
AdvancedSymbology::SymbolDataToRender symDataToRender;
symDataToRender.sidc = sidc;
symbolResultWatcher->setSymbolResult(dict.findImage(symDataToRender));
}
}
QTRY_VERIFY2_WITH_TIMEOUT((counter == extraSymbolSidcs.size()), "SymbolDictionary: something failed", 20000);
qWarning() << " counter=" << counter;
}
void SitMapUnitTest::checkSymbolDictionaryExtraDirFetchSymbol()
{
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
const QString extraSymbolDir(QLatin1String(":/advancedSymbology/CivilSymbols"));
int addedFiles = dict.addEtsSymbols(extraSymbolDir);
int extraSymbolCount = dict.etsSymbolCount();
qWarning() << "addedFiles=" << addedFiles;
qWarning() << "extraSymbolCount=" << extraSymbolCount;
QVERIFY2((addedFiles > 500), "SymbolDictionary: addExtraSymbols failed");
QVERIFY2((addedFiles == extraSymbolCount), "SymbolDictionary: extraSymbolCount failed");
// find:
{
const QString sidc( QLatin1String("DOES_NOT_EXISTS") );
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
// Here is a notFoundSymbolResult: ('?') returned.
// Because it´s not really correct, the symbolImage is marked as 'not valid':
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().isValid() == false), "SymbolDictionary: symbolImage should be invalid (notFoundSymbolResult: '?')");
}
// find:
{
const QString sidc = AdvancedSymbology::SidcCodec::encodeCivilEts("FzSanKrad"); // FzSanKrad.gif
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// inspect result:
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
}
}
void SitMapUnitTest::checkSymbolDictionaryFetchSymbolStress()
{
return; // just for manual usage
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
return;
checkSymbolDictionaryLoad();
auto &dict = AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
QStringList sidcs = AdvancedSymbology::listOfPointSidcs_Internal();
QString sidc = sidcs.first();
// AdvancedSymbology::SymbolResultWatcher *symbolResultWatcher =
// new AdvancedSymbology::SymbolResultWatcher(this);
int counter = 0;
QTimer *timer = new QTimer(this);
timer->setInterval(1);
connect(timer, &QTimer::timeout, this, [timer, &dict, sidc, &counter]()
{
if ((++counter%100) == 0)
qCritical() << " timeout... counter = " << counter;
QSharedPointer<AdvancedSymbology::SymbolResult> result = dict.fetchSymbol(sidc);
// symbolResultWatcher->setSymbolResult(dict.fetchSymbol(sidc));
if (counter == 10000)
timer->stop();
});
timer->start();
QTRY_VERIFY_WITH_TIMEOUT(!timer->isActive(), 60 * 1000);
}
void SitMapUnitTest::checkSymbolDictionaryBulkRenderer()
{
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::None)
return;
checkSymbolDictionaryLoad();
QStringList pointSidcs = AdvancedSymbology::listOfPointSidcs_Internal();
QStringList lineSidcs = AdvancedSymbology::listOfLineSidcs_Internal();
{
AdvancedSymbology::BulkRendererFindBaseSymbol bulkRenderer(m_d->m_symbologyType);
QSignalSpy spy(&bulkRenderer, &AdvancedSymbology::BulkRendererFindBaseSymbol::resultsReady);
bulkRenderer.addRequest(pointSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.addRequest(lineSidcs.first());
bulkRenderer.run(); // <--- run
QTRY_VERIFY2((spy.count() == 1), "BulkRenderer: resultsReady-signal failed");
int successfullCnt = 0;
AdvancedSymbology::BulkRendererFindBaseSymbol::RequestResultVector rrVec = bulkRenderer.results();
for (const AdvancedSymbology::BulkRendererFindBaseSymbol::RequestResult &rr : std::as_const(rrVec))
{
if (rr.second
&& rr.second->symbolResult()
&& rr.second->symbolResult()->isResultReady())
{
const QImage img = rr.second->symbolResult()->symbolImage().image();
if (img.width() > 10)
++successfullCnt;
// const QString sidc = rr.first; qCritical() << " sidc= '" << sidc << "'" << " img.size(): " << img.size();
// img.save(QStringLiteral("/tmp/img.png"));
}
} // for
QVERIFY2((successfullCnt == rrVec.size()), "BulkRenderer: size comparision failed");
bulkRenderer.reset();
}
}
void fetchSymbolGeoType(const AdvancedSymbology::SymbolDictionary &dict,
const QString &sidc,
AdvancedSymbology::GeometryType geoType)
{
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
QVERIFY2((symbolResultWatcher.resultIsValid() == false), "SymbolDictionary: resultIsValid failed");
symbolResultWatcher.setSymbolResult(dict.fetchSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// inspect result:
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = symbolResultWatcher.symbolResult();
QVERIFY2((symResult.isNull() == false), "SymbolDictionary: isNull failed");
QVERIFY2((symResult->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
if (symResult->geometryType() != geoType)
{
qWarning() << " sidc=" << sidc << "'" << ", geometryType, failed, geoType="<< (int)symResult->geometryType();
}
QVERIFY2((symResult->geometryType() == geoType), "SymbolDictionary: geometryType failed");
}
void SitMapUnitTest::checkSymbolDictionaryFindImage()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
if (!dict.isLoaded())
{
dict.load();
QTRY_VERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
}
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
QStringList sidcs = AdvancedSymbology::listOfPointSidcs_Internal();
int counter = 0;
//
// SinglePoint:
//
for (const QString &sidc : std::as_const(sidcs))
{
SituationMap::SymbolData symData;
AdvancedSymbology::SymbolDataToRender symDataToRender = symData.getDefaultRenderData();
symDataToRender.sidc = sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findImage(symDataToRender));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
const QUuid &taskId2 = symbolResultWatcher.symbolResult()->taskId();
QVERIFY2((taskId2.isNull() == false), "SymbolDictionary: taskId failed");
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter1=" << counter;
//
// Line:
//
counter = 0;
sidcs = AdvancedSymbology::listOfLineSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
qWarning() << " sidc=" << sidc;
SituationMap::SymbolData symData;
AdvancedSymbology::SymbolDataToRender symDataToRender = symData.getDefaultRenderData();
symDataToRender.sidc = sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findImage(symDataToRender));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is skipped here :
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polyline), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter2=" << counter;
//
// Area:
//
counter = 0;
sidcs = AdvancedSymbology::listOfAreaSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
SituationMap::SymbolData symData;
AdvancedSymbology::SymbolDataToRender symDataToRender = symData.getDefaultRenderData();
symDataToRender.sidc = sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findImage(symDataToRender));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is skipped here :
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polygon), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter3=" << counter;
}
}
void SitMapUnitTest::checkSymbolDictionaryFindPreview()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
dict.load();
QTRY_VERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
QStringList sidcs = AdvancedSymbology::listOfPointSidcs_Internal();
//
// SinglePoint:
//
int counter = 0;
for (const QString &sidc : std::as_const(sidcs))
{
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findPreview(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
const QUuid &taskId2 = symbolResultWatcher.symbolResult()->taskId();
QVERIFY2((taskId2.isNull() == false), "SymbolDictionary: taskId failed");
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter1=" << counter;
//
// Line:
//
counter = 0;
sidcs = AdvancedSymbology::listOfLineSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findPreview(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is slipped here :
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polyline), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter2=" << counter;
//
// Area:
//
counter = 0;
sidcs = AdvancedSymbology::listOfAreaSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findPreview(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is slipped here :
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polygon), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter3=" << counter;
}
}
void SitMapUnitTest::checkSymbolDictionaryFindBaseSymbol()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
dict.load();
QTRY_VERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
//
// SinglePoint:
//
QStringList sidcs = AdvancedSymbology::listOfPointSidcs_Internal();
int counter = 0;
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findBaseSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is skipped here
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Point), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter1=" << counter;
//
// Line:
//
counter = 0;
sidcs = AdvancedSymbology::listOfLineSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findBaseSymbol(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is skipped here:
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polyline), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter2=" << counter;
//
// Area:
//
counter = 0;
sidcs = AdvancedSymbology::listOfAreaSidcs_Internal();
for (const QString &sidc : std::as_const(sidcs))
{
// qWarning() << " sidc=" << sidc;
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
symbolResultWatcher.setSymbolResult(dict.findPreview(sidc));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: resultIsValid failed");
// TaskId is slipped here :
QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polygon), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
counter++;
}
QVERIFY2((counter == sidcs.size()), "SymbolDictionary: something failed");
qWarning() << " counter3=" << counter;
}
}
void SitMapUnitTest::checkSymbolDictionaryGctString()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
dict.load();
QTRY_VERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
// search:
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
QStringList slGctLine;
QStringList slGctArea;
{
slGctLine += QLatin1String("gct_arrow");
slGctLine += QLatin1String("gct_arrow_with_offset");
slGctLine += QLatin1String("gct_parallel_lines");
slGctLine += QLatin1String("gct_parallel_lines_mid_line");
slGctLine += QLatin1String("gct_parallel_lines_with_ticks");
slGctLine += QLatin1String("gct_two_line");
slGctLine += QLatin1String("gct_arrow_with_tail");
slGctLine += QLatin1String("gct_open_triangle");
slGctLine += QLatin1String("gct_freehand_line");
slGctLine += QLatin1String("gct_freehand_arrow");
slGctLine += QLatin1String("gct_freehand_reverse_arrow");
slGctLine += QLatin1String("gct_freehand_u");
slGctLine += QLatin1String("gct_circle");
slGctLine += QLatin1String("gct_hook");
slGctLine += QLatin1String("gct_horns");
slGctLine += QLatin1String("gct_parallel_lines_with_ticks");
slGctLine += QLatin1String("gct_t");
slGctLine += QLatin1String("gct_triple_arrow");
slGctLine += QLatin1String("gct_two_line_3_or_4_pt");
slGctLine += QLatin1String("gct_u_or_t_shape");
slGctArea += QLatin1String("gct_rectangular_1_pt");
slGctArea += QLatin1String("gct_circular");
slGctArea += QLatin1String("gct_rectangular");
slGctArea += QLatin1String("gct_parallel_lines_with_ticks");
}
unsigned int symbolCounter = 0;
unsigned int unexpectedCounter = 0;
unsigned int emptyCounter = 0;
AdvancedSymbology::SymbolDictionaryImpl &dictImpl =
static_cast<AdvancedSymbology::SymbolDictionaryImpl&>(dict);
const AdvancedSymbology::SidcCodec::SidcHashTable<AdvancedSymbology::SymbolProperties> &allSymbolProps =
dictImpl.getEsriDictionaryProcessor()->baseSymbolCodeToSymbolPropertyTable();
for (const AdvancedSymbology::SymbolProperties &prop : std::as_const(allSymbolProps))
{
QString baseKey = prop.key();
if (baseKey.isEmpty())
continue;
++symbolCounter;
const QString & gctString = prop.gctString();
if (! gctString.isEmpty())
{
switch (prop.geometryType())
{
case AdvancedSymbology::GeometryType::Point:
{
if (! gctString.isEmpty())
{
++unexpectedCounter;
qDebug() << " Point feature has none empty gctString, baseKey=" << baseKey << " gctString =" << gctString << endl;
continue;
}
}
break;
case AdvancedSymbology::GeometryType::Polyline:
{
if (! slGctLine.contains(gctString) )
{
++unexpectedCounter;
qDebug() << " Unexpected gctString for line symbol found, baseKey=" << baseKey << " gctString =" << gctString << endl;
}
continue;
}
break;
case AdvancedSymbology::GeometryType::Polygon:
{
if (! slGctArea.contains(gctString) )
{
++unexpectedCounter;
qDebug() << " Unexpected gctString for area symbol found, baseKey=" << baseKey << " gctString =" << gctString << endl;
}
continue;
}
break;
default : break;
} // switch
}
else
{
switch (prop.geometryType())
{
case AdvancedSymbology::GeometryType::Polyline: qDebug() << " Empty gctString found for line symbol, baseKey=" << baseKey << endl; ++emptyCounter; break;
case AdvancedSymbology::GeometryType::Polygon : qDebug() << " Empty gctString found for area symbol, baseKey=" << baseKey << endl; ++emptyCounter; break;
case AdvancedSymbology::GeometryType::Point :
default : break;
}
}
} // foreach
qDebug() << "Checked symbols: " << symbolCounter << " empty gctString at line or areals: " << emptyCounter << endl;
static char msg[128];
sprintf( msg, "%d unexpected gctStrings found.", unexpectedCounter);
QVERIFY2( (unexpectedCounter == 0), msg );
}
return;
} // void SitMapUnitTest::checkSymbolDictionaryGctString()
void SitMapUnitTest::checkSymbolDictionarySymbolPropertyImage()
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(m_d->m_symbologyType);
// SymbologyType::None -> no esriDict -> immediately loaded:
// ! SymbologyType::None -> esriDict -> load...
dict.load();
QTRY_VERIFY2((dict.isLoaded() == true), "SymbolDictionary: isLoaded failed");
if (m_d->m_symbologyType == AdvancedSymbology::SymbologyType::MIL2525D)
{
AdvancedSymbology::SymbolProperties symProps;
symProps.setOriginalKey(QLatin1String("25270100")); // obstacle / building
AdvancedSymbology::SymbolResultWatcher symbolResultWatcher;
QSignalSpy spy(&symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady);
QVERIFY2((symbolResultWatcher.resultIsValid() == false), "SymbolDictionary: resultIsValid failed");
symbolResultWatcher.setSymbolResult(dict.symbolPropertyImage(symProps));
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: symbolPropertyImage resultIsValid failed");
QVERIFY2((symbolResultWatcher.symbolResult().isNull() == false), "SymbolDictionary: symbolPropertyImage symbolResult failed");
QTRY_VERIFY2((spy.count() == 1), "SymbolDictionary: symbolPropertyImage resultReady-signal failed");
QVERIFY2((symbolResultWatcher.resultIsValid() == true), "SymbolDictionary: symbolPropertyImage resultIsValid failed");
// inspect result:
// QVERIFY2((symbolResultWatcher.symbolResult()->geometryType() == AdvancedSymbology::GeometryType::Polygon), "SymbolDictionary: geometryType failed");
QVERIFY2((symbolResultWatcher.symbolResult()->symbolImage().image().isNull() == false), "SymbolDictionary: symbolImage failed");
QImage img = symbolResultWatcher.symbolResult()->symbolImage().image();
img.save(QLatin1String("/tmp/unitTest.png"));
}
}
void SitMapUnitTest::checkMapSettings()
{
if (1)
{
// use absolute path:
// SituationMap::MapSettings ms(QLatin1String("/shd/CTC/TOOLS/TDS/TDS-build-product/bin/situation_map_defaults.ini"));
QString initFilePath = NGL::findFile(NGL::FileType::ConfigFile, QStringLiteral("situation_map_defaults.ini"));
if (initFilePath.isEmpty())
{
FATAL_LOG(m_logger) << " initFilePath " << initFilePath;
abort();
}
SituationMap::MapSettings ms(initFilePath);
QVERIFY2(ms.hasErrors() == false, "hasError failed");
QVERIFY2(ms.exists() == true, "exists failed");
QVERIFY2(ms.accessError() == false, "accessError failed");
QVERIFY2(ms.formatError() == false, "formatError failed");
std::cerr << " operator<<: \n" << ms << std::endl;
SituationMap::GridType gridType = ms.gridType();
QVERIFY2(gridType == SituationMap::GridType::MGRS, "gridType failed");
}
}
void SitMapUnitTest::checkMatrix2D()
{
SituationMap::MathUtils::Matrix2D matrix;
matrix.setToIdentity();
QVERIFY2( ( (matrix(0,0) == 1.0) && (matrix(0,1) == 0.0) && (matrix(0,2) == 0.0) &&
(matrix(1,0) == 0.0) && (matrix(1,1) == 1.0) && (matrix(1,2) == 0.0) &&
(matrix(2,0) == 0.0) && (matrix(2,1) == 0.0) && (matrix(2,2) == 1.0) ), "setToIdentity failed" );
SituationMap::MathUtils::Matrix2D matrix2;
QVERIFY2( ( (matrix2(0,0) == 1.0) && (matrix2(0,1) == 0.0) && (matrix2(0,2) == 0.0) &&
(matrix2(1,0) == 0.0) && (matrix2(1,1) == 1.0) && (matrix2(1,2) == 0.0) &&
(matrix2(2,0) == 0.0) && (matrix2(2,1) == 0.0) && (matrix2(2,2) == 1.0) ), "standard constructor does not set the identity matrix");
matrix2(0,0) = 11; matrix2(0,1) = 12; matrix2(0,2) = 13;
matrix2(1,0) = 21; matrix2(1,1) = 22; matrix2(1,2) = 23;
matrix2(2,0) = 31; matrix2(2,1) = 32; matrix2(2,2) = 33;
QVERIFY2( ( (matrix2(0,0) == 11) && (matrix2(0,1) == 12) && (matrix2(0,2) == 13) &&
(matrix2(1,0) == 21) && (matrix2(1,1) == 22) && (matrix2(1,2) == 23) &&
(matrix2(2,0) == 31) && (matrix2(2,1) == 32) && (matrix2(2,2) == 33) ), "set matrix elements failed");
SituationMap::MathUtils::Matrix2D matrix3(matrix2);
QVERIFY2( ( (matrix3(0,0) == 11) && (matrix3(0,1) == 12) && (matrix3(0,2) == 13) &&
(matrix3(1,0) == 21) && (matrix3(1,1) == 22) && (matrix3(1,2) == 23) &&
(matrix3(2,0) == 31) && (matrix3(2,1) == 32) && (matrix3(2,2) == 33) ), "copy constructor failed");
matrix = matrix2;
QVERIFY2( ( (matrix(0,0) == 11) && (matrix(0,1) == 12) && (matrix(0,2) == 13) &&
(matrix(1,0) == 21) && (matrix(1,1) == 22) && (matrix(1,2) == 23) &&
(matrix(2,0) == 31) && (matrix(2,1) == 32) && (matrix(2,2) == 33) ), "assign operator failed");
matrix.setToIdentity();
matrix.putTranslation(QPointF(5,7));
QPointF p = matrix.apply(QPointF(2,1));
QVERIFY2( ((p.x() == 7) && (p.y() == 8)), "putTranslation failed");
matrix.setToIdentity();
matrix.putScale(QPointF(2,3));
p = matrix.apply(QPointF(2,1));
QVERIFY2( ((p.x() == 4) && (p.y() == 3)), "putScale failed");
matrix.setToIdentity();
matrix.putScale(QPointF(2,2));
matrix.putTranslation(QPointF(5,7));
p = matrix.apply(QPointF(2,1));
QVERIFY2( ((p.x() == 9) && (p.y() == 9)), "putScale combined with putTranslate failed");
matrix.setToIdentity();
matrix.putRotate(QPointF(0,1));
p = matrix.apply(QPointF(2,1));
QVERIFY2( ((p.x() == 1) && (p.y() == -2)), "putRotated failed");
matrix.setToIdentity();
matrix.putRotate(QPointF(0.5,0.8660254)); // 60 degrees
p = matrix.apply(QPointF(1,0));
QVERIFY2( ((int(p.x()*10) == 5) && (int(p.y()*1000000) == -866025)), "putRotated 60 degrees failed");
matrix.setToIdentity();
matrix.putTranslation(QPointF(-5,-7));
matrix.putRotate(QPointF(0,1));
matrix.putTranslation(QPointF(5,7));
p = matrix.apply(QPointF(7,8));
QVERIFY2( ((p.x() == 6) && (p.y() == 5)), "putRotated combined with putTranslate failed");
matrix.setToIdentity();
matrix.putTranslation(QPointF(-5,-7));
matrix.putRotate(QPointF(0.5,0.8660254)); // 60 degrees
matrix.putTranslation(QPointF(5,7));
p = matrix.apply(QPointF(6,7));
QVERIFY2( ((int(p.x()*10) == 55) && (int(p.y()*10000000) == 61339746)), "putRotated 60 degrees combined with putTranslate failed");
} // SitMapUnitTtest::checkMatrix2D()
//-------------------------------------------------------------------------------------------------------
#include "unit_test.moc"