1160 lines
42 KiB
C++
Executable File
1160 lines
42 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* ISM Custom functions (extends ism_db_impl.cpp/.h)
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Iuliana Ojog, SLSE, 2016-11-26
|
|
*/
|
|
|
|
#include "ism_dtc_impl_custom.h"
|
|
#include "ism_dtc_impl_custom_p.h"
|
|
|
|
#include <DDS/DTC/generic_dtc.h>
|
|
#include <DDS/Generic/generic_data_reader.h>
|
|
#include <LtsUtilsCore/json_object.h>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
|
|
|
|
#include <QSet>
|
|
#include <QVector>
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonParseError>
|
|
#include <QtGui/QPolygonF>
|
|
#include <QtGui/QTransform>
|
|
#include <unordered_map>
|
|
#include <algorithm>
|
|
#include <QFile>
|
|
|
|
#include <QMutex>
|
|
#include <QMutexLocker>
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
namespace InfrastructureManagement
|
|
{
|
|
namespace Interface
|
|
{
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// [GUEZE-3258] Performance-Untersuchung der OpApp
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
// 10.01.2025, Norbert Thoden
|
|
// Das Starten dieses Plugins ist teuer, da viele (ca. 500) MainStructureElement
|
|
// mit noch mehr (~25000) StructureElements
|
|
// Es wurde
|
|
// - auf relevante Gebäude gefiltert
|
|
// - ForeignInterfaceImpl::init() mit QtConcurrent beschleunigt.
|
|
// - 2025: getStructureElementById ist es wert, beschleunigt zu werden.
|
|
// Daher wurde ein Cache erstellt: structureElementCache
|
|
// - diese Cache wird via QSignal mainStructureElementChanged aktualisert.
|
|
// - Es muss dabei aber sichergestellt werden, dass dies
|
|
// aktualisert, _BEVOR_ andere slots von mainStructureElementChanged
|
|
// aufgerufen werden und möglicherweise getStructureElementById nutzen!!!
|
|
// Also muss das connect im ctor von DtcImplCustom durchgeführt werden.
|
|
// - Bzgl. ForeignInterfaceImpl::init() ist es also wichtig, das structureElementCache
|
|
// auf Stand ist.
|
|
// 2025 zeigt sich, das ein fremdes Plugin (CDS) als erstes das mainStructureElement
|
|
// enabled. Darauf möchte man sich aber ja nicht verlassen.
|
|
// Szenario: direct das ResourcenManagement starten:
|
|
// ./bin/OperatorApplication -b guez -l de_DE -u Norbert -p xxx -a 1
|
|
// In getStructureElementById() ist es allerdings auch nicht so einfach, da
|
|
// es auch verschiedenen Threads aufgerufen werden kann und dann Abstürze drohen...
|
|
// Daher wird reloadStructureElementCacheIfEmpty inkl. Mutext eingeführt.
|
|
// - Den structureElementCache mache wir nicht static, da anderen Übungen
|
|
// möglicherweise andere Gebäude o.a. haben.
|
|
//------------------------------------------------------------------------------
|
|
// Classes anmd files:
|
|
// source Lts/Plugins/InfrastructureManagement/Data/ism_data_plugin.cpp
|
|
// Lts/Plugins/InfrastructureManagement/Data/ism_foreign_data_plugin.cpp
|
|
// Lts/Services/InfrastructureManagement/ism_dtc_impl_custom.cpp
|
|
// build Lts/Services/InfrastructureManagement/ism_dtc_impl.h
|
|
// Dtc
|
|
// ^
|
|
// |
|
|
// DtcImpl
|
|
// ^
|
|
// |
|
|
// DtcImplCustom
|
|
//
|
|
// DataPlugin has member m_dtc and m_foreignInterface (ForeignInterfaceImpl)
|
|
// -> ForeignInterfaceImpl can just call methods of the Interface 'Dtc'.
|
|
// Calling methods of DtcImpl or DtcImplCustom is difficult.
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
// class Interface::Private
|
|
//------------------------------------------------------------------------------
|
|
class DtcImplCustom::Private
|
|
{
|
|
public:
|
|
Private() = default;
|
|
~Private()
|
|
{}
|
|
|
|
MainFootPrintCache mainFootPrintCacheGroundLevel;
|
|
QHash<int, StructureElement> structureElementCache;
|
|
};
|
|
|
|
|
|
DtcImplCustom::DtcImplCustom(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector)
|
|
: DtcImpl(ddsConnector)
|
|
, d(new Private)
|
|
{
|
|
// 1.
|
|
d->mainFootPrintCacheGroundLevel.init(this);
|
|
|
|
// 2.
|
|
// [GUEZE-3258] Performance-Untersuchung der OpApp
|
|
// Norbert Thoden, Patric Karwat, Gerlinde Rudolphus 09.01.2025
|
|
// We should be the very first connecting the that signal to guarantee,
|
|
// the slot being called _before_ all other slots are called!!!!!
|
|
// Since the DtcImpl is created within this ctor, that should be true
|
|
connect(this, &DtcImpl::mainStructureElementChanged,
|
|
this, &DtcImplCustom::updateStructureElementCache, Qt::DirectConnection);
|
|
|
|
// // reloadStructureElementCache(); // reloadStructureElementCache an dieser Stelle führt zu einem Crash in svcAudioVideoManagment - grr
|
|
}
|
|
|
|
DtcImplCustom::~DtcImplCustom()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void DtcImplCustom::reloadStructureElementCacheIfEmpty()
|
|
{
|
|
static QMutex s_mutex;
|
|
QMutexLocker locker(&s_mutex);
|
|
if (!d->structureElementCache.isEmpty())
|
|
return;
|
|
reloadStructureElementCache();
|
|
}
|
|
|
|
long DtcImplCustom::reloadStructureElementCache()
|
|
{
|
|
DEBUG_LOG(m_logger) << "ISM::StructureElementCache: reloadStructureElementCache; START, structureElementCacheSize = " << structureElementCacheSize();
|
|
|
|
// BENCHMARK_SETUP_AND_START(); // struggle on link of QElapesedTimer - grrr
|
|
|
|
waitForHistoricalDataMainStructureElement(1000);
|
|
|
|
d->structureElementCache.clear();
|
|
//const auto &data = m_dtcMainStructureElement->readAlive();
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
updateStructureElementCache(sample, DataModification::eAdded);
|
|
|
|
DEBUG_LOG(m_logger) << "ISM::StructureElementCache: reloadStructureElementCache; END, structureElementCacheSize = " << structureElementCacheSize();
|
|
|
|
return d->structureElementCache.size();
|
|
}
|
|
|
|
void DtcImplCustom::updateStructureElementCache(const MainStructureElement &mse, DataModification modType)
|
|
{
|
|
static bool bIsVeryFirstCall = true;
|
|
if (bIsVeryFirstCall)
|
|
{
|
|
DEBUG_LOG(m_logger) << "ISM::StructureElementCache: updateStructureElementCache starts";
|
|
bIsVeryFirstCall = false;
|
|
}
|
|
|
|
const std::vector<InfrastructureManagement::StructureElement>& ses = mse.elements();
|
|
for (const auto &se : ses)
|
|
{
|
|
if (modType==DataModification::eRemoved)
|
|
d->structureElementCache.remove(se.id());
|
|
else
|
|
d->structureElementCache[se.id()] = se;
|
|
} // for
|
|
|
|
DEBUG_LOG(m_logger) << "ISM::StructureElementCache updateStructureElementCache, new size = " << d->structureElementCache.size();
|
|
}
|
|
|
|
long DtcImplCustom::structureElementCacheSize() const
|
|
{
|
|
return d->structureElementCache.size();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::isElementAssignedToExercise(const MainStructureElement &mse, int exerciseId) const
|
|
{
|
|
const QJsonObject obj(LtsUtils::JsonObject::fromJson(mse.properties()));
|
|
auto it = obj.find(QStringLiteral("available_in_exercise"));
|
|
if (it == obj.end())
|
|
{
|
|
INFO_LOG(m_logger) << "Main structure element id " << mse.id() << ": Attribute \"available_in_exercise\" not found. Ignoring...";
|
|
return false;
|
|
}
|
|
|
|
const QJsonArray arr = (*it).toArray();
|
|
if (std::any_of(arr.begin(), arr.end(), [exerciseId](const QJsonValue & val) { return val.isDouble() && exerciseId == val.toInt(); }))
|
|
return true;
|
|
|
|
INFO_LOG(m_logger) << "Main structure element id " << mse.id() << ": Not assigned (\"available_in_exercise\") to current exercise which has id " << exerciseId << ". Ignoring...";
|
|
return false;
|
|
}
|
|
|
|
// tested in ISM Module Tests
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getMountingPointAssetId(int structureElementId, int assetId, int &mountingPointAssetId) const
|
|
{
|
|
// Returns valid MpaId, if one or both input Values are set.
|
|
for (const auto &sample : m_dtcMountingPointAsset->readAlive())
|
|
{
|
|
DEBUG_LOG(m_logger) << "getMountingPointAssetId: "
|
|
<< " sample.data().structureElementId()=" << sample.data().structureElementId()
|
|
<< " structureElementId=" << structureElementId
|
|
<< " sample.data().assetId()=" << sample.data().assetId()
|
|
<< " assetId" << assetId;
|
|
if ((sample.data().structureElementId() == structureElementId || structureElementId <= 0) &&
|
|
(sample.data().assetId() == assetId || assetId <= 0))
|
|
{
|
|
mountingPointAssetId = sample.data().id();
|
|
return true;
|
|
}
|
|
}
|
|
mountingPointAssetId = 0;
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getAssetIdFromMountingPoint(int structureElementId, int mountingPointAssetId, int &assetId) const
|
|
{
|
|
// Returns valid MpaId, if one or both input Values are set.
|
|
for (const auto &sample : m_dtcMountingPointAsset->readAlive())
|
|
{
|
|
TRACE_LOG(m_logger) << "getAssetIdFromMountingPoint:"
|
|
<< " structureElementId=" << structureElementId
|
|
<< " mountingPointAssetId=" << mountingPointAssetId
|
|
<< " sample.data().id()=" << sample.data().id()
|
|
<< " sample.data().structureElementId()=" << sample.data().structureElementId()
|
|
<< " sample.data().assetId()=" << sample.data().assetId();
|
|
if (sample.data().structureElementId() == structureElementId)
|
|
{
|
|
assetId = sample.data().assetId();
|
|
return true;
|
|
}
|
|
}
|
|
assetId = 0;
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
int DtcImplCustom::getOpsCodeFromJSon(const std::string &s) const
|
|
{
|
|
QJsonParseError jError;
|
|
QJsonDocument doc(QJsonDocument::fromJson(s.c_str(), &jError));
|
|
if (jError.error != QJsonParseError::NoError ||
|
|
!doc.isObject())
|
|
{
|
|
ERROR_LOG(m_logger) << "Can not read json data from IPS asset - properties are not parsable: "
|
|
<< jError.errorString() << " - '" << s << "'";
|
|
return 0;
|
|
}
|
|
QJsonObject obj(doc.object());
|
|
return obj[QStringLiteral("opticalCode")].toInt();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
int DtcImplCustom::getOpticalCodeFromAssetId(int assetId) const
|
|
{
|
|
|
|
DEBUG_LOG(m_logger) << "getOpticalCodeFromAsset: assetId=" << assetId;
|
|
// Returns valid MpaId, if one or both input Values are set.
|
|
for (const InfrastructureManagement::InstrumentationAsset &instrumentationAsset : m_dtcInstrumentationAsset->readAlive())
|
|
{
|
|
DEBUG_LOG(m_logger) << "getAssetIdFromOpticalCode:"
|
|
<< instrumentationAsset.properties();
|
|
if ((instrumentationAsset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::IndoorIPS)
|
|
|| (instrumentationAsset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::OutdoorIPS))
|
|
{
|
|
DEBUG_LOG(m_logger) << "getOpticalCodeFromAsset:"
|
|
<< " assetId=" << instrumentationAsset.id()
|
|
<< " opticalCode=" << getOpsCodeFromJSon(instrumentationAsset.properties());
|
|
if (assetId == instrumentationAsset.id())
|
|
return getOpsCodeFromJSon(instrumentationAsset.properties());
|
|
}
|
|
}
|
|
return assetId;
|
|
|
|
|
|
|
|
}
|
|
|
|
int DtcImplCustom::getAssetIdFromOpticalCode(int opticalCode) const
|
|
{
|
|
DEBUG_LOG(m_logger) << "getAssetIdFromOpticalCode: opticalCode=" << opticalCode;
|
|
int assetId = -1;
|
|
// Returns valid MpaId, if one or both input Values are set.
|
|
for (const InfrastructureManagement::InstrumentationAsset &instrumentationAsset : m_dtcInstrumentationAsset->readAlive())
|
|
{
|
|
DEBUG_LOG(m_logger) << "getAssetIdFromOpticalCode:"
|
|
<< instrumentationAsset.properties();
|
|
if ((instrumentationAsset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::IndoorIPS)
|
|
|| (instrumentationAsset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::OutdoorIPS))
|
|
{
|
|
DEBUG_LOG(m_logger) << "getAssetIdFromOpticalCode:"
|
|
<< instrumentationAsset.properties();
|
|
int opticalCodeAsset = getOpsCodeFromJSon(instrumentationAsset.properties());
|
|
if (opticalCodeAsset == opticalCode)
|
|
return instrumentationAsset.id();
|
|
}
|
|
}
|
|
return assetId;
|
|
}
|
|
|
|
int DtcImplCustom::getAssetIdFromMountingPointId(int mainStructureElementId, int mountingPointId) const
|
|
{
|
|
DEBUG_LOG(m_logger) << "getAssetIdFromMountingPointId mainStructureElementId=" << mainStructureElementId
|
|
<< " mountingPointId=" << mountingPointId;
|
|
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
if (sample.data().id() != mainStructureElementId)
|
|
continue;
|
|
|
|
for (const StructureElement &elem : sample.data().elements())
|
|
{
|
|
DEBUG_LOG(m_logger) << "elem.id=" << elem.id()
|
|
<< " elem.mountingPointId=" << elem.mountingPointId();
|
|
if (elem.mountingPointId() == mountingPointId)
|
|
{
|
|
return (getMountedAssetId(elem.id()));
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
bool DtcImplCustom::getOpsDataFromMseIdAndSeId(int mainStructureElementId, int structureElementId, int &roomId, Core::GeoPosition &geoPosition) const
|
|
{
|
|
DEBUG_LOG(m_logger) << "getOpsDataFromMseIdAndSeId"
|
|
<< " mainStructureElementId=" << mainStructureElementId
|
|
<< " structureElementId=" << structureElementId;
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
if (sample.data().id() != mainStructureElementId)
|
|
continue;
|
|
|
|
for (const StructureElement &elem : sample.data().elements())
|
|
{
|
|
DEBUG_LOG(m_logger) << "elem.id=" << elem.id()
|
|
<< " elem.mountingPointId=" << elem.mountingPointId()
|
|
<< " elem.path().size=" << elem.path().size();
|
|
if (elem.id() == structureElementId)
|
|
{
|
|
if (elem.path().size() > 1)
|
|
roomId = elem.path().at(elem.path().size() - 2);
|
|
geoPosition = elem.geoPosition();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// tested in ISM Module Tests
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getStructureElementById(int structureElementId, StructureElement &structureElement) const
|
|
{
|
|
// initial code: (but slow on 500 bldgs, ~25000 structureElements)
|
|
// const auto &data = m_dtcMainStructureElement->readAlive();
|
|
// for (const auto &sample : data)
|
|
// {
|
|
// for (const StructureElement &elem : sample.data().elements())
|
|
// {
|
|
// if (elem.id() == structureElementId)
|
|
// {
|
|
// structureElement = elem;
|
|
// return true;
|
|
// }
|
|
// }
|
|
// }
|
|
// return false;
|
|
|
|
|
|
// not reliable (since threading)
|
|
// if (d->structureElementCache.isEmpty())
|
|
// {
|
|
// DtcImplCustom *THIS = const_cast<DtcImplCustom *>(this); // cast const away
|
|
// THIS->reloadStructureElementCache();
|
|
// }
|
|
|
|
// Attention: this method is called from different threads.
|
|
|
|
{
|
|
DtcImplCustom *NON_CONST_THIS = const_cast<DtcImplCustom *>(this); // cast const away
|
|
NON_CONST_THIS->reloadStructureElementCacheIfEmpty();
|
|
}
|
|
|
|
// use cache:
|
|
const auto& it = d->structureElementCache.find(structureElementId);
|
|
if (it != d->structureElementCache.end())
|
|
{
|
|
structureElement = *it;
|
|
return true;
|
|
}
|
|
|
|
|
|
DEBUG_LOG(m_logger) << "ISM::StructureElementCache old approach is used";
|
|
|
|
// fallback: old approach
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
for (const StructureElement &elem : sample.data().elements())
|
|
{
|
|
if (elem.id() == structureElementId)
|
|
{
|
|
structureElement = elem;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getStructureElementInMntPointAssetByAssetId(int assetId, StructureElement &structureElement) const
|
|
{
|
|
int structureElementId = 0;
|
|
for (const auto &sample : m_dtcMountingPointAsset->readAlive())
|
|
{
|
|
if (sample.data().assetId() == assetId)
|
|
{
|
|
structureElementId = sample.data().structureElementId();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (structureElementId == 0)
|
|
return false;
|
|
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
for (const StructureElement &elem : sample.data().elements())
|
|
{
|
|
if (elem.id() == structureElementId)
|
|
{
|
|
structureElement = elem;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getStructureElementByBuildingIdAndMountingPointId(int mainStructureElementId, int mountingPointId, StructureElement &structureElement)
|
|
{
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
if (sample.data().id() != mainStructureElementId)
|
|
continue;
|
|
|
|
for (const StructureElement &elem : sample.data().elements())
|
|
{
|
|
if (elem.mountingPointId() == mountingPointId)
|
|
{
|
|
structureElement = elem;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getAllAssetsPerRoom(const std::function<bool(const InstrumentationAsset &)> &predicate,
|
|
QMap<int, QVector<InstrumentationAsset> > &allAssets)
|
|
{
|
|
using DATA_A = InfrastructureManagement::InstrumentationAsset;
|
|
using LOANED_DATA_A = rti::sub::LoanedSample<DATA_A>;
|
|
|
|
using DATA_MPA = InfrastructureManagement::MountingPointAsset;
|
|
using LOANED_DATA_MPA = rti::sub::LoanedSample<DATA_MPA>;
|
|
|
|
using DATA_MSE = InfrastructureManagement::MainStructureElement;
|
|
using LOANED_DATA_MSE = rti::sub::LoanedSample<DATA_MSE>;
|
|
|
|
dds::sub::LoanedSamples<DATA_A> samples_a = m_dtcInstrumentationAsset->readAlive();
|
|
std::unordered_map<int, LOANED_DATA_A> assetMap;
|
|
for (const LOANED_DATA_A &asset : samples_a)
|
|
assetMap.insert(std::make_pair(asset.data().id(), asset));
|
|
|
|
dds::sub::LoanedSamples<DATA_MSE> samples_mse = m_dtcMainStructureElement->readAlive();
|
|
std::unordered_map<int, InfrastructureManagement::StructureElement> structElementMap;
|
|
for (const LOANED_DATA_MSE &mse : samples_mse)
|
|
for (const auto &se : mse.data().elements())
|
|
structElementMap.insert(std::make_pair(se.id(), se));
|
|
|
|
dds::sub::LoanedSamples<DATA_MPA> samples_mpa = m_dtcMountingPointAsset->readAlive();
|
|
for (const LOANED_DATA_MPA &mpa : samples_mpa)
|
|
{
|
|
const int assetId = mpa.data().assetId();
|
|
const auto assetIt = assetMap.find(assetId);
|
|
if (assetIt == assetMap.end())
|
|
continue;
|
|
if (!predicate(assetIt->second))
|
|
continue;
|
|
|
|
const int structureElementId = mpa.data().structureElementId();
|
|
const auto structureElementIt = structElementMap.find(structureElementId);
|
|
if (structureElementIt == structElementMap.end())
|
|
continue;
|
|
|
|
const InfrastructureManagement::StructureElement &se = structureElementIt->second;
|
|
if (se.structureElementTypeId() != InfrastructureManagement::StructureElementType::MountingPoint)
|
|
continue;
|
|
int roomId = 0;
|
|
if (se.path().size() > 1)
|
|
roomId = se.path().at(se.path().size() - 2);
|
|
allAssets[roomId].push_back(assetIt->second);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getAllAssetsPerBuilding(const std::function<bool(const InstrumentationAsset &)> &predicate,
|
|
QMap<int, QVector<InstrumentationAsset> > &allAssets) const
|
|
{
|
|
using DATA_A = InfrastructureManagement::InstrumentationAsset;
|
|
using LOANED_DATA_A = rti::sub::LoanedSample<DATA_A>;
|
|
|
|
using DATA_MPA = InfrastructureManagement::MountingPointAsset;
|
|
using LOANED_DATA_MPA = rti::sub::LoanedSample<DATA_MPA>;
|
|
|
|
dds::sub::LoanedSamples<DATA_A> samples_a = m_dtcInstrumentationAsset->readAlive();
|
|
std::unordered_map<int, LOANED_DATA_A> assetMap;
|
|
for (const LOANED_DATA_A &asset : samples_a)
|
|
assetMap.insert(std::make_pair(asset.data().id(), asset));
|
|
|
|
dds::sub::LoanedSamples<DATA_MPA> samples_mpa = m_dtcMountingPointAsset->readAlive();
|
|
for (const LOANED_DATA_MPA &mpa : samples_mpa)
|
|
{
|
|
const int assetId = mpa.data().assetId();
|
|
DEBUG_LOG(m_logger) << "Found assetId = " << assetId;
|
|
const auto assetIt = assetMap.find(assetId);
|
|
if (assetIt == assetMap.end())
|
|
continue;
|
|
if (!predicate(assetIt->second))
|
|
continue;
|
|
|
|
const int structureElementId = mpa.data().structureElementId();
|
|
int buildingId = 0;
|
|
if (getBuildingId(structureElementId, buildingId))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Found buildingId = " << buildingId << ", assetId = " << assetId;
|
|
allAssets[buildingId].push_back(assetIt->second);
|
|
}
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getBuildingId(int structureElementId, int &buildingId) const
|
|
{
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
for (const auto &se : sample.data().elements())
|
|
{
|
|
if (se.id() == structureElementId)
|
|
{
|
|
buildingId = sample.data().id();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
buildingId = 0;
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
QList<int> DtcImplCustom::getSections()
|
|
{
|
|
QList<int> sections;
|
|
for (const auto &sample : m_dtcMainStructureElement->readAlive())
|
|
{
|
|
if (!sections.contains(sample.data().groupId()))
|
|
sections.append(sample.data().groupId());
|
|
}
|
|
return sections;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
QString DtcImplCustom::getBuildingDisplayName(int buildingId)
|
|
{
|
|
return getBuildingDisplayName(mainStructureElement(buildingId));
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
QString DtcImplCustom::getBuildingDisplayName(const MainStructureElement &mse) const
|
|
{
|
|
for (const StructureElement &elem : mse.elements())
|
|
{
|
|
if ((elem.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building) ||
|
|
(elem.structureElementTypeId() == InfrastructureManagement::StructureElementType::Bridge))
|
|
{
|
|
if (elem.displayName().size() > 0)
|
|
return QString::fromStdString(elem.displayName());
|
|
}
|
|
}
|
|
return QString::fromStdString(mse.name());
|
|
}
|
|
|
|
|
|
MountingPointPlan DtcImplCustom::getMountingPointPlan(int scheduleId, int structureElementId) const
|
|
{
|
|
for (const auto &sample : m_dtcMainSchedule->readAlive())
|
|
{
|
|
if (sample.data().id() == scheduleId)
|
|
{
|
|
for (auto &mpp : sample.data().elements())
|
|
{
|
|
if (mpp.structureElementId() == structureElementId)
|
|
return mpp;
|
|
}
|
|
}
|
|
}
|
|
return MountingPointPlan();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
int DtcImplCustom::getBuildingRoomsCount(int buildingId)
|
|
{
|
|
int roomCount = 0;
|
|
const MainStructureElement mse = mainStructureElement(buildingId);
|
|
if (mse.id() > 0)
|
|
{
|
|
for (const StructureElement &elem : mse.elements())
|
|
{
|
|
if (elem.structureElementTypeId() == InfrastructureManagement::StructureElementType::Room)
|
|
roomCount++;
|
|
}
|
|
}
|
|
return roomCount;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
BridgeStatus DtcImplCustom::getBridgeStatus(int buildingId)
|
|
{
|
|
BridgeStatus ret = BridgeStatus::Intact;
|
|
const MainStructureElement mse = mainStructureElement(buildingId);
|
|
if (mse.id() > 0 && mse.structureElementTypeId() == StructureElementType::Bridge)
|
|
{
|
|
const QJsonObject obj(LtsUtils::JsonObject::fromJson(mse.properties()));
|
|
auto it = obj.find(QStringLiteral("bridgeStatus"));
|
|
if (it == obj.end())
|
|
return ret;
|
|
int st = (*it).toInt();
|
|
if (st >= 1)
|
|
ret = BridgeStatus::Broken;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// this is just a quicker method to determine if a plan is complete or not
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::checkSchedule(int scheduleId)
|
|
{
|
|
const MainSchedule schedule = mainSchedule(scheduleId);
|
|
for (const MountingPointPlan &mpp : schedule.elements()) //
|
|
{
|
|
if (mpp.mountingPointState() == MountingPointState::Idle) // whatever mounted or unmounted should be ok ?
|
|
continue;
|
|
int assetId = getMountedAssetId(mpp.structureElementId());
|
|
if (mpp.mountingPointState() == MountingPointState::Empty && assetId != -1) //mounted, but it should be empty
|
|
return false;
|
|
else if (mpp.mountingPointState() == MountingPointState::Equipped && assetId == -1) // not mounted, but it should be
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// this gives us info about differences too
|
|
//---------------------------------------------------------------------------------------------------------------------------------------------
|
|
bool DtcImplCustom::getScheduleDifferences(int scheduleId, QList<MountingPointPlan> &diffList)
|
|
{
|
|
const MainSchedule schedule = mainSchedule(scheduleId);
|
|
for (const MountingPointPlan &mpp : schedule.elements()) //
|
|
{
|
|
if (mpp.mountingPointState() == MountingPointState::Idle) // whatever mounted or unmounted should be ok ?
|
|
continue;
|
|
int assetId = getMountedAssetId(mpp.structureElementId());
|
|
if (mpp.mountingPointState() == MountingPointState::Empty && assetId != -1) //mounted, but it should be empty
|
|
diffList.append(mpp);
|
|
else if (mpp.mountingPointState() == MountingPointState::Equipped && assetId == -1) // not mounted, but it should be
|
|
diffList.append(mpp);
|
|
}
|
|
return diffList.isEmpty();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------
|
|
int DtcImplCustom::getMountedAssetId(int structureElementId) const
|
|
{
|
|
// Norbert Thoden, 12.12.2022:
|
|
// implementation could be slow
|
|
// consider using prepared ISM::MountingPoints, prepared at loading of plugion:
|
|
// InfrastructureManagement::ForeignDataInterface m_dataInterface;
|
|
// m_dataInterface->mountingPoint(mountingPointId).associatedAssetId();
|
|
|
|
using DATA_MPA = InfrastructureManagement::MountingPointAsset;
|
|
using LOANED_DATA_MPA = rti::sub::LoanedSample<DATA_MPA>;
|
|
|
|
dds::sub::LoanedSamples<DATA_MPA> samples_mpa = m_dtcMountingPointAsset->readAlive();
|
|
for (const LOANED_DATA_MPA &mpa : samples_mpa)
|
|
{
|
|
if (mpa.data().structureElementId() == structureElementId)
|
|
return mpa.data().assetId();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------
|
|
int DtcImplCustom::getStructueElementIdFromAssetId(int assetId) const
|
|
{
|
|
|
|
using DATA_MPA = InfrastructureManagement::MountingPointAsset;
|
|
using LOANED_DATA_MPA = rti::sub::LoanedSample<DATA_MPA>;
|
|
|
|
dds::sub::LoanedSamples<DATA_MPA> samples_mpa = m_dtcMountingPointAsset->readAlive();
|
|
for (const LOANED_DATA_MPA &mpa : samples_mpa)
|
|
{
|
|
DEBUG_LOG(m_logger) << "mpa.data().assetId()=" << mpa.data().assetId()
|
|
<< " assetId=" << assetId
|
|
<< " mpa.data().structureElementId()=" << mpa.data().structureElementId();
|
|
if (mpa.data().assetId() == assetId)
|
|
return mpa.data().structureElementId();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
QMap<int, MainFootprint> DtcImplCustom::getFootprintsByExerciseId(int exerciseId)
|
|
{
|
|
QMap<int, MainFootprint> footprints;
|
|
|
|
const auto &buildings = mainStructureElements();
|
|
for (const auto &building : buildings)
|
|
{
|
|
int mseId = building.id();
|
|
if (isElementAssignedToExercise(building, exerciseId))
|
|
footprints.insert(mseId, mainFootprint(mseId));
|
|
}
|
|
|
|
return footprints;
|
|
}
|
|
|
|
QMap<int, QPolygonF> DtcImplCustom::getUtmFootprintsByExerciseId(int exerciseId, int &zone, bool isGroundLevel)
|
|
{
|
|
QMap<int, QPolygonF> footprints;
|
|
DEBUG_LOG(m_logger) << "getUtmFootprintsByExerciseId exerciseId=" << exerciseId;
|
|
|
|
const auto &buildings = mainStructureElements();
|
|
for (const auto &building : buildings)
|
|
{
|
|
const int mseId = building.id();
|
|
const MainStructureElement &mse = mainStructureElement(mseId);
|
|
DEBUG_LOG(m_logger) << "mseId: " << mseId;
|
|
if (isElementAssignedToExercise(building, exerciseId))
|
|
{
|
|
// skip Bridges:
|
|
const std::vector<InfrastructureManagement::StructureElement> &elementsRef = mse.elements();
|
|
// per definition, frontElement contains StructureElementType:
|
|
if (elementsRef.empty() ||
|
|
(elementsRef.front().structureElementTypeId() != InfrastructureManagement::StructureElementType_def::Building)
|
|
)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Footprint: " << mseId << ", skip due to StructureElementType != Building";
|
|
continue;
|
|
}
|
|
// END skip Bridges:
|
|
|
|
const QPolygonF &footprintUtm = getUtmFootprintById(mseId, zone, isGroundLevel);
|
|
if (footprintUtm.isEmpty())
|
|
{
|
|
INFO_LOG(m_logger) << "getUtmFootprintsByExerciseId, mseId " << mseId
|
|
<< " skip since footprintUtm is empty";
|
|
continue;
|
|
}
|
|
|
|
footprints.insert(mseId, footprintUtm);
|
|
DEBUG_LOG(m_logger) << "getUtmFootprintsByExerciseId footprints.insert mseId=" << mseId;
|
|
}
|
|
}
|
|
DEBUG_LOG(m_logger) << "getUtmFootprintsByExerciseId footprints.size=" << footprints.size();
|
|
return footprints;
|
|
}
|
|
|
|
// returns absolut utm positions of the footprint
|
|
QPolygonF DtcImplCustom::getUtmFootprintById(int mseId, int &zoneOut, bool isGroundLevel)
|
|
{
|
|
// attention: zone is just _out_ variable, not _in_ variable!!!
|
|
return d->mainFootPrintCacheGroundLevel.getUtmFootprintById(mseId, isGroundLevel, zoneOut);
|
|
|
|
//---------------
|
|
|
|
// const MainStructureElement &mse = mainStructureElement(mseId);
|
|
// if (mse.id() != mseId)
|
|
// return {};
|
|
|
|
// const MainFootprint &mf = mainFootprint(mseId);
|
|
// if (mf.id() != mseId)
|
|
// return {};
|
|
|
|
// const std::vector<InfrastructureManagement::FootprintElement> &mfElements = mf.elements();
|
|
|
|
// // insert all Points to poly
|
|
// QPolygonF poly;
|
|
// poly.reserve(mfElements.size());
|
|
// DEBUG_LOG(m_logger) << "mseId: " << mseId << " isGroundLevel: " << isGroundLevel;
|
|
// for (const InfrastructureManagement::FootprintElement &element : qAsConst(mfElements))
|
|
// {
|
|
// // maybe this is easier?
|
|
// // // if different, continue
|
|
// // if (isGroundLevel != element.isGroundLevel())
|
|
// // continue;
|
|
|
|
// if (isGroundLevel && !element.isGroundLevel())
|
|
// continue;
|
|
// else if (!isGroundLevel && element.isGroundLevel())
|
|
// continue;
|
|
|
|
// const auto &relPos = element.relPosition();
|
|
// DEBUG_LOG(m_logger) << "relPos: " << relPos.offsetX() << ", " << relPos.offsetY() << ", " << relPos.offsetZ();
|
|
// // maybe this is easier? DEBUG_LOG(m_logger) << "relPos: " << relPos;
|
|
// poly.push_back(QPointF(relPos.offsetX(), relPos.offsetY()));
|
|
// }
|
|
|
|
// // Get other footprint if groundLevel footprint is not available
|
|
// if (poly.isEmpty() && isGroundLevel)
|
|
// {
|
|
// for (const InfrastructureManagement::FootprintElement &element : qAsConst(mfElements))
|
|
// {
|
|
// const auto &relPos = element.relPosition();
|
|
// poly.push_back(QPointF(relPos.offsetX(), relPos.offsetY()));
|
|
// }
|
|
// }
|
|
|
|
// // rotate poly
|
|
// QTransform trans;
|
|
// trans.rotate(mse.angle());
|
|
// poly = trans.map(poly);
|
|
|
|
// const auto utm = LtsCoordTrans::UtmCoordinate::fromGeographic(QPointF(mse.geoPosition().lon(), mse.geoPosition().lat()), zone);
|
|
// zone = utm.zone;
|
|
// const QPointF utmFpPosition(utm.x, utm.y);
|
|
|
|
// QPolygonF retPolyUtm;
|
|
// retPolyUtm.reserve(poly.size());
|
|
// for (const QPointF &point : qAsConst(poly))
|
|
// {
|
|
// const QPointF finalUtmPoint(utmFpPosition + point);
|
|
// retPolyUtm.push_back(finalUtmPoint);
|
|
// DEBUG_LOG(m_logger) << "utmPoint x: " << finalUtmPoint.x() << " utmPoint.y : " << finalUtmPoint.y();
|
|
// }
|
|
|
|
// return retPolyUtm;
|
|
}
|
|
|
|
|
|
// returns all building IDs that have an intersection with the area under the polygon and are assigned to the specified exercise.
|
|
// Parameter: completeEnclosed true = Only buildings that are completely enclosed by the polygon are taken into account.
|
|
// false = All buildings that are completely enclosed by the polygon and that have an overlap with the polygon are taken into account.
|
|
QVector <int> DtcImplCustom::getBuildingByPolygon(int exerciseId, const QPolygonF &polygon, bool completeEnclosed, bool isGroundLevel)
|
|
{
|
|
DEBUG_LOG(m_logger) << "getBuildingByPolygon execiseId=" << exerciseId
|
|
<< " polygon.size=" << polygon.size()
|
|
<< " completeEnclosed=" << completeEnclosed;
|
|
QVector <int> result;
|
|
|
|
QPolygonF polygonUtm;
|
|
polygonUtm.reserve(polygon.size());
|
|
|
|
// Convert Form to UTM
|
|
int zone = -1;
|
|
for (const QPointF &point : qAsConst(polygon))
|
|
{
|
|
auto utm = LtsCoordTrans::UtmCoordinate::fromGeographic(point, zone);
|
|
DEBUG_LOG(m_logger) << "geo=" << point.x() << "/" << point.y()
|
|
<< " utm=" << utm.x << "/" << utm.y
|
|
<< " zone=" << zone;
|
|
polygonUtm.append(QPointF(utm.x, utm.y));
|
|
}
|
|
|
|
|
|
|
|
const QMap<int, QPolygonF> &buildingPoygons = getUtmFootprintsByExerciseId(exerciseId, zone, isGroundLevel);
|
|
DEBUG_LOG(m_logger) << "buildingPoygons.size=" << buildingPoygons.size();
|
|
DEBUG_LOG(m_logger) << "zone: " << zone;
|
|
|
|
for (auto footprintPolygon = buildingPoygons.cbegin(), end = buildingPoygons.cend(); footprintPolygon != end; ++footprintPolygon)
|
|
{
|
|
DEBUG_LOG(m_logger) << "key=" << footprintPolygon.key();
|
|
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
|
|
if (polygonUtm.intersected(footprintPolygon.value()).isClosed())
|
|
#else
|
|
if (polygonUtm.intersects(footprintPolygon.value()))
|
|
#endif
|
|
{
|
|
bool appendToResult = true;
|
|
DEBUG_LOG(m_logger) << "getBuildingByPolygon Append Building id=" << footprintPolygon.key();
|
|
if (completeEnclosed)
|
|
{
|
|
const QPolygonF &footprintPolygonRef = footprintPolygon.value();
|
|
for (const QPointF &fpPoint : qAsConst(footprintPolygonRef))
|
|
{
|
|
if (!polygonUtm.containsPoint(fpPoint, Qt::OddEvenFill))
|
|
{
|
|
DEBUG_LOG(m_logger) << "!polygonUtm.containsPoint"
|
|
<< " point=" << fpPoint.x() << "/" << fpPoint.y();
|
|
appendToResult = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DEBUG_LOG(m_logger) << " appendToResult=" << appendToResult;
|
|
if (appendToResult)
|
|
{
|
|
DEBUG_LOG(m_logger) << " appendToResult=" << appendToResult
|
|
<< " key=" << footprintPolygon.key();
|
|
result.append(footprintPolygon.key());
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// returns building ID surrounds the polygon and is assigned to the specified exercise.
|
|
// returns -1 if no building found
|
|
int DtcImplCustom::getSurroundingBuildingByPolygon(int exerciseId, const QPolygonF &polygon, bool isGroundLevel)
|
|
{
|
|
bool completeEnclosed = true;
|
|
DEBUG_LOG(m_logger) << "getSurroundingBuildingByPolygon execiseId=" << exerciseId
|
|
<< " polygon.size=" << polygon.size()
|
|
<< " completeEnclosed=" << completeEnclosed;
|
|
QPolygonF polygonUtm;
|
|
polygonUtm.reserve(polygon.size());
|
|
|
|
// Convert Form to UTM
|
|
int zone = -1;
|
|
for (const QPointF &point : qAsConst(polygon))
|
|
{
|
|
auto utm = LtsCoordTrans::UtmCoordinate::fromGeographic(point, zone);
|
|
DEBUG_LOG(m_logger) << "geo=" << point.x() << "/" << point.y()
|
|
<< " utm=" << utm.x << "/" << utm.y;
|
|
polygonUtm.append(QPointF(utm.x, utm.y));
|
|
}
|
|
const QMap<int, QPolygonF> &buildingPoygons = getUtmFootprintsByExerciseId(exerciseId, zone, isGroundLevel);
|
|
DEBUG_LOG(m_logger) << "buildingPoygons.size=" << buildingPoygons.size();
|
|
DEBUG_LOG(m_logger) << "zone: " << zone;
|
|
|
|
// loop over all buildings
|
|
for (auto footprintPolygon = buildingPoygons.cbegin(), end = buildingPoygons.cend(); footprintPolygon != end; ++footprintPolygon)
|
|
{
|
|
DEBUG_LOG(m_logger) << "key=" << footprintPolygon.key();
|
|
for (int i = 0; i < footprintPolygon.value().size(); i++)
|
|
DEBUG_LOG(m_logger) << " value=" << footprintPolygon.value()[i].x() << "/" << footprintPolygon.value()[i].y();
|
|
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
|
|
if (polygonUtm.intersected(footprintPolygon.value()).isClosed())
|
|
#else
|
|
if (polygonUtm.intersects(footprintPolygon.value()))
|
|
#endif
|
|
{
|
|
bool appendToResult = true;
|
|
DEBUG_LOG(m_logger) << "getBuildingByPolygon Append Building id=" << footprintPolygon.key();
|
|
if (completeEnclosed)
|
|
{
|
|
for (const QPointF &fpPoint : qAsConst(polygonUtm))
|
|
{
|
|
if (!footprintPolygon.value().containsPoint(fpPoint, Qt::OddEvenFill))
|
|
{
|
|
DEBUG_LOG(m_logger) << "!footprintPolygonRef.containsPoint"
|
|
<< " point=" << fpPoint.x() << "/" << fpPoint.y();
|
|
appendToResult = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DEBUG_LOG(m_logger) << " appendToResult=" << appendToResult;
|
|
if (appendToResult)
|
|
{
|
|
DEBUG_LOG(m_logger) << " appendToResult=" << appendToResult
|
|
<< " key=" << footprintPolygon.key();
|
|
return footprintPolygon.key();
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*!
|
|
* \brief DtcImplCustom::getBuildingIdAtPosition
|
|
* \param exerciseId
|
|
* \param utmPos
|
|
* \param isGroundLevel
|
|
* \return
|
|
*/
|
|
int DtcImplCustom::getBuildingIdAtPosition(int exerciseId, const QPointF &utmPos, bool isGroundLevel)
|
|
{
|
|
int zone = -1;
|
|
int bldId = -1;
|
|
const QMap<int, QPolygonF> &buildingPoygons = getUtmFootprintsByExerciseId(exerciseId, zone, isGroundLevel);
|
|
for (auto bldFootPrint = buildingPoygons.cbegin(), end = buildingPoygons.cend(); bldFootPrint != end; ++bldFootPrint)
|
|
{
|
|
const QPolygonF &bldUtmPolygon = bldFootPrint.value();
|
|
if (bldUtmPolygon.containsPoint(utmPos, Qt::OddEvenFill))
|
|
{
|
|
bldId = bldFootPrint.key();
|
|
break;
|
|
}
|
|
}
|
|
return bldId;
|
|
}
|
|
|
|
// The floors list is sorted according to height.
|
|
QVector <int> DtcImplCustom::getFloorIdsFromBuilding(int buildingId)
|
|
{
|
|
QVector <int> floorIds;
|
|
QList <StructureElement> floors = getFloorsFromBuilding(buildingId);
|
|
floorIds.reserve(floors.size());
|
|
for (int i = 0; i < floors.size(); i++)
|
|
floorIds.append(floors.at(i).id());
|
|
return floorIds;
|
|
}
|
|
|
|
bool structureElementHeightComparator(const StructureElement &a, const StructureElement &b)
|
|
{
|
|
return a.relPosition().offsetZ() < b.relPosition().offsetZ();
|
|
}
|
|
|
|
QList <StructureElement> DtcImplCustom::getFloorsFromBuilding(int buildingId)
|
|
{
|
|
QList <StructureElement> floors;
|
|
const MainStructureElement mse = mainStructureElement(buildingId);
|
|
// Determine all floor heights
|
|
if (mse.id() > 0)
|
|
{
|
|
for (const StructureElement &elem : mse.elements())
|
|
{
|
|
if (elem.structureElementTypeId() == InfrastructureManagement::StructureElementType::Floor)
|
|
{
|
|
DEBUG_LOG(m_logger) << "getFloorsFromBuilding append "
|
|
<< " id=" << elem.id()
|
|
<< " Z=" << elem.relPosition().offsetZ();
|
|
floors.append(elem);
|
|
}
|
|
}
|
|
}
|
|
// put the floor heights in the correct order
|
|
|
|
std::sort(floors.begin(), floors.end(), structureElementHeightComparator);
|
|
return floors;
|
|
}
|
|
|
|
double DtcImplCustom::getHalfFloorHeight(int buildingId, int floorId)
|
|
{
|
|
QList <StructureElement> floorHeights = getFloorsFromBuilding(buildingId);
|
|
DEBUG_LOG(m_logger) << "getHalfFloorHeight"
|
|
<< " buildingId=" << buildingId
|
|
<< " floorId=" << floorId
|
|
<< " floorHeights.size=" << floorHeights.size();
|
|
|
|
// Determine the height of each floor. The specified z-value is the height of the floor
|
|
for (int i = 0; i < floorHeights.size(); i++)
|
|
{
|
|
DEBUG_LOG(m_logger) << "i=" << i
|
|
<< " id= " << floorHeights[i].id()
|
|
<< " offsetZ()=" << floorHeights[i].relPosition().offsetZ();
|
|
if (floorHeights[i].id() == floorId)
|
|
{
|
|
if (floorHeights.size() > i + 1)
|
|
return (floorHeights[i].relPosition().offsetZ() + floorHeights[i + 1].relPosition().offsetZ()) / 2.0;
|
|
else
|
|
return floorHeights[i].relPosition().offsetZ() + 2.0;
|
|
}
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
QVector <int> DtcImplCustom::getRoomIdsFromFloorId(int buildingId, int floorId)
|
|
{
|
|
DEBUG_LOG(m_logger) << "getRoomIdsFromFloorId "
|
|
<< " buildingId=" << buildingId
|
|
<< " floorId=" << floorId;
|
|
|
|
QVector <int> rooms;
|
|
const MainStructureElement mse = mainStructureElement(buildingId);
|
|
rooms.reserve(mse.elements().size());
|
|
// Determine all floor heights
|
|
if (mse.id() > 0)
|
|
{
|
|
for (const StructureElement &elem : mse.elements())
|
|
{
|
|
std::vector< int32_t > path = elem.path();
|
|
|
|
if (std::find(path.begin(), path.end(), floorId) != path.end())
|
|
if (elem.structureElementTypeId() == InfrastructureManagement::StructureElementType::Room)
|
|
{
|
|
DEBUG_LOG(m_logger) << " rooms.append=" << elem.id();
|
|
rooms.append(elem.id());
|
|
}
|
|
}
|
|
}
|
|
return rooms;
|
|
}
|
|
|
|
QVector <int> DtcImplCustom::getBuildingIdsByExercise ( int exerciseId)
|
|
{
|
|
QVector <int> result;
|
|
|
|
|
|
const auto &buildings = mainStructureElements();
|
|
for (const auto &building : buildings)
|
|
{
|
|
if (isElementAssignedToExercise(building, exerciseId))
|
|
result.append(building.id());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
QByteArray DtcImplCustom::getVulnerabilityModelData( int buildingId)
|
|
{
|
|
const MainStructureElement &mse = mainStructureElement(buildingId);
|
|
if (mse.id() != buildingId)
|
|
{
|
|
WARNING_LOG(m_logger) << "mainStructureElement not found, id/buildingId = " << buildingId;
|
|
return {};
|
|
}
|
|
|
|
static const QString optPath = QStringLiteral("/opt/BuildingModels/StaticMeshes/");
|
|
const QString &vulnerabilityModelFilename = optPath + QStringLiteral("%1.flt.VWM_Building.xml").arg(QString::fromStdString(mse.name()));
|
|
|
|
QFile f(vulnerabilityModelFilename);
|
|
if (!f.open(QIODevice::ReadOnly))
|
|
{
|
|
WARNING_LOG(m_logger) << "Could not open file '" << vulnerabilityModelFilename << "' for reading: " << f.errorString();
|
|
}
|
|
|
|
QByteArray dataBa = f.readAll();
|
|
return dataBa;
|
|
}
|
|
|
|
|
|
} // namespace Interface
|
|
} // namespace InfrastructureManagement
|