/** * @RDE_HEADER@ * Unittest * $Id$ * $HeadURL$ * $Author$ */ #include "unit_test.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 tc = QSharedPointer(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 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 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 qContL; // do NOT modify, QList is used to compare with QVector (a couple of lines later) QVector 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 -> " << 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 -> " << timer.elapsed() << "ms"; } } } void SitMapUnitTest::checkQWeakPointer() { QWeakPointer ts_weak; // TextStyle does NOT inherent from QObject QVERIFY2((ts_weak.isNull() == true), "isNull: failed"); { QSharedPointer 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 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() is not false." ); } void SitMapUnitTest::checkIdHandlerReUseId() { quint32 usedIdCount = m_d->m_uniqueIdHandler->countUsedIds(); QList 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 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 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 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 class MyMapObjectType : public T { public: MyMapObjectType(const QString &debugInfo = QString()) : T(debugInfo) {} }; using MyParticipantImpl = MyMapObjectType; using MyBiologicalAgentImpl = MyMapObjectType; using MyBuildingOutlineImpl = MyMapObjectType; void SitMapUnitTest::checkIdContainer() { QVERIFY2((IdGeneratorCounting::getCounter() == 0), "Check IdGeneratorCounting, count failed"); // SituationMap::BuildingOutlineImpl bbbbbbbbb( QLatin1String("bio2") ); { // // ONE IdGenerator connected to TWO ObjectContainer: // QSharedPointer 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 part1(new MyParticipantImpl(QLatin1String("part1"))); QVERIFY2(part1.valid() == true , "create part failed"); SituationMap::RefPointer bio1(new MyBiologicalAgentImpl(QLatin1String("bio1"))); QVERIFY2(bio1.valid() == true , "create failed"); SituationMap::RefPointer bio2(new MyBiologicalAgentImpl(QLatin1String("bio2"))); QVERIFY2(bio2.valid() == true , "create failed"); SituationMap::RefPointer build1(new MyBuildingOutlineImpl(QLatin1String("build1"))); QVERIFY2(build1.valid() == true , "create failed"); SituationMap::RefPointer build2(new MyBuildingOutlineImpl(QLatin1String("build2"))); QVERIFY2(build2.valid() == true , "create failed"); SituationMap::RefPointer 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 part1(new MyParticipantImpl(QLatin1String("part1"))); QVERIFY2(part1.valid() == true , "create part failed"); SituationMap::RefPointer bio1(new MyBiologicalAgentImpl(QLatin1String("bio1"))); QVERIFY2(bio1.valid() == true , "create failed"); SituationMap::RefPointer 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 keyList = container2->getAllKeys(); QVERIFY2((keyList.count() == 3), "Check IdContainer getAllKeys failed"); QList 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 objPtr1; objPtr1 = objFac.create(layername, QLatin1String("UnitTestId1")); QVERIFY2(objPtr1.valid() == false , "objectFactory: create1 failed"); SituationMap::RefPointer objPtr2; objPtr2 = objFac.create(layername, QLatin1String("UnitTestId2")); QVERIFY2(objPtr2.valid() == false , "objectFactory: create2 failed"); SituationMap::RefPointer objPtr3; objPtr3 = objFac.create(layername, QLatin1String("UnitTestId3")); QVERIFY2(objPtr3.valid() == false , "objectFactory: create3 failed"); SituationMap::RefPointer objPtr4; objPtr4 = objFac.create(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::ObjectFactory::registerMe(typeid(SituationMap::BiologicalAgent), new SituationMap::GenericObjectFactory()); SituationMap::ObjectFactory::registerMe(typeid(SituationMap::BuildingOutline), new SituationMap::GenericObjectFactory()); SituationMap::ObjectFactory::registerMe(typeid(SituationMap::DangerArea), new SituationMap::GenericObjectFactory()); QVERIFY2(objFac.count() == 0 , "objectFactory: count failed"); // now technicalLayerCount == 1 (basemap) QVERIFY2(mapImplDummy.technicalLayerCount() == 1 , "layerFactory: technicalLayerCount failed"); objPtr1 = objFac.create(layername, QLatin1String("UnitTestId1")); QVERIFY2(objPtr1.valid() == true , "objectFactory: create11 failed"); objPtr2 = objFac.create(layername, QLatin1String("UnitTestId2")); QVERIFY2(objPtr2.valid() == true , "objectFactory: create22 failed"); objPtr3 = objFac.create(layername, QLatin1String("UnitTestId3")); QVERIFY2(objPtr3.valid() == true , "objectFactory: create33 failed"); objPtr4 = objFac.create(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(&layerFac); QVERIFY2(layerFacImpl , "layerFac: dynamic_cast failed"); const QString &rbLayerName = layerFacImpl->rubberbandLayer(); QVERIFY2(rbLayerName.isEmpty() == false , "layerFac: rubberbandLayer failed"); objPtr2 = objFac.create(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(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(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(&layerFac); QVERIFY2(layerFacImpl , "LayerFactory: layerFacImpl failed"); QSharedPointer tactApp = QSharedPointer ( 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 : qAsConst(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 : qAsConst(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 : qAsConst(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 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 activeTracks1 = mtMgr.activeTrackIds(); QVERIFY2(activeTracks1 == QVector() << 4712 << 4713 << 4714, "objectIdsOfActiveTracks failed"); mtMgr.deactivateTrack(4713); // still 3 tracks, but just 2 active: QVERIFY2(mtMgr.size() == 3, "size failed"); const QVector activeTracks2 = mtMgr.activeTrackIds(); QVERIFY2(activeTracks2 == QVector() << 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 activeTracks3 = mtMgr.activeTrackIds(); QVERIFY2(activeTracks3 == QVector() << 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 &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 &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 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(dict); Esri::ArcGISRuntime::DictionarySymbolStyle *esriDict = const_cast(dictImpl.getEsriSymbolDictionary()); QHash baseSymbolCodeToSymbolPropertyTable; connect(esriDict, &Esri::ArcGISRuntime::DictionarySymbolStyle::searchSymbolsCompleted, this, [this, &baseSymbolCodeToSymbolPropertyTable] (QUuid ssTaskId, Esri::ArcGISRuntime::SymbolStyleSearchResultListModel *searchResults) { INFO_LOG(m_logger) << LOGFUNCTION << " proceessing...,ssTaskId " << ssTaskId; // // process all results and store them in member: // const QList &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(); }); // lambda : // lambda connected, start request now: Esri::ArcGISRuntime::SymbolStyleSearchParameters sssp; Esri::ArcGISRuntime::TaskWatcher tw = esriDict->searchSymbols(sssp); QVERIFY2((tw.isValid()), "SymbolDictionary: TaskWatcher failed"); QTest::qWait(2000); QStringList noKey8Entries; QStringList noKey8EntriesOfUnknown; QStringList propsDiffer; for (const AdvancedSymbology::SymbolProperties &symPropItem : qAsConst(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 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 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 : qAsConst(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 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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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(dict); const AdvancedSymbology::SidcCodec::SidcHashTable &allSymbolProps = dictImpl.getEsriDictionaryProcessor()->baseSymbolCodeToSymbolPropertyTable(); for (const AdvancedSymbology::SymbolProperties &prop : qAsConst(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"