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

269 lines
8.1 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Class MovementTrack
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "movement_track.h"
#include <LtsCoordTrans/lts_coord_trans.h>
// Qt
#include <QVector>
#include <QJsonObject>
#include <QJsonArray>
namespace SituationMap
{
int MovementTrack::m_count = 0;
MovementTrack::MovementTrack(int trackId)
// : m_logger(getLogger("MovementTrack", trackId))
: m_logger(getLogger("MovementTrack"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " trackId/participantId=" << trackId
<< " m_count=" << m_count;
++m_count;
m_trackId = trackId;
m_active = true;
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_trackId=" << m_trackId << " m_count=" << m_count;
}
MovementTrack::~MovementTrack()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_trackId=" << m_trackId << " m_count=" << m_count;
--m_count;
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_trackId=" << m_trackId << " m_count=" << m_count;
}
void MovementTrack::setActive(bool active)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START " << " active=" << active << " m_count=" << m_count;
m_active = active;
}
bool MovementTrack::addPosition(const COORD_T &newPosition,
qint64 currentTimeMsec, double minDistance, int maxNumberOfPositions)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " currentTimeMsec=" << currentTimeMsec
<< " newPosition=" << newPosition
<< " #ofCoords=" << m_cont.size();
bool success = false;
// Very first access?
if (m_cont.isEmpty())
{
m_cont.insert(currentTimeMsec, newPosition);
success = true;
}
else
{
// Avoid identical values:
const COORD_T &lastPosition = m_cont.last();
// isEmpty already checked:
if (lastPosition != newPosition)
{
const double distance = LtsCoordTrans::distance(lastPosition.x(), lastPosition.y(),
newPosition.x(), newPosition.y());
DEBUG_LOG(m_logger) << LOGFUNCTION << " distance " << distance;
if (distance > minDistance)
{
m_cont.insert(currentTimeMsec, newPosition);
success = true;
}
} // if (lastPosition != newPosition)
}
if (!m_cont.isEmpty() &&
(m_cont.size() > maxNumberOfPositions) && (maxNumberOfPositions > 0))
{
// see QTBUG-59373
m_cont.erase(m_cont.begin());
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END " << "success=" << success << " #ofCoords=" << m_cont.size();
return success;
}
bool MovementTrack::removeEntriesNewer(qint64 currentTimeMsec)
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_active=" << m_active << " m_count=" << m_count;
bool modified = false;
QMapIterator<KEY_T, COORD_T> mapIt(m_cont);
mapIt.toBack();
while (mapIt.hasPrevious())
{
mapIt.previous();
if (mapIt.key() > currentTimeMsec)
{
m_cont.remove(mapIt.key());
modified = true;
}
else
break;
} // while
// TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_active=" << m_active << " m_count=" << m_count << " modified=" << modified;
return modified;
}
bool MovementTrack::removeEntriesOlder(qint64 currentTimeMsec, qint64 maxAgeMsec)
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_active=" << m_active << " m_count=" << m_count << " currentTimeMsec=" << currentTimeMsec << " maxAgeMsec=" << maxAgeMsec;
bool modified = false;
auto it = m_cont.begin();
while (it != m_cont.end())
{
const KEY_T &ageMsec = currentTimeMsec - it.key();
if (ageMsec > maxAgeMsec)
{
it = m_cont.erase(it);
modified = true;
}
else
++it;
} // while
// TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_active=" << m_active << " m_count=" << m_count << " modified=" << modified;
return modified;
}
QVector<MovementTrack::COORD_T> MovementTrack::getTrack() const
{
QVector<MovementTrack::COORD_T> ret;
ret.reserve(m_cont.size());
for (const auto &pos : m_cont)
ret.push_back(pos);
return ret;
}
QVector<MovementTrack::COORD_T> MovementTrack::getVisibleTrack(qint64 currentTimeMsec,
qint64 maxAgeMsec,
qint64 maxViewAgeMsec)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_trackId=" << m_trackId << " currentTimeMsec=" << currentTimeMsec << " maxAgeMsec=" << maxAgeMsec << " maxViewAgeMsec=" << maxViewAgeMsec;
removeEntriesOlder(currentTimeMsec, maxAgeMsec);
// Auch wenn keine neuen Positionen eingegangen sind,
// hat sich die Spur evtl. wegen der modifizierten Zeit 'currentTimeMsec'
// geändert:
// uebertragen in validCoords
QVector<MovementTrack::COORD_T> validCoords;
validCoords.reserve(m_cont.size());
for (auto it = m_cont.cbegin(); it != m_cont.cend(); ++it)
{
const KEY_T &ageMsec = currentTimeMsec - it.key();
if (ageMsec > maxViewAgeMsec && maxViewAgeMsec > 0)
continue;
if (ageMsec < 0)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " age is negative!!! - "
<< " currentTimeMsec=" << currentTimeMsec
<< " m_trackId=" << m_trackId
<< " ageMsec=" << ageMsec
<< " - "
<< " size = " << m_cont.size()
<< ", dis = " << std::distance(m_cont.cbegin(), it);
if (ageMsec < -1500)
WARNING_LOG(m_logger) << LOGFUNCTION << " age is negative!!! - "
<< " currentTimeMsec=" << currentTimeMsec
<< " m_trackId=" << m_trackId
<< " ageMsec=" << ageMsec
<< " - "
<< " size = " << m_cont.size()
<< ", dis = " << std::distance(m_cont.cbegin(), it);
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_trackId=" << m_trackId << " ageMsec=" << ageMsec << " coord=" << it.value();
validCoords.push_back(it.value());
} // for
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " validCoords.size()/m_cont.size(): " << validCoords.size() << " / " << m_cont.size();
return validCoords;
}
QSharedPointer<MovementTrack> MovementTrack::read(const QJsonObject &json)
{
if (!json.contains(QLatin1String("trackId")))
return nullptr;
int trackId = -1;
if (json.contains(QLatin1String("trackId")))
trackId = json[QLatin1String("trackId")].toInt();
if (trackId < 0)
return nullptr;
QSharedPointer<MovementTrack> mt =
QSharedPointer<MovementTrack>(new MovementTrack(trackId));
// active
if (json.contains(QLatin1String("active")))
mt->setActive(json[QLatin1String("active")].toBool());
// coordinates
QJsonArray jArray = json[QLatin1String("coordinates")].toArray();
for (int idx = 0; idx < jArray.size(); ++idx)
{
const QJsonObject &objTemp = jArray[idx].toObject();
const KEY_T &timeMsec = objTemp[QLatin1String("pointInTimeMsec")].toDouble(); // toDouble!!!
Point3D p3D;
p3D.rx() = objTemp[QLatin1String("loc_x_lon")].toDouble();
p3D.ry() = objTemp[QLatin1String("loc_y_lat")].toDouble();
if (json.contains(QLatin1String("loc_z")))
p3D.rz() = objTemp[QLatin1String("loc_z")].toDouble();
mt->addPosition(p3D, timeMsec, 0, 0);
} // for
return mt;
}
QJsonObject MovementTrack::toJsonObject() const
{
QJsonObject json;
json[QLatin1String("trackId")] = m_trackId;
json[QLatin1String("active")] = m_active;
QJsonArray jArray;
QMapIterator<KEY_T, COORD_T> it(m_cont);
while (it.hasNext())
{
it.next();
const KEY_T &key = it.key();
const COORD_T &coord = it.value();
QJsonObject jsonCoord;
jsonCoord[QLatin1String("loc_x_lon")] = coord.x();
jsonCoord[QLatin1String("loc_y_lat")] = coord.y();
jsonCoord[QLatin1String("loc_z")] = coord.z();
jsonCoord[QLatin1String("pointInTimeMsec")] = key;
jArray.append(jsonCoord);
}
json[QLatin1String("coordinates")] = jArray;
return json;
}
} // namespace SituationMap