/** * @RDE_HEADER@ * Class MovementTrack * $Id$ * $HeadURL$ * $Author$ */ // Own #include "movement_track.h" #include // Qt #include #include #include 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 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::getTrack() const { QVector ret; ret.reserve(m_cont.size()); for (const auto &pos : m_cont) ret.push_back(pos); return ret; } QVector 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 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::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 mt = QSharedPointer(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 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