Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/AreaEffectSimulation/object_functional_area.cpp
T
berrux-dev 472f537313 Migrates AreaEffectSimulation to generated rtiddsgen API
Converts accessor calls to plain member access across aes service and plugin.
2026-09-21 02:45:07 +02:00

376 lines
13 KiB
C++
Executable File

/**
* Handler for the HMI language
* $Id$
* $HeadURL$
* $Author$
*/
#include "object_functional_area.h"
#include "special_area_provider.h"
#include "Utils/polygons.h"
#include "handler_charge_administration.h"
#include "settings.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QtGui/QPolygonF>
#include <QtCore/QTimer>
#include <cmath>
namespace AreaEffectSimulation
{
ObjectFunctionalArea::ObjectFunctionalArea(MainHandler *mainHandler,
QObject *parent)
: ObjectBaseTmpl(mainHandler, QStringLiteral("FunctionalArea"), parent)
{
}
ObjectFunctionalArea::~ObjectFunctionalArea()
{
delete m_timer;
removeTopics();
}
Core::FunctionReplyObject ObjectFunctionalArea::createObject(const Database::AesFunctionalArea &data)
{
DEBUG_LOG(m_logger) << "ObjectFunctionalArea::createObject aesId=" << data.id
<< " data.effectStateId=" << data.effectStateId;
Core::FunctionReplyObject ret;
bool setIsCentral = false;
m_dataAesFunctionalArea = data;
if (data.supplyMode == AesOperatingMode::OmWaitingTime)
{
setIsCentral = true;
m_data.participantId = data.participantId;
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout,
this, &ObjectFunctionalArea::myTimerSlot, Qt::UniqueConnection);
DEBUG_LOG(m_logger) << "connect participantPositionChanged";
connect(m_mainHandler->dds()->ppmDtc().get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &ObjectFunctionalArea::onParticipantPositionChanged);
DEBUG_LOG(m_logger) << " onParticipantPositionChanged.....";
auto cb = [this](const ParticipantManagement::ParticipantPosition & data)
{
onParticipantPositionChanged(data, DataModification::eAdded);
};
m_mainHandler->dds()->ppmDtc()->participantPositions(cb);
DEBUG_LOG(m_logger) << " onParticipantPositionChanged.....DONE";
}
ret = ObjectBaseTmpl::createObject(m_dataAesFunctionalArea, false, setIsCentral);
return ret;
}
Core::FunctionReplyObject ObjectFunctionalArea::updateObject(const Database::AesFunctionalArea &data)
{
m_dataAesFunctionalArea = data;
Core::FunctionReplyObject ret = ObjectBaseTmpl::updateObject(data);
Q_UNUSED(ret)
if (ret.error() || (isOnlyObjectNameModifiable() && (data.id > 0))) // data.id > 0 -> negative values from oc always get a full update
return ret;
// only allow some fields
auto tmpData(m_data);
tmpData.id = std::abs(data.id);
tmpData.name = data.name;
tmpData.effectStart = data.effectStart;
tmpData.effectDuration = data.effectDuration;
tmpData.position = data.position;
DEBUG_LOG(m_logger) << "tmpData.position=" << data.position.x() << "/" << data.position.y();
tmpData.participantId = data.participantId;
tmpData.partyId = data.partyId;
tmpData.chargeTypeId = data.chargeTypeId;
tmpData.width = data.width;
tmpData.length = data.length;
tmpData.pointSymbol = data.pointSymbol;
tmpData.functionalAreaTypeId = data.functionalAreaTypeId;
tmpData.deconMode = data.deconMode;
tmpData.deconTime = data.deconTime;
tmpData.maintMode = data.maintMode;
tmpData.maintTime = data.maintTime;
tmpData.medicMode = data.medicMode;
tmpData.medicTime = data.medicTime;
tmpData.effectStateId = data.effectStateId; // overwrite for oc
tmpData.properties = data.properties;
if (!m_mainHandler->db()->update(tmpData))
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating functional area with id %1 in database.")).arg(m_data.id);
m_data = std::move(tmpData);
m_publishDataTimer->start();
checkEnterNewState();
return Core::FunctionReplyObject(data.id); // data not m_data for the possible negative id in the oc-laptop
}
Core::FunctionReplyObject ObjectFunctionalArea::removeObject()
{
Core::FunctionReplyObject ret = ObjectBaseTmpl::removeObject();
return ret;
}
bool ObjectFunctionalArea::removeObjectFromDb()
{
return m_mainHandler->db()->removeAesFunctionalArea(m_data.id);
}
void ObjectFunctionalArea::setEffectState(AesEffectState newState)
{
ObjectBaseTmpl::setEffectState(newState);
}
void ObjectFunctionalArea::onPublishData()
{
if (m_data.id == 0)
{
DEBUG_LOG(m_logger) << "ObjectFunctionalArea::onPublishData return";
return;
}
ObjectBaseTmpl::onPublishData();
if (!m_mainHandler->db()->update(m_data))
ERROR_LOG(m_logger) << "Error updating AesFunctionalArea-data in database";
DEBUG_LOG(m_logger) << "onPublishData m_data.position=" << m_data.position.x() << "/" << m_data.position.y()
<< " id=" << m_data.id
<< " effectStateId=" << m_data.effectStateId;
const auto pointSymbol = m_data.pointSymbol.toStdString();
FunctionalArea ddsData(m_data.id,
m_data.name.toStdString(),
effectState() == AesEffectState::EsRemoved,
false,
partitionTimeMSec(),
{m_data.chargeTypeId,0,0},
m_data.effectDuration,
toOptional(toMSec(m_data.effectStart)),
m_data.effectStateId,
m_data.effectSourceId,
toOptional(m_data.partyId),
toOptional(m_data.participantId),
m_data.effectMarkingInTa,
m_data.externalId,
m_data.isCentral,
m_data.properties.toStdString(),
Area(Core::GeoPosition2D(m_data.position.x(),
m_data.position.y()),
m_data.width,
m_data.length,
0.0),
toOptional(pointSymbol),
m_data.functionalAreaTypeId,
m_data.deconMode,
m_data.deconTime,
m_data.maintMode,
m_data.maintTime,
m_data.medicMode,
m_data.medicTime,
m_data.supplyMode,
m_data.supplyTime,
m_data.notfightMode,
m_data.notfightTime
);
m_mainHandler->dds()->dts()->publish(ddsData);
publishAiv();
}
void ObjectFunctionalArea::publishAiv()
{
// Todo: calculate unique id.
// Better than aiv.id(1000 * aesItemId + AesType::AtFunctionalArea);
DEBUG_LOG(m_logger) << "publishAiv";
const QPolygonF poly = Polygons::functionalArea(m_data);
const QRectF bounds(poly.boundingRect());
AesItemView aiv(m_aiv);
aiv.aesItemId = m_data.id;
aiv.chargeStruct.chargeTypeId = m_data.chargeTypeId;
aiv.effectStart = toMSec(m_data.effectStart);
ddsVecFromPoly(poly, aiv.form);
aiv.boundingBoxBottomLeft = Core::GeoPosition2D(bounds.bottomLeft().x(), bounds.bottomLeft().y());
aiv.boundingBoxTopRight = Core::GeoPosition2D(bounds.topRight().x(), bounds.topRight().y());
aiv.aesTypeId = AesType::AtFunctionalArea;
aiv.effectStateId = effectState();
aiv.id = 1000 * m_data.id + static_cast<int>(AesType::AtFunctionalArea);
if (m_data.partyId != 0)
aiv.partyId = m_data.partyId;
checkIsCentralAndPublish(aiv.form, m_aiv.form, m_data.isCentral);
if (aiv != m_aiv)
{
aiv.sampleTime = partitionTimeMSec();
m_aiv = aiv;
m_mainHandler->dds()->dts()->publish(aiv);
emit newAiv(aiv);
}
}
void ObjectFunctionalArea::removeTopics()
{
auto dts = m_mainHandler->dds()->dts();
dts->removeFunctionalAreaByKey(m_data.id);
dts->removeAesItemViewByKey(1000 * m_data.id + static_cast<int>(AesType::AtFunctionalArea));
emit removeAiv(m_data.id);
}
QPolygonF ObjectFunctionalArea::generateForm()
{
return Polygons::functionalArea(m_data);
}
QPointF ObjectFunctionalArea::geographic2Utm(const Core::GeoPosition2D &geoPos, int *zone)
{
const int zoneToUse = zone ? *zone : -1;
auto utm = LtsCoordTrans::UtmCoordinate::fromGeographic(geoPos.lon, geoPos.lat, zoneToUse);
if (zone)
*zone = utm.zone;
return QPointF(utm.x, utm.y);
}
void ObjectFunctionalArea::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
if (modType != DataModification::eRemoved && (data.participantId == m_data.participantId))
{
DEBUG_LOG(m_logger) << " onParticipantPositionChanged....."
<< " participantId=" << data.participantId
<< " aesId=" << m_data.id
<< " suppyParticipantId=" << m_data.participantId;
DEBUG_LOG(m_logger) << "Supply Truck: onParticipantPositionChanged: " << data;
if (m_activePosAvailable)
{
int zone = -1;
DEBUG_LOG(m_logger) << "New Supply Truck Position participantId: " << data.participantId
<< " pos: lat=" << data.pos.lat << " lon=" << data.pos.lon;
const QPointF participantPosUtmPoint = geographic2Utm(data.pos, &zone);
DEBUG_LOG(m_logger) << "participantPosUtmPoint=" << participantPosUtmPoint.x() << "/" << participantPosUtmPoint.y()
<< " zone=" << zone;
const QPointF activationPosUtmPoint = geographic2Utm(m_activatePos, &zone);
DEBUG_LOG(m_logger) << "activationPosUtmPoint=" << activationPosUtmPoint.x() << "/" << activationPosUtmPoint.y()
<< " zone=" << zone;
//double squareDistance = LtsCoordTrans::squareDistance(participantPosUtmPoint, activationPosUtmPoint);
const double distanceSquared = LtsCoordTrans::squareDistance(data.pos.lon, data.pos.lat, m_activatePos.lon, m_activatePos.lat);
DEBUG_LOG(m_logger) << "squareDistance=" << distanceSquared
<< " distance = " << sqrt(distanceSquared)
<< " getMaximumStepLengthStanding=" << Settings::getMaximumStepLengthStanding();
// vehicle does not move
if (distanceSquared < Settings::getMaximumStepLengthStanding() * Settings::getMaximumStepLengthStanding())
{
DEBUG_LOG(m_logger) << "Supply Truck is not moving";
return;
}
else
{
DEBUG_LOG(m_logger) << "Supply Truck is moving! state=" << m_data.effectStateId;
if (m_data.effectStateId == AesEffectState::EsActivated)
{
m_data.effectStateId = AesEffectState::EsPaused;
m_dataAesFunctionalArea.effectStateId = AesEffectState::EsPaused;
DEBUG_LOG(m_logger) << "Supply Truck is moving Timer neu setzen!";
updateTimer();
}
}
}
m_data.position.setX(data.pos.lon);
m_data.position.setY(data.pos.lat);
m_data.partyId = data.partyId;
m_data.isCentral = true;
m_dataAesFunctionalArea.position.setX(data.pos.lon);
m_dataAesFunctionalArea.position.setY(data.pos.lat);
m_dataAesFunctionalArea.partyId = data.partyId;
m_dataAesFunctionalArea.isCentral = true;
{
int zone = -1;
const QPointF participantPosUtmPoint = geographic2Utm(data.pos, &zone);
QPointF utmPointShift;
utmPointShift.setX(participantPosUtmPoint.x() - m_dataAesFunctionalArea.length / 2);
utmPointShift.setY(participantPosUtmPoint.y() - m_dataAesFunctionalArea.width / 2);
DEBUG_LOG(m_logger) << "data.pos=" << data.pos
<< " participantPosUtmPoint=" << participantPosUtmPoint.x() << "/" << participantPosUtmPoint.y()
<< " utmPointShift=" << utmPointShift.x() << "/" << utmPointShift.y()
<< " length=" << m_dataAesFunctionalArea.length
<< " width=" << m_dataAesFunctionalArea.width;
Core::GeoPosition2D posShift;
LtsCoordTrans::UtmCoordinate utm;
utm.x = utmPointShift.x();
utm.y = utmPointShift.y();
utm.zone = zone;
QPointF point = utm.geographic();
m_activatePos.lon = point.x();
m_activatePos.lat = point.y();
m_dataAesFunctionalArea.position.setX(point.x());
m_dataAesFunctionalArea.position.setY(point.y());
m_data.position.setX(point.x());
m_data.position.setY(point.y());
DEBUG_LOG(m_logger) << "m_activatePos=" << m_activatePos;
}
m_activePosAvailable = true;
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: Vor updateObject";
updateObject(m_dataAesFunctionalArea);
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: Vor onPublishData";
onPublishData();
}
}
void ObjectFunctionalArea::updateTimer()
{
DEBUG_LOG(m_logger) << "TargetTimer::updateTimer t=" << Settings::getActivationTimeAfterStopSupplyTruck();
m_timer->setSingleShot(true);
m_timer->start(Settings::getActivationTimeAfterStopSupplyTruck());
}
void ObjectFunctionalArea::myTimerSlot()
{
// m_activePosAvailable = false;
m_data.effectStateId = AesEffectState::EsActivated;
m_dataAesFunctionalArea.effectStateId = AesEffectState::EsActivated;
DEBUG_LOG(m_logger) << "TimerSlot Setze Supply-Truck active aesItemId=" << m_aiv.aesItemId
<< " participantId=" << m_data.participantId
<< " effectStateId=" << m_data.effectStateId;
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: Vor updateObject";
updateObject(m_dataAesFunctionalArea);
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: Vor onPublishData";
onPublishData();
}
} // Namespace AreaEffectSimulation