Files
qt5-legatus-legacy/Lts/Proxies/Buildings/BuildingControlUnit/VWM/vwm_xml_reader.cpp
T
2026-08-13 18:33:10 +02:00

347 lines
13 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Read all xml config files
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, SLSA, 2013-03-05
*/
#include "vwm_xml_reader.h"
#include "vwm_building_room_geometry.h"
#include <logger.h>
#include <QFile>
#include <QDomDocument>
#include <QSet>
#include <bcu_xml_reader.h>
namespace BuildingControlUnit
{
namespace VWM
{
namespace XmlReader
{
static NGL::INGLLogger &logger()
{
return BuildingControlUnit::getLogger("XmlReader");
}
static Charge parseCharge(const QDomElement &domCharge)
{
Charge charge;
charge.id = getTagText(domCharge, QStringLiteral("Id")).toInt();
charge.chargeTypeId = getTagText(domCharge, QStringLiteral("ChargeTypeId")).toInt();
charge.destructiveFactor = getTagText(domCharge, QStringLiteral("DestructiveFactor")).toInt();
charge.penetrationEffect = getTagText(domCharge, QStringLiteral("PenetrationEffect")).toInt();
charge.effectSoundId = getTagText(domCharge, QStringLiteral("EffectSound")).toInt();
charge.difcueLight = getTagText(domCharge, QStringLiteral("DifcueLight")).toInt() != 0;
charge.difcuePyro = getTagText(domCharge, QStringLiteral("DifcuePyro")).toInt() != 0;
if (hasTagText(domCharge, QStringLiteral("showHitLine")))
charge.showHitLine = getTagText(domCharge, QStringLiteral("showHitLine")).toInt() != 0;
else
charge.showHitLine = true;
DEBUG_LOG(logger()) << "Charge: " << charge;
//if (charge.destructiveFactor <= 0)
// throw XmlReaderException(QStringLiteral("Destructive factor for charge %1 <= 0 which is not allowed!").arg(charge.id));
//if (charge.penetrationEffect < 0)
// throw XmlReaderException(QStringLiteral("Penetration effect for charge %1 < 0 which is not allowed!").arg(charge.id));
return charge;
}
bool readCharges(const QString &fn, QMap<int, Charge> &charges)
{
charges.clear();
const QDomElement domRoot = readFile(fn, QStringLiteral("Charges"));
if (domRoot.isNull())
return false;
QDomElement domChargeType = domRoot.firstChildElement(QStringLiteral("Charge"));
while (!domChargeType.isNull())
{
try
{
const Charge c = parseCharge(domChargeType);
charges.insert(c.chargeTypeId, c);
}
catch (const XmlReaderException &ex)
{
QString errorString = QLatin1String("Error reading charge type: ") + QLatin1String(ex.what());
ERROR_LOG(logger()) << errorString;
return false;
}
domChargeType = domChargeType.nextSiblingElement(domChargeType.tagName());
}
return true;
}
static LtsUtils::QPoint3D getCoord3D(const QDomElement &domCoord)
{
LtsUtils::QPoint3D ret;
ret.rx() = getTagText(domCoord, QStringLiteral("X")).toDouble();
ret.ry() = getTagText(domCoord, QStringLiteral("Y")).toDouble();
ret.rz() = getTagText(domCoord, QStringLiteral("Z")).toDouble();
// Ein Runden auf cm hat auch Nachteile:
// So kommt es vor, das Polygone (in mm) um lineare Abhängigkeiten reduziert
// werden können, aber wenn diese auf cm gerundet sind, nicht mehr!!!
// Siehe Lts/Proxies/Buildings/BuildingControlUnit/VWM/vwm_math_unit_test.cpp
/*static const QVector<LtsUtils::QPoint3D> polyBldg1103_205_5_ORG({
{11.639, 6.026, 5.412}, // idx=0
{11.639, 2.607, 5.513}, // idx=1 // problem: linear dependent -> wird erkannt
{11.639, 1.690, 5.540}, // idx=2
{14.659, 1.694, 5.539}, // idx=3
{14.659, 6.026, 5.412} // idx=4
});
static const QVector<LtsUtils::QPoint3D> polyBldg1103_205_5_ROUNDED({
{11.64, 6.03, 5.41}, // idx=0
{11.64, 2.61, 5.51}, // idx=1 // problem: linear dependent -> wird erkannt
{11.64, 1.69, 5.54}, // idx=2
{14.66, 1.69, 5.54}, // idx=3
{14.66, 6.03, 5.41} // idx=4
});
*/
// ret.setX( roundf(ret.x() * 100) / 100 );
// ret.setY( roundf(ret.y() * 100) / 100 );
// ret.setZ( roundf(ret.z() * 100) / 100 );
return ret;
}
static NeighbourRoom parseNeighbourRoom(const QDomElement &domNeighbour)
{
NeighbourRoom ret;
ret.setId(getTagText(domNeighbour, QStringLiteral("RoomId")).toInt());
ret.setTransitionFactor(getTagText(domNeighbour, QStringLiteral("TransitionFactor")).toDouble());
DEBUG_LOG(logger()) << " NeighbourRoom id=" << ret.id() << ", transitionFactor=" << ret.transitionFactor();
return ret;
}
static ExclusionZone parseExclusionZone(const QDomElement &domeExclusionZone)
{
ExclusionZone ret;
QVector<LtsUtils::QPoint3D> poly;
ret.setProtectiveFactor(getTagText(domeExclusionZone, QStringLiteral("ExclusionZoneProtectiveFactor")).toInt());
DEBUG_LOG(logger()) << " ExclusionZone protectiveFactor= " << ret.protectiveFactor();
QDomElement domExclusionZoneElement = domeExclusionZone.firstChildElement(QStringLiteral("ExclusionZoneElement"));
while (!domExclusionZoneElement.isNull())
{
poly.clear();
QDomElement domPolygonPoint = domExclusionZoneElement.firstChildElement(QStringLiteral("PolygonPoint"));
while (!domPolygonPoint.isNull())
{
poly += getCoord3D(domPolygonPoint);
domPolygonPoint = domPolygonPoint.nextSiblingElement(domPolygonPoint.tagName());
}
ret.elements() += poly;
domExclusionZoneElement = domExclusionZoneElement.nextSiblingElement(domExclusionZoneElement.tagName());
}
return ret;
}
static OuterWall parseOuterWall(const QDomElement &domOuterWall)
{
OuterWall ret;
QVector<LtsUtils::QPoint3D> poly;
// try {
// }
// catch (...)
// {
// ERROR_LOG(logger()) << " OuterWall protectiveFactor set to Default = 200 for bldg_3100";
// ret.setProtectiveFactor(0);
// }
ret.setProtectiveFactor(getTagText(domOuterWall, QStringLiteral("OuterWallProtectiveFactor")).toInt());
DEBUG_LOG(logger()) << " OuterWall protectiveFactor=" << ret.protectiveFactor();
{
DEBUG_LOG(logger()) << " OuterWallAreaElements:";
QDomElement domPolygonPoints = domOuterWall.firstChildElement(QStringLiteral("OuterWallAreaElement"));
while (!domPolygonPoints.isNull())
{
poly.clear();
QDomElement domPolygonPoint = domPolygonPoints.firstChildElement(QStringLiteral("PolygonPoint"));
while (!domPolygonPoint.isNull())
{
poly += getCoord3D(domPolygonPoint);
domPolygonPoint = domPolygonPoint.nextSiblingElement(domPolygonPoint.tagName());
}
ret.elements() += poly;
domPolygonPoints = domPolygonPoints.nextSiblingElement(domPolygonPoints.tagName());
}
}
{
QDomElement domExclusionZones = domOuterWall.firstChildElement(QStringLiteral("ExclusionZones"));
QDomElement domExclusionZone = domExclusionZones.firstChildElement(QStringLiteral("ExclusionZone"));
DEBUG_LOG(logger()) << " ExclusionZones:";
while (!domExclusionZone.isNull())
{
ret.exclusionZones() += parseExclusionZone(domExclusionZone);
domExclusionZone = domExclusionZone.nextSiblingElement(domExclusionZone.tagName());
}
}
return ret;
}
static Room parseRoom(const QDomElement &domRoom)
{
Room ret;
ret.setId(getTagText(domRoom, QStringLiteral("RoomId")).toInt());
DEBUG_LOG(logger()) << "Parsing Room id=" << ret.id();
{
QDomElement domNeighbours = domRoom.firstChildElement(QStringLiteral("NeighborRooms"));
QDomElement domNeighbour = domNeighbours.firstChildElement(QStringLiteral("NeighborRoom"));
while (!domNeighbour.isNull())
{
const NeighbourRoom n = parseNeighbourRoom(domNeighbour);
auto itNeighbourRoom = ret.neighbours().find(n.id()); // for sanity
if (itNeighbourRoom.value().id() == n.id())
{
WARNING_LOG(logger()) << "Room with id " << n.id()
<< " listed twice neighbour of room " << ret.id();
}
ret.neighbours().insert(n.id(), n);
domNeighbour = domNeighbour.nextSiblingElement(domNeighbour.tagName());
}
}
{
QDomElement domOuterWalls = domRoom.firstChildElement(QStringLiteral("RoomOuterWalls"));
QDomElement domOuterWall = domOuterWalls.firstChildElement(QStringLiteral("OuterWall"));
while (!domOuterWall.isNull())
{
const OuterWall w = parseOuterWall(domOuterWall);
ret.outerWalls() += w;
domOuterWall = domOuterWall.nextSiblingElement(domOuterWall.tagName());
}
}
return ret;
}
bool readBuilding(const QDomElement &domRoot, Building &cfg)
{
if (domRoot.isNull())
return false;
cfg.rooms().clear();
try
{
cfg.setName(getTagText(domRoot, QStringLiteral("BuildingName")));
cfg.setModelId(getTagText(domRoot, QStringLiteral("ModelId")).toInt());
cfg.setBuildingProtectionLevel(getTagText(domRoot, QStringLiteral("BuildingProtectionLevel")).toDouble());
cfg.setExclusionZoneProtectionLevel(getTagText(domRoot, QStringLiteral("ExclusionZoneProtectionLevel")).toInt());
cfg.setOuterWallProtectionLevel(getTagText(domRoot, QStringLiteral("OuterWallProtectionLevel")).toInt());
DEBUG_LOG(logger()) << "**********************";
DEBUG_LOG(logger()) << "*** BUILDING: ***";
DEBUG_LOG(logger()) << "**********************";
DEBUG_LOG(logger()) << "readBuilding name=" << cfg.name();
DEBUG_LOG(logger()) << "readBuilding modelId=" << cfg.modelId();
DEBUG_LOG(logger()) << "readBuilding buildingProtectionLevel=" << cfg.buildingProtectionLevel();
DEBUG_LOG(logger()) << "readBuilding exclusionZoneProtectionLevel=" << cfg.exclusionZoneProtectionLevel();
DEBUG_LOG(logger()) << "readBuilding outerWallProtectionLevel=" << cfg.outerWallProtectionLevel();
QDomElement domRooms = domRoot.firstChildElement(QStringLiteral("Rooms"));
QDomElement domRoom = domRooms.firstChildElement(QStringLiteral("Room"));
while (!domRoom.isNull())
{
try
{
const Room r = parseRoom(domRoom);
cfg.rooms().insert(r.id(), r);
}
catch (const XmlReaderException &ex)
{
QString errorString = QLatin1String("Error reading room config: ") + QLatin1String(ex.what());
ERROR_LOG(logger()) << errorString;
return false;
}
domRoom = domRoom.nextSiblingElement(domRoom.tagName());
}
}
catch (const XmlReaderException &ex)
{
QString errorString = QLatin1String("Error reading BSMConfiguration: ") + QLatin1String(ex.what());
ERROR_LOG(logger()) << errorString;
return false;
}
QMap<int, Room> rooms = cfg.rooms();
QMap<int, Room>::iterator room = rooms.begin();
while (room != rooms.end())
{
auto itNeighbourRoom = room.value().neighbours().find(room.value().id());
if (room.value().id() == itNeighbourRoom.value().id())
{
WARNING_LOG(logger()) << "Room with id " << itNeighbourRoom.value().id()
<< " was defined as neighbour of itself!";
}
QMap<int, NeighbourRoom> &neighbours = room.value().neighbours();
QMap<int, NeighbourRoom>::iterator neighbour = neighbours.begin();
while (neighbour != neighbours.end())
{
auto itRoom = rooms.find(neighbour.value().id());
if (neighbour.value().id() != itRoom.value().id())
{
WARNING_LOG(logger()) << "Could not find room with id " << neighbour.value().id()
<< " which was defined as neighbour of room " << room.value().id();
}
++neighbour;
}
++room;
}
return true;
}
bool readBuilding(const QString &fn, Building &cfg)
{
const QDomElement domRoot = readFile(fn, QStringLiteral("BuildingVulnerability"));
return readBuilding(domRoot, cfg);
}
bool readBuilding(const QByteArray &data, Building &cfg)
{
QDomDocument doc;
QString errorMsg;
int errorLine;
int errorColumn;
if (!doc.setContent(data, &errorMsg, &errorLine, &errorColumn))
{
ERROR_LOG(logger()) << "Line=" << errorLine << ", Column=" << errorColumn << ": " << errorMsg;
return false;
} // if
const QDomElement domRoot = doc.documentElement();
return readBuilding(domRoot, cfg);
}
bool readBuildingGeometry(const QDomElement &domRoot, BuildingRoomGeometry &bldgGeometry)
{
if (domRoot.isNull())
return false;
const QDomElement &domHdr = domRoot.firstChildElement(QStringLiteral("Header"));
const QDomElement &domGroup = domHdr.firstChildElement(QStringLiteral("Group"));
return bldgGeometry.init(domGroup);
}
bool readBuildingGeometry(const QString &fn, BuildingRoomGeometry &bldgGeometry)
{
const QDomElement domRoot = readFile(fn, QStringLiteral("STREIF"));
return readBuildingGeometry(domRoot, bldgGeometry);
}
} // namespace XmlReader
} // namespace VWM
} // namespace BuildingControlUnit