Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+347
@@ -0,0 +1,347 @@
|
||||
/**
|
||||
* Handler for the HMI language
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "object_danger_area.h"
|
||||
#include "special_area_provider.h"
|
||||
|
||||
#include "Utils/polygons.h"
|
||||
#include <QTimer>
|
||||
|
||||
#include "handler_bccontamination.h"
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ngldb/dbtransaction.h>
|
||||
|
||||
namespace AreaEffectSimulation
|
||||
{
|
||||
|
||||
ObjectDangerArea::ObjectDangerArea(MainHandler *mainHandler,
|
||||
QObject *parent)
|
||||
: ObjectBaseTmpl(mainHandler, QStringLiteral("DangerArea"), parent)
|
||||
, m_zone(-1)
|
||||
{
|
||||
connect(m_mainHandler->bcContaminationHandler().get(), &HandlerBase::newAiv,
|
||||
this, &ObjectDangerArea::onNewAiv);
|
||||
connect(m_mainHandler->bcContaminationHandler().get(), &HandlerBase::removeAiv,
|
||||
this, &ObjectDangerArea::onRemoveAiv);
|
||||
}
|
||||
|
||||
ObjectDangerArea::~ObjectDangerArea()
|
||||
{
|
||||
removeTopics();
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectDangerArea::createObject(const Database::AesDangerArea &data,
|
||||
const std::vector<Core::GeoPosition2D> &segmentsDds,
|
||||
const QVector<Database::AesDangerSegment> &segmentsDb)
|
||||
{
|
||||
auto getRightId = [](int id, bool originOc) -> int
|
||||
{
|
||||
return (originOc)?(id*-1):(id);
|
||||
};
|
||||
|
||||
bool originOc = false;
|
||||
m_data = data;
|
||||
|
||||
// New Data!
|
||||
if (m_data.id <= 0)
|
||||
{
|
||||
DBTransaction trans(m_mainHandler->db()->database());
|
||||
m_data.effectStateId = AesEffectState::EsUnknown;
|
||||
if (segmentsDds.size() == 0)
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not create danger area without segments."));
|
||||
|
||||
if (m_data.id < 0) // is the id given as negative? make positive again -> used by OC-Laptop
|
||||
{
|
||||
m_data.id *= -1;
|
||||
m_data.priv_entityId = m_data.id; // OC is using id from Tetra and these are unique
|
||||
originOc = true;
|
||||
}
|
||||
else
|
||||
m_data.id = 0;
|
||||
|
||||
if (!m_mainHandler->db()->insert(m_data))
|
||||
return Core::FunctionReplyObject(getRightId(m_data.id, originOc), tr_lts("dds", "Error inserting AesDangerArea-data into database."));
|
||||
|
||||
m_segments.reserve(segmentsDds.size());
|
||||
for (const Core::GeoPosition2D &segmentDds : segmentsDds)
|
||||
{
|
||||
Database::AesDangerSegment segment;
|
||||
segment.id = 0;
|
||||
segment.dangerAreaId = m_data.privDangerAreaId; // db
|
||||
segment.position = QPointF(segmentDds.lon(), segmentDds.lat());
|
||||
// will update segment.id
|
||||
if (!m_mainHandler->db()->insert(segment))
|
||||
return Core::FunctionReplyObject(getRightId(m_data.id, originOc), tr_lts("dds", "Error inserting AesDangerSegment-data into database."));
|
||||
|
||||
m_segments.append(std::move(segment));
|
||||
}
|
||||
trans.commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_segments = segmentsDb;
|
||||
}
|
||||
m_publishDataTimer->start();
|
||||
checkEnterNewState();
|
||||
|
||||
return Core::FunctionReplyObject(getRightId(m_data.id, originOc));
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectDangerArea::updateObject(const Database::AesDangerArea &data, const std::vector<Core::GeoPosition2D> &segments)
|
||||
{
|
||||
if (segments.size() == 0)
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not modify danger area without segments."));
|
||||
|
||||
DBTransaction trans(m_mainHandler->db()->database());
|
||||
|
||||
auto tmpData = m_data;
|
||||
tmpData.id = std::abs(data.id);
|
||||
// Todo: Why only name and effect Start?
|
||||
tmpData.name = data.name;
|
||||
tmpData.effectStart = data.effectStart;
|
||||
tmpData.properties = data.properties;
|
||||
tmpData.effectStateId = data.effectStateId; // overwrite for oc
|
||||
|
||||
auto tmpSegments = m_segments;
|
||||
const int newSegmentSize = segments.size();
|
||||
// segment count increased
|
||||
for (int i = m_segments.size(); i < newSegmentSize; ++i)
|
||||
{
|
||||
Database::AesDangerSegment segment;
|
||||
segment.dangerAreaId = m_data.privDangerAreaId; // db
|
||||
// will update segment.id
|
||||
if (!m_mainHandler->db()->insert(segment))
|
||||
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error inserting AesMineAreaSegment-data into database."));
|
||||
|
||||
tmpSegments.append(segment);
|
||||
}
|
||||
// segment count decreased
|
||||
for (int i = newSegmentSize; i < m_segments.size(); ++i)
|
||||
{
|
||||
if (!m_mainHandler->db()->removeAesDangerSegment(m_segments.at(i).id))
|
||||
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error removing AesMineAreaSegment-data into database."));
|
||||
}
|
||||
tmpSegments.resize(newSegmentSize); // if count is decreased
|
||||
|
||||
for (size_t i = 0; i < segments.size(); ++i)
|
||||
tmpSegments[i].position = QPointF(segments[i].lon(), segments[i].lat());
|
||||
|
||||
for (const Database::AesDangerSegment &segment : qAsConst(tmpSegments))
|
||||
{
|
||||
if (!m_mainHandler->db()->update(segment))
|
||||
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating AesDangerSegment-data in database."));
|
||||
}
|
||||
|
||||
if (!m_mainHandler->db()->update(tmpData))
|
||||
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating danger area with id %1 in database.")).arg(m_data.id);
|
||||
|
||||
trans.commit();
|
||||
m_data = tmpData;
|
||||
m_segments = tmpSegments;
|
||||
|
||||
m_publishDataTimer->start();
|
||||
checkEnterNewState();
|
||||
|
||||
return Core::FunctionReplyObject(data.id);
|
||||
}
|
||||
|
||||
void ObjectDangerArea::onPublishData()
|
||||
{
|
||||
ObjectBaseTmpl::onPublishData();
|
||||
|
||||
if (!m_mainHandler->db()->update(m_data))
|
||||
ERROR_LOG(m_logger) << "Error updating AesDangeArea-data in database";
|
||||
|
||||
DangerArea ddsData(m_data.id,
|
||||
m_data.name.toStdString(),
|
||||
effectState() == AesEffectState::EsRemoved,
|
||||
false,
|
||||
m_mainHandler->dds()->currentPartitionTimeMSec(),
|
||||
{m_data.chargeTypeId,0,0},
|
||||
m_data.effectDuration,
|
||||
toOptional(toMSec(m_data.effectStart)),
|
||||
effectState(),
|
||||
m_data.effectSourceId,
|
||||
toOptional(m_data.partyId),
|
||||
toOptional(m_data.participantId),
|
||||
m_data.effectMarkingInTa,
|
||||
m_data.externalId,
|
||||
m_data.isCentral,
|
||||
m_data.properties.toStdString(),
|
||||
{},
|
||||
toOptional(m_data.associatedAesId));
|
||||
dbSegment2DdsSegment(m_segments, ddsData.segments());
|
||||
|
||||
m_mainHandler->dds()->dts()->publish(ddsData);
|
||||
publishAiv();
|
||||
}
|
||||
|
||||
void ObjectDangerArea::publishAiv()
|
||||
{
|
||||
// Todo: calculate unique id.
|
||||
// Better than aiv.id(1000 * aesItemId + AesType::AtExplosionArea);
|
||||
|
||||
// Todo: Use Polygons::dangerArea();
|
||||
QPolygonF poly(m_segments.size());
|
||||
for(int i = 0; i < m_segments.size(); ++i)
|
||||
poly[i] = m_segments.at(i).position;
|
||||
|
||||
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());
|
||||
const QRectF bounds(poly.boundingRect());
|
||||
aiv.boundingBoxBottomLeft(Core::GeoPosition2D(bounds.bottomLeft().x(), bounds.bottomLeft().y()));
|
||||
aiv.boundingBoxTopRight(Core::GeoPosition2D(bounds.topRight().x(), bounds.topRight().y()));
|
||||
aiv.aesTypeId(AesType::AtDangerArea);
|
||||
aiv.effectStateId(effectState());
|
||||
aiv.id(1000 * m_data.id + AesType::AtDangerArea);
|
||||
aiv.partyId(0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
m_zone = LtsCoordTrans::UtmCoordinate::fromGeographic(poly[0]).zone;
|
||||
m_utmPoly = utmPolyFromGeoVec(aiv.form(), m_zone);
|
||||
onUpdateCorrelation();
|
||||
|
||||
}
|
||||
|
||||
QPolygonF ObjectDangerArea::utmPolyFromGeoVec(const std::vector<Core::GeoPosition> &geoPos, int zone)
|
||||
{
|
||||
if (geoPos.size() == 0)
|
||||
return QPolygonF();
|
||||
|
||||
int actZone = LtsCoordTrans::UtmCoordinate::fromGeographic(geoPos.at(0).lon(),geoPos.at(0).lat(), zone).zone;
|
||||
|
||||
QPolygonF retVal(geoPos.size());
|
||||
int i=0;
|
||||
for(const auto &pos : geoPos)
|
||||
{
|
||||
LtsCoordTrans::UtmCoordinate utm = LtsCoordTrans::UtmCoordinate::fromGeographic(QPointF(pos.lon(), pos.lat()), actZone);
|
||||
retVal[i++] = QPointF(utm.x, utm.y);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void ObjectDangerArea::removeTopics()
|
||||
{
|
||||
auto dts = m_mainHandler->dds()->dts();
|
||||
dts->removeDangerAreaByKey(m_data.id);
|
||||
dts->removeAesItemViewByKey(1000 * m_data.id + AesType::inner_enum::AtDangerArea);
|
||||
for (int idx : qAsConst(m_correlatedAesItems))
|
||||
dts->removeDangerAreaCorrelatedAesItemByKey(idForCorrelatedItem(idx));
|
||||
m_correlatedAesItems.clear();
|
||||
emit removeAiv(m_data.id);
|
||||
}
|
||||
|
||||
void ObjectDangerArea::onUpdateCorrelation()
|
||||
{
|
||||
// Method Called, when Danger Area changes...
|
||||
|
||||
// If Danger Area is not active, remove correlations and return
|
||||
if (effectState() != AesEffectState::EsActivated)
|
||||
{
|
||||
for(int oldItem : qAsConst(m_correlatedAesItems))
|
||||
m_mainHandler->dds()->dts()->removeDangerAreaCorrelatedAesItemByKey(idForCorrelatedItem(oldItem));
|
||||
m_correlatedAesItems.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
QSet<int> vec;
|
||||
|
||||
// BC Contaminations:
|
||||
const auto bcConts = m_mainHandler->bcContaminationHandler()->forms();
|
||||
QHashIterator<int, std::vector<Core::GeoPosition> > it(bcConts);
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
QPolygonF utmPolyBc = utmPolyFromGeoVec(it.value(), m_zone);
|
||||
if(intersects(m_utmPoly, utmPolyBc))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << QStringLiteral("B/C Area %1 cuts Danger Area %2").arg(it.key()).arg(m_data.id);
|
||||
vec << it.key();
|
||||
}
|
||||
}
|
||||
// Other AesItems go here:
|
||||
// ...
|
||||
|
||||
// Conclude:
|
||||
const QSet<int> newItems = vec - m_correlatedAesItems;
|
||||
const QSet<int> oldItems = m_correlatedAesItems - vec;
|
||||
|
||||
for(int newItem : newItems)
|
||||
{
|
||||
DangerAreaCorrelatedAesItem item;
|
||||
item.id(idForCorrelatedItem(newItem));
|
||||
item.aesItemId(newItem);
|
||||
item.dangerAreaId(m_data.id); // on dds - correct
|
||||
m_mainHandler->dds()->dts()->publish(item);
|
||||
}
|
||||
|
||||
for(int oldItem : oldItems)
|
||||
m_mainHandler->dds()->dts()->removeDangerAreaCorrelatedAesItemByKey(idForCorrelatedItem(oldItem));
|
||||
|
||||
m_correlatedAesItems = m_correlatedAesItems + newItems - oldItems;
|
||||
}
|
||||
|
||||
void ObjectDangerArea::onNewAiv(const AesItemView &itemView)
|
||||
{
|
||||
// Method called, when (other) Aes Items change
|
||||
// Warning: TypeId not in Key, so don't process multiple AIV per Type!
|
||||
|
||||
// Todo: Change here if more than BC is needed
|
||||
if (itemView.aesTypeId() != AesType_def::AtBCContamination)
|
||||
return;
|
||||
|
||||
if (effectState() != AesEffectState_def::EsActivated ||
|
||||
itemView.effectStateId() != AesEffectState_def::EsActivated)
|
||||
{
|
||||
// If ES of this DA or the Contamination changed from(!) Activated to Whatever, kill the correlation
|
||||
m_mainHandler->dds()->dts()->removeDangerAreaCorrelatedAesItemByKey(idForCorrelatedItem(itemView.aesItemId()));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "New Aiv iof Type BC Contamination: " << itemView.aesItemId();
|
||||
QPolygonF utmPolyBc = utmPolyFromGeoVec(itemView.form(), m_zone);
|
||||
if (!intersects(m_utmPoly, utmPolyBc))
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "intersects with Danger Area:" << m_data.id;
|
||||
|
||||
DangerAreaCorrelatedAesItem item;
|
||||
item.id(idForCorrelatedItem(itemView.aesItemId()));
|
||||
item.aesItemId(itemView.aesItemId());
|
||||
item.dangerAreaId(m_data.id);
|
||||
m_mainHandler->dds()->dts()->publish(item);
|
||||
m_correlatedAesItems += itemView.aesItemId();
|
||||
}
|
||||
|
||||
void ObjectDangerArea::onRemoveAiv(int32_t aesItemId)
|
||||
{
|
||||
// Don't worry, if aesItemId is not on bus or in List...
|
||||
m_mainHandler->dds()->dts()->removeDangerAreaCorrelatedAesItemByKey(idForCorrelatedItem(aesItemId));
|
||||
m_correlatedAesItems -= aesItemId;
|
||||
}
|
||||
|
||||
QPolygonF ObjectDangerArea::generateForm()
|
||||
{
|
||||
QPolygonF poly(m_segments.size());
|
||||
for(int i = 0; i < m_segments.size(); ++i)
|
||||
poly[i] = m_segments.at(i).position;
|
||||
|
||||
return poly;
|
||||
}
|
||||
} // Namespace AreaEffectSimulation
|
||||
Reference in new issue
Block a user