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

339 lines
9.4 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Class MovementTrackManager
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "movement_track_manager.h"
// Qt
#include <QVector>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
namespace SituationMap
{
MovementTrackManager::MovementTrackManager(QObject *parent)
: BaseClass(parent)
, m_logger(getLogger("MovementTrackManager"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
init();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MovementTrackManager::~MovementTrackManager()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " size=" << m_cont.size();
m_cont.clear();
TRACE_LOG(m_logger) << LOGFUNCTION << " END ";
}
void MovementTrackManager::init()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_cont.clear();
m_currentTimeMsec = 0;
m_maxNumberOfTracks = 10;
m_maxNumberOfPointsPerTrack = 600; // 600
// min sec msec
m_maxAgeMsec = 30 * 60 * 1000; // (30Min * 60 * 1000= 1 800 000sec)
m_maxViewAgeMsec = 30 * 60 * 1000; // (30Min * 60 * 1000= 1 800 000sec)
m_minDistance = 2; // 2 Meter
// just for testing:
// m_maxNumberOfTracks = 3;
// m_maxAgeMsec = 6000 * 60 * 1000;
// m_maxViewAgeMsec = 6000 * 60 * 1000;
// m_maxNumberOfPointsPerTrack = 10;
// m_minDistance = 0;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QSet<int> MovementTrackManager::setCurrentTimeMsec(qint64 timeMsec)
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " timeMsec=" << timeMsec;
QSet<int> modifiedMapObjects;
if (m_currentTimeMsec == timeMsec)
return modifiedMapObjects;
// forward or backward?
bool forward = timeMsec > m_currentTimeMsec;
m_currentTimeMsec = timeMsec;
QVectorIterator<DATA_T> vecIt(m_cont);
while (vecIt.hasNext())
{
DATA_T item = vecIt.next();
if (!item)
continue;
bool mod;
if (forward)
mod = item->removeEntriesOlder(timeMsec, m_maxAgeMsec);
else
mod = item->removeEntriesNewer(timeMsec); // set time backward -> remove all entries whose time is too new
if (mod)
{
int trackId = item->trackId();
DEBUG_LOG(m_logger) << LOGFUNCTION << " Track changes, simId/trackId=" << trackId
<< " (m_maxAgeMsec=" << m_maxAgeMsec << ")"
<< " (m_maxViewAgeMsec=" << m_maxViewAgeMsec << ")";
modifiedMapObjects.insert(trackId);
}
} // while
// TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " timeMsec=" << timeMsec << " modifiedMapObjects=" << modifiedMapObjects.size();
return modifiedMapObjects;
}
bool MovementTrackManager::addTrack(int trackId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " size=" << m_cont.size() << " trackId=" << trackId;
if (hasTrack(trackId))
return false;
m_cont.push_back(DATA_T(new MovementTrack(trackId)));
if (!m_cont.isEmpty() && (m_cont.size() > m_maxNumberOfTracks))
{
const int trackIdSave = m_cont.first()->trackId();
m_cont.pop_front();
emit trackRemoved(trackIdSave);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END " << " size=" << m_cont.size() << " trackId=" << trackId;
return true;
}
MovementTrackManager::DATA_T MovementTrackManager::getTrack(int trackId) const
{
QVectorIterator<DATA_T> vecIt(m_cont);
while (vecIt.hasNext())
{
DATA_T item = vecIt.next();
if (item && item->trackId() == trackId)
return item;
} // while
return nullptr;
}
void MovementTrackManager::removeTrack(int trackId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " size=" << m_cont.size() << " trackId=" << trackId;
for (int idx = m_cont.size() - 1; idx >= 0; --idx)
{
const DATA_T &item = m_cont.at(idx);
if (item && item->trackId() == trackId)
{
m_cont.removeAt(idx);
emit trackRemoved(trackId);
}
} // for
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " size=" << m_cont.size() << " trackId=" << trackId;
}
void MovementTrackManager::activateTrack(int trackId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " size=" << m_cont.size() << " trackId=" << trackId;
// Eintrag finden
DATA_T track = getTrack(trackId);
if (track)
{
if (!track->isActive())
{
track->setActive(true);
emit trackActivityChanged(trackId, true);
}
}
else
{
addTrack(trackId); // new Track -> active
emit trackActivityChanged(trackId, true);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " size=" << m_cont.size() << " trackId=" << trackId;
}
void MovementTrackManager::deactivateTrack(int trackId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " size=" << m_cont.size() << " trackId=" << trackId;
// 1. find track and save:
DATA_T savedTrack = getTrack(trackId);
if (!savedTrack)
return;
if (!savedTrack->isActive()) // is already deactivated
return;
// 2. remove track:
for (int idx = m_cont.size() - 1; idx >= 0; --idx)
{
const DATA_T &item = m_cont.at(idx);
if (item && item->trackId() == trackId)
m_cont.removeAt(idx);
} // for
// 3. re-add savedTrack:
savedTrack->setActive(false);
m_cont.push_front(savedTrack); // front -> remove candidate / Guez: was push_back!?
emit trackActivityChanged(trackId, false);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " size=" << m_cont.size() << " trackId=" << trackId;
}
bool MovementTrackManager::addPosition(int trackId, const MovementTrack::COORD_T &coord, qint64 timeMsec)
{
DATA_T track = getTrack(trackId);
if (track.isNull())
return false;
return track->addPosition(coord, timeMsec, m_minDistance, m_maxNumberOfPointsPerTrack);
}
PositionCont MovementTrackManager::activeAndVisibleTrack(int trackId) const
{
DATA_T track = getTrack(trackId);
if (!track || !track->isActive())
return PositionCont();
return track->getVisibleTrack(m_currentTimeMsec, m_maxAgeMsec, m_maxViewAgeMsec);
}
void MovementTrackManager::emit_activeSimIdsChanged(const QVector<int32_t> &activeSimIds)
{
emit activeSimIdsChanged(activeSimIds);
}
bool MovementTrackManager::read(const QJsonObject &json)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
this->init();
if (json.contains(QLatin1String("currentTimeMsec")))
this->setCurrentTimeMsec(json[QLatin1String("currentTimeMsec")].toDouble()); // qint64 -> toDouble
if (json.contains(QLatin1String("maxAgeMsec")))
this->setMaxAgeMsec(json[QLatin1String("maxAgeMsec")].toDouble()); // qint64 -> toDouble
if (json.contains(QLatin1String("maxViewAgeMsec")))
this->setMaxViewAgeMsec(json[QLatin1String("maxViewAgeMsec")].toDouble()); // qint64 -> toDouble
if (json.contains(QLatin1String("minDistance")))
this->setMinDistance(json[QLatin1String("minDistance")].toInt());
if (json.contains(QLatin1String("maxNumberOfTracks")))
this->setMaxNumberOfTracks(json[QLatin1String("maxNumberOfTracks")].toInt());
if (json.contains(QLatin1String("maxNumberOfPointsPerTrack")))
this->setMaxNumberOfPointsPerTrack(json[QLatin1String("maxNumberOfPointsPerTrack")].toInt());
// coords
const QJsonArray &jArray = json[QLatin1String("movementTracks")].toArray();
DEBUG_LOG(m_logger) << LOGFUNCTION << " movementTrack QJsonArray size=" << jArray.size();
for (int idx = 0; idx < jArray.size(); ++idx)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " movementTrack QJsonArray, idx=" << idx;
const QJsonObject &objTemp = jArray[idx].toObject();
const QSharedPointer<MovementTrack> &mt = MovementTrack::read(objTemp);
if (!mt)
continue;
if (mt->trackId() >= 0)
m_cont.append(mt);
} // for
// send signals for all tracks:
for (const QSharedPointer<MovementTrack> &mt : qAsConst(m_cont))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " emit trackActivityChanged,"
<< " mt->trackId()=" << mt->trackId()
<< " mt->isActive()=" << mt->isActive();
emit trackActivityChanged(mt->trackId(), mt->isActive());
}
return true;
}
QJsonObject MovementTrackManager::toJsonObject() const
{
QJsonObject json;
json[QLatin1String("currentTimeMsec")] = m_currentTimeMsec;
json[QLatin1String("maxAgeMsec")] = m_maxAgeMsec;
json[QLatin1String("maxViewAgeMsec")] = m_maxViewAgeMsec;
json[QLatin1String("minDistance")] = m_minDistance;
json[QLatin1String("maxNumberOfTracks")] = m_maxNumberOfTracks;
json[QLatin1String("maxNumberOfPointsPerTrack")] = m_maxNumberOfPointsPerTrack;
QJsonArray jArray;
for (const auto &item : m_cont)
{
if (!item)
continue;
QJsonObject objTemp = item->toJsonObject();
jArray.append(objTemp);
}
json[QLatin1String("movementTracks")] = jArray;
return json;
}
QByteArray MovementTrackManager::toJson() const
{
// final - toJson
QJsonDocument jDoc(toJsonObject());
return jDoc.toJson();
}
QVector<int> MovementTrackManager::activeTrackIds() const
{
QVector<int> trackIds;
trackIds.reserve(m_cont.size());
for (const auto &item : m_cont)
{
if (item && item->isActive())
trackIds.append(item->trackId());
}
return trackIds;
}
QVector<int> MovementTrackManager::deactiveTrackIds() const
{
QVector<int> deactiveTrackIds;
deactiveTrackIds.reserve(m_cont.size());
for (const auto &item : m_cont)
{
if (item && !item->isActive())
deactiveTrackIds.append(item->trackId());
}
return deactiveTrackIds;
}
} // namespace GDW_CTC