/** * @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 #include #include #include #include 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 &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 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 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 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 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 rooms = cfg.rooms(); QMap::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 &neighbours = room.value().neighbours(); QMap::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